Python analog read only receives update per 20 ms

Hi, I am building a IR light sensor for chemical engineering purposes using an IR transistor and arduino uno(controlled by python). One of my designs uses capacitor discharge to measure the conductivity of the transistor. I used a infinite while loop to contiuously check whether the capacitor voltage is below a threshold, and then the discharge time can be found. Although the while loop can circulate and execute analog read() once per 5 us, I noticed that the values read using analog read() function only updates once per 20 ms. So the output I received is like: 5,5,5,5....(20ms)..,4,4,4,4......(20ms)..,3,3,3,....2,2,2....
Part of the code I use is:

a = True
while i<5:
     board.digital[12].write(1)
     time.sleep(3)
     board.digital[12].write(0)
     t1 = time.time()
     while a:
         read =analog_red.read()
         c_data[i][0].append(time.time()-t1)
         c_data[i][1].append(read)
         if read<0.5/5:
             a = False
     i = i+1
     a= True

I know arduino has a internal latency not larger than 100 us, so how do I achieve this? I still have to use python and not the arduino IDE because there are some other devices I need to control.

Python running on:

  • PC ?
  • Raspberry Pi ?
  • microPython board ?

There are a number of fast-read solutions (Google it); one is:

GitHub - avandalen/avdweb_AnalogReadFast

Post the full Python code, where is the data printed out?
I am not familiar with the board interface you seem to be using, does it add delays or timeout for communications?

This loop can last an unknown amount of time

I'm using PC(mac pro). Thanks i'll go check it out!


import pyfirmata
import time

board = pyfirmata.Arduino('/dev/cu.usbmodem144101')
it = pyfirmata.util.Iterator(board)
it.start()
a = True
c_data = [[[],[]],[[],[]],[[],[]],[[],[]],[[],[]]]
i = 0
analog_red = board.get_pin('a:1:i')
time.sleep(6)

while i<5:
     board.digital[12].write(1)
     time.sleep(3)
     board.digital[12].write(0)
     t1 = time.time()
     while a:
         read =analog_red.read()
         c_data[i][0].append(time.time()-t1)
         c_data[i][1].append(read)
         if read<0.5/5:
             a = False
     i = i+1
     a= True

This is just the code that I use to test the capacitor discharge time. It will charge and discharge the capacitor 5 times and store the voltage and time reading in 5 lists embedded in "c_data". After I run the code I found that in c_data, the voltage reading stays constant for about 20ms and suddenly changes to a new value and stay there for about 20ms too. This means I only get 5 different voltage values during 100ms of time.
The loop will end when voltage reading is below 0.5 V, but due to the large latency, when i use a capacitor with small capacitance( 50 uF or lower), I cant get its discharge time because the error is larger than the discharge time. Arduino simply does not update value at the instant when capacitor has discharged.

I don’t know much about pyfirmata - I came across it by helping out here - but it Is not highly regarded from what I have read.

I notice that you use an iterator thread - may be that’s reading way too much information (all the pins’ status?) - you would have to dig in the details and check if enable_reporting() might not be a alternate choice

pyfirmata probably does the basics OK but it’s such an overhead with a slow and obscure Serial communication that it might not be fit for your purpose.

If I had to do this, i would write custom code on the arduino for the experiment and custom Python code to get the data…

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.