Reading analog voltage with ADC and attenuation
I am playing with a rangefinder ultrasonic sensor (MB7360 from Maxbotix) and I have some question regarding the way to correctly read the sensor values.
The sensor operates at voltage between 2.7V and 5.5V, so I hooked it up on the 3.3V pin of the expansion board.
I am using the sensor's analog voltage output to read the distance measured by the sensor. In the spec-sheet it is mentioned that
- the output is referenced to the sensor ground and Vcc (which is 3.3V, right?)
- the scale factor is Vcc / 5120 per 1 mm
- using a 10 bits ADC, we just need to multiply the voltage read by 5 to obtain the distance
Since the maximum voltage output is 3.3V, I used an attenuation of 11 dB and I am using this piece of code to get the distance:
from machine import ADC # setting up the Analog/Digital Converter with 10 bits adc = ADC(bits=10) # create an analog pin on P20 for the ultrasonic sensor apin = adc.channel(pin='P20', attn=ADC.ATTN_11DB) # get distance dist = apin() * 5
With that code, the readings are not accurate, so I was wondering if I need to scale the distance to take into account the attenuation? (sorry if it's a stupid question, this is new to me)
Many thanks for your help/comments/suggestions!
PS: the sensor has also other outputs such as a Pulse Width output and a serial output (RS232 format), but the former seems to be difficult to measure using a LoPy (correct me if I am wrong, maybe I missed something while searching in the forum) and I don't have a RS232 <-> TTL converter with me for the later(plus I'd like to avoid using additional boards).
Thanks for all the clarifications! I'll switch to an ADC of 12 bits and give it a try.
@jojo The internal range of the ADC is 0-1V. The attentiation of 11dB gives the range of 0-3.3V, which is what you need for our sensor, running at an Vcc of 3.3V. So you do not need a factor of x of range scaling, but you might need it for calibration.
I never used the ADC in a range other than 12 bits. It might be that in lower than 12 bits mode you have to shift right the returned value by 1 or 2 bits. I have to try. So if the value you get is off by a factor of 4, that this may be the reason.
Thanks for the quick reply! :)
I should have said that when I use:
dist = apin() * 5
it is already a shortcut for
dist = apin() * 5120 / 1024
where 5120 is the sensor range and 1024 is the range of the ADC using 10 bits. I was wondering if because there is an attenuation, I also have to scale the value of
apin()by a factor
dist = apin() * 5 * x
Also, thanks for the suggestions. I should have mentioned that the piece of code is just a simplified exemple. In my code I also take multiple readings and then use the median (I'm not too found of the mean due to the huge variability). I agree that using a RS232 <-> TTL converter is probably the best option.
@jojo With an attn of 11db, the range of the ADC is 0-3.3V. You used 10 bits, so 1024 is equivalent to about 5 meters. I would assume then that the distance in meters you should get is:
ADC_RANGE = const(1024) sensor_range = 5.0 dist = apin * sensor_range/ ADC_RANGE
If you use bits=12, then ADC_RANGE has to be set to 4096. You might need to adapt sensor_range for calibration. And be warned, the ADC of ESP is not very good. It is nonlinear and noisy. It might be advisable instead of a single value to take the average of several values.
Anyhow, from that data sheet it looks as anyhow using the serial output is the most precise option.