Skip to content

mandeeps/SU-WaterCam

Repository files navigation

Build Guide / How To

See ticktalk branch for current work

Project requires a Raspberry Pi

or compatible single board computer with GPIO, I2C, SPI etc.,

Parts List

Test the SD cards with F3: https://github.com/AltraMayor/f3

Raspberry Pi 4 with Flir camera, IMU, and Quectel Cellular modem+GPS

Ideally we will have an image that can be flashed onto an SD card for new builds.

Installation from scratch: Use Raspberry Pi Imager to install current stable 64-bit Raspberry Pi OS lite to a microSD card with SSH enabled in the configuration options, along with the user account name and password, and configure a unique hostname for each system that makes sense (like the installation location)

https://www.raspberrypi.com/software/

After flashing, add enable_uart=1 at the end of the /boot/config.txt file. Insert the SD card in the Pi, attach power and boot it up.

https://www.jeffgeerling.com/blog/2021/attaching-raspberry-pis-serial-console-uart-debugging

Use a serial cable to connect to the console and use sudo raspi-config to configure the device settings (locale, timezone, predictable network names, etc.,) and select Network Manager in place of dhcpcd in networking settings. https://learn.adafruit.com/adafruits-raspberry-pi-lesson-5-using-a-console-cable/software-installation-windows

Leave GPU memory at the default of 32 MB, PiCamera2 will not need more and the camera will not work with less.

Use sudo nmtui to configure the ethernet connection to a static IP, with your computer IP as the gateway and DNS server if you are sharing your Internet connection with the Pi. Otherwise configure for whatever network setup you have.

Now you can use ssh to login to the Pi after connecting it to your computer with an ethernet cable. Connection sharing can be setup using Network Manager on a Linux computer, or Windows Connection sharing, or the macOS equivalent.

Once you've logged in and are sharing an internet connection from your computer to the Pi, run sudo apt update and sudo apt upgrade

Verify the Pi is on the latest firmware with rpi-eeprom-update.

Helpful tools: sudo apt install git tmux screen minicom Install your preferred editor, which should be neovim, and aptitude if you want a TUI for apt

Set /boot/config.txt options:

Disable LEDs to save a little power

dtparam=act_led_trigger=none dtparam=act_led_activelow=off dtparam=pwr_led_activelow=off

To disable ethernet LEDs on Pi 3 & 4 try:

dtparam=eth_led0=4 dtparam=eth_led1=4

or:

dtparam=eth_led0=14 dtparam=eth_led1=14

disable audio

dtparam=audio=off

disable wireless, we won't use WiFi or Bluetooth

dtoverlay=disable-wifi dtoverlay=disable-bt dtoverlay=pi3-disable-wifi dtoverlay=pi3-disable-bt

I2C clock stretching for BNO055 IMU

dtparam=i2c_arm_baudrate=10000

Add to /boot/cmdline.txt - Flir SPI settings

spidev.bufsiz=131072

SD Card settings

Disable swap and set noatime to prolong SD card life: sudo swapoff --all, sudo apt purge dphys-swapfile.

Add noatime,commit=60 settings to ext4 partitions in /etc/fstab - noatime prevents writing access times to files, commit collects and delays writes to every N seconds. Data loss will be limited to the last N seconds of writes if power is lost. Do NOT change the /boot partition settings, it is a vfat filesystem and these options will not work and will cause the Pi to not boot.

Set temp directories like /tmp, /var/tmp to mount in RAM, ex. tmpfs /var/tmp tmpfs nodev,nosuid,size=20M 0 0 in fstab

Use a larger SD card size than needed so you have free space for automatic wear-leveling.

Optional Tweaks

You can disable services we won't be needing to speed up boot slightly (~3s) sudo systemctl disable man-db.timer wpa_supplicant keyboard-setup triggerhappy

If there are issues with taking high-resolution images use the vc4-kms-v3d driver with options: dtoverlay=vc4-kms-v3d,cma-320

Can also add nohdmi to the vc4-kms-v3d line to disable HDMI ports and save ~30mA

Power Management

Next, configure the WittyPi 3 Mini for power management. Download: wget http://www.uugear.com/repo/WittyPi3/install.sh Install: sudo sh install.sh Reboot, then run wittyPi.sh from the wittypi directory to configure the schedule.

