• 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.

Mystery loop

Status
Not open for further replies.

ibwev

Member
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:
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:
while rx.ready():
. However, when I uncomment
Code:
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:
 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:
 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:
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:
#!/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()
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top