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).
serial output (RS232 format),
As far as I understand the data sheet, the voltage levels of the serial output are 0 and Vcc. If you run the sensor at Vcc=3.3v, then these ouput levels are ocmpatible with the xxPy devices. You can try to connect the output to the input of UART 1, 9600 baud. If you receive gibberish, then an inverter may be needed, which can be a single 2n7000 Transistor (S->GND, D->Rx input, G->Sensor-ouput). You might need a pullup-resitor at the Rx-input.
To test, whether that works, connect it to a USB/UART bridge and open a serial terminal emulator.
Hi...i am a new user here. As per my knowledge you should run this sensor at Vcc of 3.3V. So you do not need a factor of x of range scaling, but you might need it for calibration. You can try 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.
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.