SU-WaterCam setup

Clone the public git repo: https://github.com/mandeeps/SU-WaterCam.git Compile lepton.c and capture.c for the device. Install build-essential if not already done: sudo apt install build-essential. Then cd to the SU-WaterCam/tools directory and run: gcc lepton.c -o lepton && gcc capture.c -o capture

Copy to the root of the SU-WaterCam directory: From tools directory, run "cp lepton ../." and "cp capture ../."

Use apt to install these packages: sudo apt install libgpiod-dev python3-pandas python3-dev python3-venv exempi python3-wheel python3-picamera2

Make sure picamera2 is installed as system package, not through pip

We need to use virtual environments for Python on Debian-derivatives like Raspberry Pi OS starting with Debian 12 (codenamed Bookworm). As of 6-20-23 Debian 11 remains the current stable base for Raspberry Pi OS, but let's future proof by using a venv now. Create a virtual environment with python -m venv --system-site-packages /home/pi/SU-WaterCam/venv, (we use system-site-packages to copy over pandas and other installed modules) activate with source /home/pi/SU-WaterCam/venv/bin/activate, and then install modules with pip install -r /home/pi/SU-WaterCam/requirements.txt or manually with pip install compress_pickle adafruit-blinka gpiozero piexif py-gpsd2 python-xmp-toolkit

If using MLX90640 thermal sensor also install: adafruit_circuitpython-mlx90640. If using MPU6050 IMU install: adafruit_circuitpython_mpu6050. If using BNO055 IMU: pip install adafruit-circuitpython-bno055 in the venv.

If using Adafruit MPU6050 IMU:

Change the WittyPi 3 i2c address to avoid a conflict. The WittyPi 3 uses 0x68 for the RTC, and 0x69 for its microcontroller. The RTC address cannot be changed, but the microcontroller address can. The MPU6050 uses 0x68 by default. First solder the connection on the back of the MPU6050 board to change its i2c address to 0x69. Then change the WittyPi 3 microcontroller i2c address to something else, like 0x70 by following the instructions in the manual. WittyPi 4 does not require this.

Change the Witty Pi 3 microcontroller I2C address: i2cset -y 1 0x69 9 0x70

Edit the utilities.sh file in the wittypi directory and change I2C_MC_ADDRESS=0x69 to 0x70

Then shutdown the system: sudo halt

Disconnect the power to the wittypi 3, reconnect it, start the system up

Check the i2c settings changed: i2cdetect -y 1

Run the wittypi script to verify ./wittypi/wittyPi.sh

Note changing the microcontroller address seems to interfere with displaying power draw using wittyPi.sh despite having changed the address in utilities.sh

now install adafruit_circuitpython_mpu6050 to use the MPU6050 in Python

Adafruit BNO055 IMU

pip install adafruit-circuitpython-bno055 in the venv

Calibrate the IMU prior to use:

With the MPU6050 IMU stable and flat, run the mpu6050 calibration script to save offset values.

TODO: Calibrate BNO055

Quectel EC25 Modem and GPS

sudo apt install gpsd gpsd-clients

Remove and purge udhcpcd and openresolv: sudo apt purge udhcpcd openresolv Reconfigure current network devices with network manager to retain local networking during setup - sudo nmtui is easiest way Make sure /etc/network/interfaces has no references to devices you want NM to manage

Then configure the cellular modem and verify everything works as expected after restarts sudo mmcli -m 0 --simple-connect='apn=iot.1nce.net' Replace apn as appropriate

Setup connection with NetworkManager: sudo nmcli c add type gsm ifname cdc-wdm0 con-name Quectel apn iot.1nce.net

On Bookworm: sudo mmcli -m 0 –-location-enable-gps-unmanaged -- to tell ModemManager to start the GPS on the Quectel EC25 but not control it, so gpsd can manage it instead Enable gps.service in the git config directory so this will be done automatically on boot.

Bullseye: ModemManager on Bullseye doesn't support --location-enable-gps-unmanaged for the Quectel EC25 apparently, and since RaspberryPi OS has not officially released a Bookworm-based version yet, we are using Bullseye and working around this by creating a custom Udev rule to tell ModemManager to ignore the GPS:

