Search code examples
pythontimegrovepi+

Separating time.sleep for different actions


fairly new to python here and trying to separate out the time.sleep function for several readings.

while True:
#read from a analog sensor on input 1
d= grovepi.analogRead(1)
#read from an analog sensor on input 2
a= grovepi.analogRead(2)
#read from an digital sensor on input 3
(t,h)=grovepi.dht(3,0)


#output the data
#print (datetime,time)
print('Timestamp: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now()))
print ("Noise:",d,"dB")
print ("Light:",a,"lux")
print ("Temperature:",t,"C")
print ("Humidity:",h,"rH")
grovelcd.setText("T:" + str(t) + " H:" + str(h) + " N:" + str(d)+ " L:" + str(a))

time.sleep(5)

What i would like is for the readings to be printed at different frequencies but still run simultaneously.

e.g.

print ("Noise:",d,"dB")
time.sleep(3)

and

print ("Light:",a,"lux")
time.sleep(5)

I understand this may be a simple syntactical issue but i haven't found a simple solution.

Many thanks


Solution

  • Here is a partial solution using threads:

    import threading
    import time
    import grovepi
    
    def take_analog_measurement(stop, lock, name, pin, units, period):
        while not stop.is_set():
            with lock:
                val = grovepi.analogRead(pin)
            print(name, ': ', val, units, sep='')
            time.sleep(period)
    
    def take_dht_measurement(stop, lock, pin, mtype, period):
        while not stop.is_set():
            with lock:
                temp, hum = grovepi.dht(pin, mtype)
            print('Temperature: ', temp, ' C\nHumidity: ', hum, ' rH', sep='')
            time.sleep(period)
    
    stop = threading.Event()
    grovepilock = threading.Lock()
    threads = []
    threads.append(threading.Thread(target=take_analog_measurement, args=(stop, grovepilock, 'Noise', 1, 'dB', 3)))
    threads.append(threading.Thread(target=take_analog_measurement, args=(stop, grovepilock, 'Light', 2, 'lux', 5)))
    threads.append(threading.Thread(target=take_dht_measurement, args=(stop, grovepilock, 3, 0, 7)))
    for thread in threads:
        thread.start()
    
    for thread in threads:
        try:
            thread.join()
        except KeyboardInterrupt:
            stop.set()
            thread.join()
    
    print('done')
    

    I don't have a GrovePi so I can't test it with the hardware, but I have done some simulated tests.

    This will read each sensor at the given frequency and output the value. The lock is used to protect grovepi since I am not sure if it is thread-safe. The event is used to signal all of the threads to stop (although they will have to wait until they wake up before they can actually stop).

    I don't know how you want to handle the grovelcd.setText when each variable changes at a different frequency. One possible solution might be another thread that uses a dictionary (and lock) shared with all of the sensor threads. Then the LCD would update on a period and use the data from the dictionary.