I was talking to an ADS1115 ADC over I²C via /dev/i2c-1
on a Raspberry Pi 4.
My first attempt was using high-level IOStream
APIs like write(io, bytes)
and read(io, n)
, and it worked but only for the first value. Every value afterward is somehow saturated i.e. they’re all 0xFFFF
.
const I2C_SLAVE::UInt16 = 0x0703
const ADS1115_ADDRESS::UInt8 = 0x48
const ADS1115_CONFIG_REG::UInt8 = 0x01
const ADS1115_CONVERSION_REG::UInt8 = 0x00
io = open("/dev/i2c-1", "r+")
_fd = fd(io)
ccall((:ioctl, "libc.so.6"), Cint, (Cint, Culong, Cint), _fd, I2C_SLAVE, ADS1115_ADDRESS)
write(io, UInt8[ADS1115_CONFIG_REG, 0b10100010, 0b00000011])
flush(io)
sleep(0.01)
write(io, UInt8[ADS1115_CONVERSION_REG])
flush(io)
while true
data = read(io, 2)
value = reinterpret(Int16, data[end:-1:begin])
println(value)
sleep(0.2)
end
# results:
#
# 7328 (a random meaningful value)
# -1
# -1
# -1
# ...
I resolved the problem by ccall
ing the low-level read
in libc instead; that is, I modified the loop to be
data = Array{UInt8}(undef, 2)
while true
ccall((:read, "libc.so.6"), Cint, (Cint, Ptr{UInt8}, Csize_t), _fd, v, nbuf)
value = reinterpret(Int16, data[end:-1:begin])
println(value)
sleep(0.2)
end
# results:
#
# 7328
# 7329
# 7328
# ...
I suspect that it’s because IOStream
is buffered but lack relevant knowledge to dig deeper. I prefer sticking to high-level APIs as much as possible so I wonder if anyone can tweak the first example to make it work.
P.S. I tried unsafe_read
but ended up with no luck.