create file /etc/udev/rules.d/77-mm-quectel-ignore-gps.rules with contents: ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", SUBSYSTEM=="tty", ENV{ID_MM_PORT_IGNORE}="1"

Save this and run sudo udevadm control --reload

sudo udevadm trigger

If using a different cellular modem change the ids to the appropriate ones, use lsusb to lookup the ids.

Might need to reboot before next step...

Activate the GPS and enable autostart for future use -

install minicom if not already available and run it: minicom -b 9600 -D /dev/ttyUSB2

(ttyUSB2 is the AT port for the Quectel. ttyUSB1 is the GPS output port)

In minicom, issue the following AT commands -

Enable NMEA: AT+QGPSCFG="nmeasrc",1

Enable Autostart: AT+QGPSCFG="autogps",1

Turn GPS on: AT+QGPS=1

Assisted location fix: AT+QGPSXTRA=1

Quit minicom with ctrl-a, x These should be saved to the device's NVRAM so this should only need to be done once.

Now edit /etc/default/gpsd to set the correct gps device, in this case /dev/ttyUSB1

Then in python we can get gps data with py-gpsd2: import gpsd2 gpsd2.connect() packet = gpsd2.get_current() print(packet.position())

If there are issues getting a fast location fix try updating the XTRA assist data by downloading a new xtra2.bin from xtrapath4.izatcloud.net/xtra2.bin and uploading it to the modem with sudo mmcli -m 0 --location-inject-assistance-data=xtra2.bin

sources: https://sigquit.wordpress.com/2012/03/29/enabling-gps-location-in-modemmanager/ Stackoverflow mirror: https://code.whatever.social/questions/6146131/python-gps-module-reading-latest-gps-data

Flir Lepton Breakout board wiring

8 female-female jumper cables needed. At least 2 should be splitters to share I2C with other devices.

Orient the back of the breakout board towards yourself. The front is the side with the socket for the Lepton camera. Let's call the pins that are closest to you pins 1 through 10, starting from the left and going to the right. Right is the side with the mini ZIF connector on top (the white plastic bit above the QR code sticker) Let's call the pins on the bottom (away from you) pins A through J Pin 1 is for power, so wire that to the 3.3V power pin on the Pi. See the Flir Lepton Wiring image for help. We can use the top pin of the two pins without jumpers on the back of the board (side towards you right now) for ground. In other words, the pin with nothing covering it that is closest to the white ZIF socket towards the top is the ground pin, so connect it to the ground pin on the Pi.

TODO: upload photos of Lepton wiring

Because we need I2C for other peripherals, use splitter cables for the two I2C pins (SDA and SCL) on the Pi. So get or make two cables that each have a female header on one end and a male and female header on the other end. One female end connects to a pin on the Raspberry Pi GPIO header, and the other two ends are for the Flir breakout board and a peripheral like the Adafruit IMU. Another pair of split cables is useful for 3.3V and ground.

