How can I use Python Threading with parameter passing between threads?

1. Summarize the problem I am working with Python 2 and a Raspberry Pi 4 running Raspbian Buster. Trying to limit the speed at which my program reads sensor data from my Android device that is using Sockets to send its data via UDP connection. IE: I built this as a small laser trip wire app and to start I wanted to increment a count accumulator every time the sensor value dropped below a certain number, indicating a tripped laser. However, the data reads in so fast that count is incremented many times for each time the sensor level drops below. How can I only read the UDP data every X seconds?

2. Describe what you’ve tried

  • I have tried time.sleep() but from what I have read, this is a blocking function and after testing, it does indeed stop my program being able to update the sensor data over the UDP socket
  • I have tried Threading but I cannot figure out how to pass in the sensor data from one thread into another.
  • I researched join() but the technical documentation I happened across wasn't very beginner friendly.
  • Some posts here recomend setting up a client/server interface, but I am not sure how to do that either.

3. When appropriate, show some code Here is my current progress for a threaded solution. I am using the android app called SensorUDP and with the Ambient Light sensor on and Send Data activated this program will read in the UDP data and print it. even without the UDP data it will still run the count thread.

import socket
from struct import *
import time
import threading

#We have 0-92 over a 1024 byte buffer representing distinct
#sensors being sent over UDP from my android smartphone
#this test program im only pulling byte 56 for Ambient Light sensing
#a laser shining into my phones sensor has 30,000-50,000 lums so anything
#less then that range must mean the laser was tripped


#UDP = SOCK_DGRAM, AF_INET = Internet
UDP_IP = "192.168.1.149" #my rpi4 address
print "Receiver IP: ", UDP_IP
UDP_PORT = 5000 #arbitrary for now but needs to match my androids broadcast
print "Port: ", UDP_PORT
sock = socket.socket(socket.AF_INET, # Internet
                    socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT)) #complete the binding

running = True
count = 0
laserOn = 1000 #using a low lums to test so I dont have to use laser every time
aLight = 0
result_available = threading.Event() #.set() this when the data is recieved
threadTimer = 5

def calcAmbLight():

# Continuously read from the UDP socket
   
    while running:
       
        data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
        #the data from the app Im using to push the sensor data needs to
        #be unpacked
        aLight = "%.1f" %unpack_from ('!f', data, 56)
        print ("Ambient Light = ", aLight)

def displayCount():
    count = 0
    while running:
        time.sleep(1)
        #how to pass aLight into this thread from the other thread?
        if aLight < laserOn:
            count = count + 1

        print("Current aLight: ",aLight)
        print("Current Count: ", count)
       
if __name__ == '__main__':
              
    #create a basicthread to run calcAmbLight
    calcAmb = threading.Thread(target= calcAmbLight)
    calcAmb.start()
   
    dispCount = threading.Thread(target = displayCount)
    dispCount.start()

The issue with the current setup is due to the fact that you are not declaring aLight as global in calcAmbLight(). Declaring it as a global variable should allow this to work.

def calcAmbLight():
    global aLight  # Set the global aLight, instead of a local stack variable

    while running:

        data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
        #the data from the app Im using to push the sensor data needs to
        #be unpacked
        aLight = "%.1f" %unpack_from ('!f', data, 56)
        print ("Ambient Light = ", aLight)