1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Mystery loop

Discussion in 'Microcontrollers' started by ibwev, Jan 30, 2017.

  1. ibwev

    ibwev Member

    Joined:
    Dec 5, 2010
    Messages:
    188
    Likes:
    0
    Location:
    Shreveport, Louisiana
    When I power an RF Transmitter attached to an aduino, I am successfully sending text messages via an RF Receiver connected to a Raspberry Pi that has a GSM module attached to it. The RF sniffing code on the Raspberry Pi waits for a transmission from the RF Transmitter before sending a text. However, once the sniffing code receives the first signal, it doesn't stop sending text messages even after the transmitter has been powered off. If I comment out the line
    Code (text):
    sendSMS1.sms()
    the code works as expected. In other words, when I power off the transmitter and have the above line commented out, the sniffing program does not enter the loop at
    Code (text):
    while rx.ready():
    . However, when I uncomment
    Code (text):
    sendSMS1.sms()
    , run the program, and turn the transmitter on to send one text and immediately power it off , it continuously loops this section (line 369 - 382 of vw.py).
    Code (text):
     if (letter[len(letter) - 1]) == "L": #capture lastletter of list
                    print("The letter is L")
                    print(letter + "before send")
                    sendSMS1.sms()    #send the text
                    i += 1
                    l = list(letter)  #strings are immutable, convert to a list
                    del(l[len(letter) - 1]) #delete the last letter of the list
                    letter = "".join(l)  #assign the list of chars to the string letter
                    print(letter)
                    print(i)
     
    Somehow, when the transmitter is cycled on and off one time, the char "L" is re-appended to the string even though it is successfully removed after sending the text. I assume I have broken some sort of importing rule when I call
    Code (text):
     sendSMS1.sms()
    but I have tried numerous modifications and can't seem to figure it out. Any help solving this problem would be much appreciated.

    Text Code (sendSMS1.py)
    Code (text):
    import os
    import serial
    from time import sleep, time
    from string import replace
    from globalParVar import *
    from agsm2_064_hw_control import *
    from agsm_Serial_Lib import *
    from agsm_Basic_Lib import *
    from agsm_SMS_Lib import *





    def sms():    #when importing this module, the desired code must be in a definition
        message="Hi!\r\nThis message has been sent from the a-gsm v2.064 shield connected with my RPi board."
        destinationNumber="3185184930"#usually phone number with International prefix eg. +40 for Romania - in some networks you must use domestic numbers
        usePoweringControl = 1#change it to 0 if you do not want to control powerUP/powerDown the a-gsm board. In this case, please be sure the a-gsm board is powered UP(..see a-gsm_kickstart_v_x-yz.pdf) before run this utility  

        print "Light example - just send a SMS to a destination number"
        sleep(1)

        if not os.getuid() == 0:
           print("please use root privileges! try: \"sudo python yourPythonFileName.py\"")
           exit(0)

        if destinationNumber=="":
           print("No destination number has been set for your SMS!")
           print("Edit the file and set the destinationNumber in line 35\r\n")
           exit(0)

    # set SERIAL/USB communication section start
    # bellow chose value bw [SER] Serial /dev/ttyAMA0 or [USB] /dev/ttyUSB0
    # if module USB port maps to other port as /dev/ttyUSB1, just edit the moduleName_Serial_lib.py...
        serialCommunicationVia = SERIALCON      # OVERRIDE the default value loaded from globalParVar.py. here I use via SERIAL communication
        setSerialCom(serialCommunicationVia)    # set the current communication option
        startSerialCom()                        # open serial communication bw. RPi and a-gsm shield
    # set SERIAL/USB communication section end

    # set HARDWARE CONTROL setup & POWER ON section start        
        if usePoweringControl==1:
           hwControlSetup()                    # setup the RPi I/O ports

        sleep(2)#some delay...

        if usePoweringControl==1:
           poweron()

        sleep(1)
    # set HARDWARE CONTROL setup & POWER ON section end        

    # set MODEM STARTUP SETUP section start        
        setupMODEM()
    # set MODEM STARTUP SETUP section end        


    # MAIN PROGRAM section start        
        print "try to send a SMS...."

    #check AT command pdf for proper 129/145 parameter/number format usage
        res = sendSMS(destinationNumber, "129", message)#domestic format numbers
    #res = sendSMS(destinationNumber, "145", message)#international format numbers
        if res==0:
            print "SMS has been sent with succes"
    # MAIN PROGRAM section end        

    # stop SERIAL COMMUNICATION section start        
        stopSerialCom()                             # close modem communication
    # stop SERIAL COMMUNICATION section end        

    # HARDWARE CONTROL release & POWER OFF section start        
        if usePoweringControl==1:
           poweroff()                              #shutdown modem

        if usePoweringControl==1:
           hwControlRelease()                      # free GPIO
    # HARDWARE CONTROL release & POWER OFF section end        


        print("\r\n\r\nThat's all folks!\r\n")
    Sniffing Code (vw.py)
    Code (text):
    #!/usr/bin/env python
    """
    This module provides a 313MHz/434MHz radio interface compatible
    with the Virtual Wire library used on Arduinos.

    It has been tested between a Pi, TI Launchpad, and Arduino Pro Mini.
    """
    # 2014-08-14
    # vw.py

    import time
    import pigpio
    import sendSMS1

    MAX_MESSAGE_BYTES=77

    MIN_BPS=50
    MAX_BPS=10000

    _HEADER=[0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c]

    _CTL=3

    _SYMBOL=[
       0x0d, 0x0e, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
       0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34]


    def _sym2nibble(symbol):
       for nibble in range(16):
          if symbol == _SYMBOL[nibble]:
             return nibble
       return 0

    def _crc_ccitt_update(crc, data):

       data = data ^ (crc & 0xFF);

       data = (data ^ (data << 4)) & 0xFF;

       return (
                 (((data << 8) & 0xFFFF) | (crc >> 8)) ^
                  ((data >> 4) & 0x00FF) ^ ((data << 3) & 0xFFFF)
              )

    class tx():

       def __init__(self, pi, txgpio, bps=2000):
          """
          Instantiate a transmitter with the Pi, the transmit gpio,
          and the bits per second (bps).  The bps defaults to 2000.
          The bps is constrained to be within MIN_BPS to MAX_BPS.
          """
          self.pi = pi

          self.txbit = (1<<txgpio)

          if bps < MIN_BPS:
             bps = MIN_BPS
          elif bps > MAX_BPS:
             bps = MAX_BPS

          self.mics = int(1000000 / bps)

          self.wave_id = None

          pi.wave_add_new()

          pi.set_mode(txgpio, pigpio.OUTPUT)


       def _nibble(self, nibble):

          for i in range(6):
             if nibble & (1<<i):
                self.wf.append(pigpio.pulse(self.txbit, 0, self.mics))
             else:
                self.wf.append(pigpio.pulse(0, self.txbit, self.mics))

       def _byte(self, crc, byte):
          self._nibble(_SYMBOL[byte>>4])
          self._nibble(_SYMBOL[byte&0x0F])
          return _crc_ccitt_update(crc, byte)

       def put(self, data):
          """
          Transmit a message.  If the message is more than
          MAX_MESSAGE_BYTES in size it is discarded.  If a message
          is currently being transmitted it is aborted and replaced
          with the new message.  True is returned if message
          transmission has successfully started.  False indicates
          an error.
          """
          if len(data) > MAX_MESSAGE_BYTES:
             return False

          self.wf = []

          self.cancel()

          for i in _HEADER:
             self._nibble(i)

          crc = self._byte(0xFFFF, len(data)+_CTL)

          for i in data:

             if type(i) == type(""):
                v = ord(i)
             else:
                v = i

             crc = self._byte(crc, v)

          crc = ~crc

          self._byte(0, crc&0xFF)
          self._byte(0, crc>>8)

          self.pi.wave_add_generic(self.wf)

          self.wave_id = self.pi.wave_create()

          if self.wave_id >= 0:
             self.pi.wave_send_once(self.wave_id)
             return True
          else:
             return False


       def ready(self):
          """
          Returns True if a new message may be transmitted.
          """
          return not self.pi.wave_tx_busy()

       def cancel(self):
          """
          Cancels the wireless transmitter, aborting any message
          in progress.
          """
          if self.wave_id is not None:
             self.pi.wave_tx_stop()
             self.pi.wave_delete(self.wave_id)
             self.pi.wave_add_new()

          self.wave_id = None

    class rx():

       def __init__(self, pi, rxgpio, bps=2000):
          """
          Instantiate a receiver with the Pi, the receive gpio, and
          the bits per second (bps).  The bps defaults to 2000.
          The bps is constrained to be within MIN_BPS to MAX_BPS.
          """
          self.pi = pi
          self.rxgpio = rxgpio

          self.messages = []
          self.bad_CRC = 0

          if bps < MIN_BPS:
             bps = MIN_BPS
          elif bps > MAX_BPS:
             bps = MAX_BPS

          slack = 0.20
          self.mics = int(1000000 / bps)
          slack_mics = int(slack * self.mics)
          self.min_mics = self.mics - slack_mics       # Shortest legal edge.
          self.max_mics = (self.mics + slack_mics) * 4 # Longest legal edge.

          self.timeout =  8 * self.mics / 1000 # 8 bits time in ms.
          if self.timeout < 8:
             self.timeout = 8

          self.last_tick = None
          self.good = 0
          self.bits = 0
          self.token = 0
          self.in_message = False
          self.message = [0]*(MAX_MESSAGE_BYTES+_CTL)
          self.message_len = 0
          self.byte = 0

          pi.set_mode(rxgpio, pigpio.INPUT)

          self.cb = pi.callback(rxgpio, pigpio.EITHER_EDGE, self._cb)

       def _calc_crc(self):

          crc = 0xFFFF
          for i in range(self.message_length):
             crc = _crc_ccitt_update(crc, self.message[i])
          return crc

       def _insert(self, bits, level):

          for i in range(bits):

             self.token >>= 1

             if level == 0:
                self.token |= 0x800

             if self.in_message:

                self.bits += 1

                if self.bits >= 12: # Complete token.

                   byte = (
                      _sym2nibble(self.token & 0x3f) << 4 |
                      _sym2nibble(self.token >> 6))

                   if self.byte == 0:
                      self.message_length = byte

                      if byte > (MAX_MESSAGE_BYTES+_CTL):
                         self.in_message = False # Abort message.
                         return

                   self.message[self.byte] = byte

                   self.byte += 1
                   self.bits = 0

                   if self.byte >= self.message_length:
                      self.in_message = False
                      self.pi.set_watchdog(self.rxgpio, 0)

                      crc = self._calc_crc()

                      if crc == 0xF0B8: # Valid CRC.
                         self.messages.append(
                            self.message[1:self.message_length-2])
                      else:
                         self.bad_CRC += 1

             else:
                if self.token == 0xB38: # Start message token.
                   self.in_message = True
                   self.pi.set_watchdog(self.rxgpio, self.timeout)
                   self.bits = 0
                   self.byte = 0

       def _cb(self, gpio, level, tick):

          if self.last_tick is not None:

             if level == pigpio.TIMEOUT:

                self.pi.set_watchdog(self.rxgpio, 0) # Switch watchdog off.

                if self.in_message:
                   self._insert(4, not self.last_level)

                self.good = 0
                self.in_message = False

             else:

                edge = pigpio.tickDiff(self.last_tick, tick)

                if edge < self.min_mics:

                   self.good = 0
                   self.in_message = False

                elif edge > self.max_mics:

                   if self.in_message:
                      self._insert(4, level)

                   self.good = 0
                   self.in_message = False

                else:

                   self.good += 1

                   if self.good > 8:

                      bitlen = (100 * edge) / self.mics

                      if   bitlen < 140:
                         bits = 1
                      elif bitlen < 240:
                         bits = 2
                      elif bitlen < 340:
                         bits = 3
                      else:
                         bits = 4

                      self._insert(bits, level)

          self.last_tick = tick
          self.last_level = level

       def get(self):
          """
          Returns the next unread message, or None if none is avaiable.
          """
          if len(self.messages):
             return self.messages.pop(0)
          else:
             return None

       def ready(self):
          """
          Returns True if there is a message available to be read.
          """
          return len(self.messages)

       def cancel(self):
          """
          Cancels the wireless receiver.
          """
          if self.cb is not None:
             self.cb.cancel()
             self.pi.set_watchdog(self.rxgpio, 0)
          self.cb = None

    if __name__ == "__main__":

       import time

       import pigpio

       import vw

       RX=27
       TX=25

       BPS=900

       pi = pigpio.pi() # Connect to local Pi.

       rx = vw.rx(pi, RX, BPS) # Specify Pi, rx gpio, and baud.
       tx = vw.tx(pi, TX, BPS) # Specify Pi, tx gpio, and baud.

       msg = 0

       start = time.time()

       while (time.time()-start) < 300:

     #     msg += 1

     #     while not tx.ready():
    #         time.sleep(0.1)

    #      time.sleep(0.2)

     #     tx.put([48, 49, 65, ((msg>>6)&0x3F)+32, (msg&0x3F)+32])

    #      while not tx.ready():
    #         time.sleep(0.1)

     #     time.sleep(0.2)

    #      tx.put("Hello World #{}!".format(msg))

          i = 0  
          while rx.ready():
             print("immediately after while before join")
        letter = ("".join(chr (c) for c in rx.get())) #retrieve what was sent first 2 or 3 characters are preambles
        if (letter[len(letter) - 1]) == "L": #capture lastletter of list
            print("The letter is L")
            print(letter + "before send")
            sendSMS1.sms()    #send the text
            #time.sleep(60)  this does not help. Line does not execute until previous is finished
    #when executing sendSMS1.sms() this loop completes once the text is sent
    #I unplug the battery but code does not exit while loop and it somehow restores the string to remember the L
    #the code works as expected if I comment out the sendSMS1 command
            i += 1
            l = list(letter)  #strings are immutable, convert to a list
            del(l[len(letter) - 1]) #delete the last letter of the list
            letter = "".join(l)  #assign the list of chars to the string letter
            print(letter)
            print(i)
        else:
            print("failed")

       rx.cancel()
       tx.cancel()

       pi.stop()
     

Share This Page