The SDA pin on the Pi (pin #3) will connect to pin C on the breakout board (side away from you) - use a splitter

The SCL pin on the Pi (pin #5) will connect to pin 4 on the breakout board (side towards you) - use a splitter

MOSI on the Pi (pin #19) connects to pin E on the breakout

MISO on the Pi (pin #21) connects to pin 6 on the breakout board

CLK pin on the Pi (pin #23) will connect to pin D on the breakout

CS pin (pin #24, right across from CLK, aka CE0, GPIO 8) connects to pin 5 on the breakout board

The VSYNC pin is Pin #11, GPIO 17 on the Pi connected to pin H on the breakout board.

Reset pin on the breakout is pin I following the convention declared above. Connect it to an arbritrary GPIO pin on Pi that is set high by default (options are 0-8)

I am using GPIO 6 (pin 31 on the Pi) in the lepton_reset.py script. We need a pin that is high by default because the breakout board reset triggers on low.

Insert the Flir camera into the breakout board. Check everything is correct by running the capture and lepton binaries in SU-WaterCam. Rename or copy the appropriate 32 or 64-bit binaries to "lepton" and "capture" and then run: ./capture

Examine the created files to verify things are working.

Binaries are from https://github.com/lukevanhorn/Lepton3

Thanks Luke Van Horn! Also, thanks to Max Lipitz for the tip about the output containing the temperature values in degrees Kelvin.

Leptonic for live thermal image stream

We're setting up an unused Pi 3 for collecting thermal images for coregistration - using leptonic from github, a forked branch that can be built on Debian 12 Bookworm

https://github.com/rob-coco/leptonic/tree/bookworm-update

checkout the bookworm-update branch, compile that after installing dependencies: libzmq3-dev

Port forward, first ssh into pi and run leptonic on /dev/spidev0.0, then open another terminal and port forward with: ➜ ssh -L 5555:10.42.0.3:5555 [email protected]

Run the leptonic web server on your own machine, it's too much for the Pi 3 to do both: npm start in frontend directory then 127.0.0.1:3000 in your browser

Multitech mDot LoRa module

The default mDot firmware is set up for UART. The WittyPi can tell if the Raspberry Pi is off by reading the TX pin, which should be set low when the Pi shuts down. The mDot seems to interfere with this, keeping the TX pin on the Pi set high and preventing the WittyPi from cutting off power to the system. There are several possible workarounds for this:

  • Option #1 - Use something other than the WittyPi. We already have several and it works well otherwise, so this is not a good option.

  • Option #2 - Use something other than the mDot. We also have several of these, so this is not an ideal option.

  • Option #3 - Use a USB-Serial adapter to connect the mDot to the Pi instead of the UART pins. This would increase power draw and add another component to the deployed build, so it is not ideal but better than the first two. This is the option I am using on non-4 model Pis.

The non-4 models only expose one UART on GPIO at a time, so using the USB adapter may be the only easy option for those. For a Pi 3 or other non-4, connect the Adafruit USB-serial adapter to the USB port. Connect the mDot TX to the white RX header, and the mDot RX to the green TX header. Use minicom or screen with the settings listed in the mDot manual to connect to the appropriate device, it will be /dev/ttyUSBx where x is a number. Check dmesg to see what device the adapter is: dmesg | grep "cp210x"

  • Option #4 - Modify the mDot firmware to keep its RX pin low. We do not have a devkit for this device yet so this is not possible right now. The same applies to modifying the firmware to use I2C instead. Maybe we could use a resistor to connect to ground?

  • Option #5 - Turn on alternative UART pins on the Pi 4 and use those to connect to the mDot instead of the pin the WittyPi reads to determine the Pi's state. This is the option I am currently using for our Pi 4s. Upside is we can use the serial console for debugging and use the mDot at the same time.

By adding dtoverlay=uart5 to /boot/config.txt on a Pi 4 we can use pin 32 for TX and pin 33 for RX. On the Pi 4, make sure "enable_uart=1" is in the /boot/config.txt file, and add dtoverlay=uart5. Save and reboot. Connect the TX pin on the mDot to pin #33 on the Pi and connect the RX pin on the mDot to pin #32 on the Pi.

The power pin (VOD, pin # 1) on the mDot can be connected to the 5V or 3.3V power pin on the Pi. Connect ground (pin 10 on the mDot) to a free ground pin. Connect the mDot UART TX (transmit, pin #2) to the Pi RX (receive) pin (#10 default, pin #33 if using uart5), and the mDot RX pin (#3) to the Pi TX pin (#8 default, pin #32 using uart5).

On the Pi run sudo minicom -s -D /dev/serial0 to connect to the mDot if it is on the default TX/RX pins, minicom -s -D /dev/ttyAMA1 if on uart5, and issue AT commands. Use the settings specified in the mDot manual:

Baud rate 115200

Data bits 8

Parity N

Stop bits 1

Hardware/software flow control off

If you are using the mDot on the default Pi TX/RX pins you need to remove "console=serial0,115200 console=tty1" from /boot/cmdline.txt on the Pi if you've been using a serial connection to the Pi for debugging. Reboot the Pi for this to take effect.

For deployment we'll want the mDot to have a seperate power source so we can remotely trigger it to signal the WittyPi to boot up the system and record data.

Tailscale for remote login over cellular data

https://tailscale.com/download

Install and use mosh for high-latency cellular connections sudo apt install mosh

Use an appropriate client for your own device.

Remote Video Streaming

with libcamera-apps-lite installed run:

libcamera-vid -t 0 --inline --listen -o tcp://0.0.0.0:8888

On your machine connected to the Pi (over Tailscale or directly) use VLC to stream the video using 'open network stream' and enter tcp/h264://PI_ADDRESS_OR_HOSTNAME:8888 with the appropriate IP address and port number.

Pytorch

pip install torch torchvision (in the venv)

Model based on FloodNet data set and DeepLab FloodNet: https://ieeexplore.ieee.org/document/9460988

lang segment anything

lang-segment-anything needs older Python version than what is available in current raspberrypi os.

https://github.com/luca-medeiros/lang-segment-anything/tree/main

So first install pyenv to install an older python

sudo apt-get install build-essential zlib1g-dev libffi-dev libssl-dev libbz2-dev libreadline-dev libsqlite3-dev liblzma-dev

curl https://pyenv.run | bash

add to .bashrc as instructed

pyenv install 3.8

switch to python 3.8 with pyenv local 3.8

Use local for the current directory, or global use 3.8 for everything

now you can run the install for lang-segment-anything

Run running_test.py

TinySAM -

Old Pi Zero 32-bit Instructions

Written assuming you are using a Raspberry Pi Zero with headers installed and the Adafruit MLX90640 sensor

Flash the provided disk image onto the microSD card if not already done

If installing regular Raspbian/RaspberryPi OS image from scratch: in raspi-config set timezone, enable camera, ssh and i2c, set static IP address, reduce GPU memory to 128 minimum for optical camera, change default password, etc., use apt to install python3-pandas and libgpiod-dev: sudo apt install libgpiod-dev python3-pandas

Create a virtual environment with python -m venv --system-site-packages /home/pi/SU-WaterCam/venv, activate with source /home/pi/SU-WaterCam/venv/bin/activate, and then install modules with pip install -r /home/pi/SU-WaterCam/requirements.txt or manually use pip to install dependencies: python3 -m pip install compress_pickle adafruit-blinka adafruit_circuitpython-mlx90640 gpiozero adafruit_circuitpython_mpu6050

It's easier to connect the optical camera before installing the WittyPi. Be careful with the connector and the cable, IME ribbon cables and ZIF sockets are fragile. While the cable can flex it should not be folded. Be careful you don't break the socket clip by using too much force. For the RPi Zero you'll want to replace any cable included with the camera with the correct RPi Zero camera cable.

Insert the larger end of the RPi camera ribbon cable into the optical camera by gently pulling the black plastic clip out and inserting the cable in, making sure the exposed side with the gold pins is facing down. Secure the cable by pusing the plastic clip back in.

Now on the Raspberry Pi end, gently pull forward the black plastic clip on the CSI camera connector. Insert the cable into the connector making sure the exposed side is down. Push the black plastic clip back into place.

Install stacking header onto the Raspberry Pi header making sure it is firmly in place.

Install WittyPi 3 Mini onto the extended headers making sure it is in place.

Once the WittyPi is installed you can connect your thermal sensor. See the reference Raspberry Pi Zero image

Connect the Stemma QT cable to the Adafruit MLX90640 sensor, either socket works

Connect the red header cable to pin 1, the 3.3v pin on the top left

Connect the blue header cable to pin 3, the GPIO data pin just below pin 1

Connect the yellow header cable to pin 5, the GPIO clock pin just below pin 3

Connect the black header cable to pin 6, the Ground pin just right of pin 5

Make sure your battery is charged. Connect the battery to the WittyPi micro USB port. Either directly with a cable if using a Voltaic power pack, or through the charger if using a lipo battery. Press the button on the WittyPi to check if everything turns on. Check the LEDs

Log into the Pi and use the WittyPi program to set the schedule (and increase idle power use if using a normal power bank that isn't intended for IoT devices/doesn't have an always-on mode. Voltaic batteries should not need this.)

https://cdn-shop.adafruit.com/product-files/5038/5038_WittyPi3Mini_UserManual.pdf

If you have a computer set up to connect to the RPi Zero using USB-OTG networking

https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget

https://artivis.github.io/post/2020/pi-zero/

you can plug a micro USB cable into the data port of the RPi (the middle port of the three) and the other end into your computer. Assuming your computer configuration is correct you should be able to use SSH to access the Zero. If you are not using a Zero you'll need to use a serial connection to connect to the Pi or configure ethernet or wifi networking on the Pi to SSH in. Or just plug in a monitor and keyboard.

About

Software for a Raspberry Pi-based environmental monitoring system

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published