Code: Select all
adjustedAnalogValue = 1240.90909091 ((analogRead() / 1333.8762215) + 0.13)
I wanted to document how I solved an issue because I believe the solution will benefit other people.
Essentially, I have a pressure sensor which reads 0psi at 0.5v and the max rated psi at 4.5v.
It's a 5v device so I simply passed it through a 2 resistor voltage divider to divide the voltage down to 3.3v for the esp32's internal adc to read.
So lets set up some expected values. The esp32 adc has an analogRead range of 0 (0v) to 4095 (3.3v)
Our 0 psi analogRead value expectation is (0.5/5) * 4095 = 409.5
Out max psi analogRead value expectation is (4.5/5) * 4095 = 3685.5
Seems simple enough. You can then do a fairly straightforward calculation to get the pressure, but that is unneeded for the rest of this thread.
The issue comes in when I tried to read the value of the pressure sensor.
analogRead at 0psi was returning roughly 240...
That is quite off from our expected 409.5 value!
This resulted in an unnacceptably innacurate reading of pressure for me.
I dove in trying to figure out why my calculations were off, messing with different things. To make things more interesting, I also use an ads1115 for 4 more of the same pressure sensors, and that one was reading values quite accurately.
So this meant that my calculations were likely fine, it was something specifically with my voltage divider and reading on the esp32's build in adc.
I eventually stumbled upon this graph here:
It clicked with me...
the esp32's adc does not read properly outside of 0.13v and 3.2 volts.
This means that the whole graph of the readings is slightly off... simplifying the graph, it has a steeper slope than expected.
From 0v to 1.65v we would be reading below actual, and from 1.65v to 3.3v we would be reading slightly higher. With the values more dramatic towards the end.
For example... if I am receiving 0.13v I would expect analogRead to return maybe 100 or so, but instead it would return 0. You see?
Here this image is what we would theoretically expect to receive from the esp32:
A perfect line from 0,0 to 3.3,4095
I am a little rusty on my math skills, but I thought there must be a way to translate/stretch out our values from analog read to match this perfect line.
So here is what I came up with, where y is the analog value and x is the voltage:
First, describe the ideal line sitation.
This is easy, just use out 2 points on the ideal line, (0,0) and (3.3,4095), and formulate them
y-y1 = m(x-x1)
m = (y-y1)/(x-x1) = (0-4095)/(0-3.3) = 1240.90909
y - 0 = 1240.90909 (x - 0)
y = 1240.90909x
That formula represents our ideal line
Now we need a line that represents an approximation of what the esp32 reads, which is a line between the points (0.13,0) and (3.2,4095)
m = (y-y1)/(x-x1) = (0-4095)/(0.13-3.2) = 1333.8762215
y - 0 = 1333.8762215 (x - 0.13 )
This represents our approximation of what the esp32 is ACTUALLY reading.
Basically, if you wanted to get the voltage back from the readings of analogRead, you would assume you would use the forumula from the ideal line, but actually this approximation line is a much closer representation of what the esp32 is actually reading.
Now we can take that formula and solve for x (voltage) so we can get the voltage back from the approximation:
y = 1333.8762215 (x - 0.13)
y / 1333.8762215 = x - 0.13
(y / 1333.8762215) + 0.13 = x
X = voltage, y = the value from analogRead, now we can plug this voltage back in to our ideal graph to get the value the esp32 would have been reading if it worked perfectly:
approximation: voltage = (analogRead() / 1333.8762215) + 0.13
ideal: adjustedAnalogValue = 1240.90909 * voltage
So then we substitute in voltage and we get our final formula:
Code: Select all
adjustedAnalogValue = 1240.90909091 ((analogRead() / 1333.8762215) + 0.13)
So now any where that you use the internal esp32 analogRead function you can wrap it in this simple formula to get a much more accurate reading.
Cheers!