Closed mattjg908 closed 2 years ago
Thanks for the information and digging - I wasn't aware of this. Does this only effect the final voltage conversion? Currently this library doesn't actually return voltage, just the 'val' (although there is an open issue about getting final voltage).
Hi @tomjoro , thanks for the quick reply! The only thing I've used the library for is final voltage so I'm not sure if anything else is affected. I just learned of i2c's existence yesterday so I'm still gaining context.
I see the other issue so perhaps this one should be closed in light of that? Happy to help if that is desired/helpful although, again, I'm still gaining context into what a lot of this means.
If the other issue is not implemented, I'm curious on your and @mmmries thoughts on this issue, and I'm wondering what val
used for?
It's been a while since I was using this, but I think converting to a final voltage also requires some knowledge about the inputs to the ADC, right? Meaning that the user would have to pass in the reference voltage that they are comparing against?
In your example above I would have thought that when we pattern match with a <<val::signed-size(16)>>
the sign bit would already be account for since we're asking the BEAM to treat this as a signed integer. Do we know how the ADS1015 pads it's 12 bits of data? I think the BEAM is assuming that the sign bit will be the first bit, but if the ADC sends something like 0000
and then a signed twelve-bit number, we would need to change that pattern match to be <<_ignored::unsigned-size(4), val::signed-size(12)>>
so that we capture the right number.
Looking at the datasheet here it looks like the 16-bit register reserves the 4 lowest bits as always being "0" and then the remaining bits as a signed 12-bit number.
It's been a little while since I've thought about these kinds of binaries, so I'm not sure if it matters whether we do the divide by 16 (ie shift 4 bits) before we treat it as a 2's complement number? Maybe the right pattern match is <<val::signed-size(12), _rest ::binary>>
?
Hi!
It's been a while since I was using this, but I think converting to a final voltage also requires some knowledge about the inputs to the ADC, right?
I think I'm doing that by first doing ADS1015.read(ref, 72, {:ain0, :gnd})
, until I do that I only ever get <<0, 0>>
back from I2C.write_read/4
. After I do that, it gives me
iex(51)> {:ok, <<val::signed-size(16)>>} = I2C.write_read(bus, addr, <<0>>, 2)
{:ok, <<39, 240>>}
I would have thought that when we pattern match with a <<val::signed-size(16)>> the sign bit would already be account for
I would have expected so as well, I've also tried specifying little-endian which isn't right. It seems to me, for some reason, the sign-bit comes back as the LSB. Maybe it's something to do with the datasheet saying this data comes back in 2's complement? I don't understand why if I just get rid of the first bit, it works as I'd expect.
Maybe the right pattern match is <<val::signed-size(12), _rest ::binary>>?
I did try that (..._rest::binary
will err out, seems like you need to mention the size explicitly). While it does seem to negate the need to shift, it still returns an unexpectedly high value
I don't know why, but it seems like the sign-bit is the LSB for some reason
Hi,
Do you have the PGA (gain) settings at gain: 2048,
? From your snippet above:
iex(77)> ADS1015.config(ref, address)
{:ok,
%ADS1015.Config{
comp_latch: false,
comp_mode: :traditional,
comp_polarity: :active_low,
comp_queue: :disabled,
data_rate: 1600,
gain: 2048, # <--- gain must be larger than the largest voltage you want to measure
mode: :single_shot,
mux: {:ain1, :gnd},
performing_conversion: false
}}
If so, that would mean the maximum voltage you can measure is +2.048V.
The PGA setting actually controls what the maximum voltage can be read.
val
returns 2047 when measuring +2.047Vval
returns 2047 when measuring +4.096Vval
returns 2047 when measuring +6.144VAs I understand, the way the PGA works is that the PGA zooms in on the voltage range. You need to set the gain to 6144 to read +5V.
And also use the same gain, i.e. 6144, in the voltage conversion.
def convert_to_voltage(fsr, gain \\ 2048) do
Hi @tomjoro , Thank you for explaining that! Yes, I must have gain set unintentionally low.
I think I'm going to close this issue because:
Thanks for the help @tomjoro and @mmmries !
Hello, thank you for the nice library! I am not sure if I'm correct about this so I thought I'd ask here...
TLDR, I think this line should be updated
https://github.com/mmmries/ads1115/blob/71811175f8ad3c0d82add4e5b5fa2925de98b881/lib/ads1015.ex#L55
Possible Issue (or just me making a mistake)
I'm using an Rpi3 and a Pimoroni Automation Hat mini which uses the ADS1015 chip
The ADS1015 uses scaling,
This point about
ADS1015
scaling is also mentioned here,I have taken a 5 v wire and plugged it into one of the analog inputs oof the hat and then used this
ads11115
library to read the power as a test. For context:iex(77)> ADS1015.config(ref, address)
{:ok,
%ADS1015.Config{
comp_latch: false,
comp_mode: :traditional,
comp_polarity: :active_low,
comp_queue: :disabled,
data_rate: 1600,
gain: 2048,
mode: :single_shot,
mux: {:ain1, :gnd},
performing_conversion: false
}}
So, if I then undo the scaling I'd expect
~5 volts
(essentially taking the same formula from the previous link)So, short story long, I think the line below should ignore the first bit: https://github.com/mmmries/ads1115/blob/71811175f8ad3c0d82add4e5b5fa2925de98b881/lib/ads1015.ex#L55
and perhaps should be:
So then continuing with that I divide by 16 (shift) https://github.com/mmmries/ads1115/blob/71811175f8ad3c0d82add4e5b5fa2925de98b881/lib/ads1015.ex#L57
And now when I undo the scaling I get the expected
~5 volts
I also tested this update by connecting another Rpi's ground and 3.3 volt to the Pimoroni Hat, and with the changes I mentioned above it reads
3.297833333333333
as expected, without the changes mentioned it here it reads6.595666666666666