We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Post 55
Weather App 03 - New Firmware and Gather Data
Published on: 2025-08-04
Tags:
elixir, Blog, Side Project, Nerves, Weather App
Capturing Sensor Data
Okay so now that we are ready to move onto the capture part of the process we need to download the spec sheet for the environmental hat (https://www.waveshare.com/environment-sensor-hat.htm). Here are some of the information that we will need:
Light Sensor
I2C address: 0x29
Temp/Humidity/Air Pressure
I2c address: 0x76
Motion Sensor:
I2C adress: 0x68
UV Sensor:
I2C address: 0x53
VOC Sensor:
I2C address: 0x59
These might be different for your device I was able to look up the sensor data on line and it even has them on the board itself. Some of the sensors will have different sensitivities so be sure to check those out too.
Now let's change a few deps and then upload the new firmware.
$ mix deps.get
...
$ mix firmware
...
$ mix upload
...
$ ssh nerves.local
...
So again my current settings I was unable to use the nerves.local so I had to create an firmware update script and then use that to upload it to the pi.
mix firmware.gen.script # This is instead of the mix upload
./upload.sh 192.168.x.x $ Your IP address of the pi
Now you can ssh into the device.
ssh 192.168.x.x
This is the way to do it with the basic sensor that the book is using.
Here is where we will start to take some the sensor data.
ex(1)> alias Circuits.I2C
Circuits.I2C
iex(2)> sensor = 0x29 # This is the address of the light sensor
72
iex(3)> command = <<0>>
<<0>>
iex(4)> byte_size = 2
2
iex(5)> {:ok, i2c_ref} = I2C.open("i2c-1")
{:ok, #Reference<0.1635386997.268828675.62058>}
iex(6)> <<value::little-16>> = I2C.write_read!(i2c_ref, sensor, command, 2)
<<1, 0>>
iex(7)> value |> inspect(base: :binary)
"0b0"
With the value of 0b0 being returned we know that the sensor is turned off. Let's turn it on.
iex(8)> config = 0b0001100000000000
6144
iex(9)> Circuits.I2C.write(i2c_ref, sensor, <<0, config::little-16>>)
:ok
iex(10)> <<value::little-16>> = I2C.write_read!(i2c_ref, sensor, command, 2)
<<0, 24>>
iex(11)> value |> inspect(base: :binary)
"0b1100000000000"
This didn't work for me so Ill try an other way
alias Circuits.I2C
import Bitwise
sensor = 0x29 # Sensor I2C address
command_bit = 0x80 # Command bit to indicate command register (depends on sensor)
enable_register = 0x00 # Register address to enable power and ALS
config_register = 0x01 # Configuration register
data_register = 0x14 # Data register address (where readings start)
# Bit flags to enable power and ALS (ambient light sensing)
enable_power_on = 0x01
enable_als_enable = 0x02
# Combine flags with bitwise OR
enable_value = enable_power_on ||| enable_als_enable
# Open I2C bus
{:ok, i2c_ref} = I2C.open("i2c-1")
# Write to enable register with command bit set
I2C.write(i2c_ref, sensor, <<command_bit ||| enable_register, enable_value>>)
# Optionally configure other registers here...
# Read 2 bytes from the data register
<<raw_value::little-16>> = I2C.write_read!(i2c_ref, sensor, <<command_bit ||| data_register>>, 2)
IO.inspect(raw_value, base: :binary)
Now we can start to do something with the sensor.
iex(12)> light_reading = 4
4
iex(13)> <<value::little-16>> =
...(13)> Circuits.I2C.write_read!(i2c_ref, sensor, <<light_reading>>, 2)
iex(14)> value
440
We get a value back. Now, put your hand over the sensor so that there’s less light and see if the value is lower:
iex(15)> <<value::little-16>> =
...(15)> Circuits.I2C.write_read!(i2c_ref, sensor, <<light_reading>>, 2)
iex(16)> value
40
Now we can try and transfor the data into something useful.
iex(17)> measure_light = fn i2c, address ->
...(17)> <<value::little-16>> = I2C.write_read!(i2c, address, <<4>>, 2)
...(17)> value * 0.2304
...(17)> end
#Function<43.97283095/2 in :erl_eval.expr/5>
iex(16)> measure_light.(i2c_ref, sensor)
57.6