Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add silolevel sensor #38

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
/files/Thumbs.db
43 changes: 40 additions & 3 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,45 @@ station:
calibration_weight: 0
terminal_weight: 0
cameraRotation: 180
weightResetInMinutes: 20
audio_gain: +20 #audio_gain is to lift the volume of the microphone.To high values generate white noice, to low doesn't change anything
weightResetInMinutes: 20
audio_gain: +20
environment_values:
temperature : true
humidity: true
#If a Distancesensor is added set this to true
silolevel: false
sensors:
temperature:
#0- None 1-DHT22
type: 1
humidity:
#0- None 1-DHT22
type: 1
silolevel:
#0-None 5-vl53l0x
type: 5
hardware:
# This section defines GPIO Ports, and other hardware dependent values for each Sensor
DHT22:
#Default DATA_PIN:16
DATA_PIN: 16
HX711:
#Default SCK_PIN: 23,DT_PIN:17
SCK_PIN: 23
DT_PIN: 17
SPH0645KM4H:
#Default LRCL_PIN: 19,OUT_PIN:20, CLK_PIN:18
LRCL_PIN: 19
OUT_PIN: 20
CLK_PIN: 18
vl53l0x:
#Default GPIO1_PIN: 4, XSHUT_PIN: 26, i2cAddress: 0x29
GPIO1_PIN: 4
XSHUT_PIN: 26
empty_value: 0
full_value: 0
i2cAddress: "0x29"
misc:
loglevel: 20 # loglevel can be either 0-NOTSET, 10-DEBUG, 20-INFO, 30-WARNING, 40-ERROR, 50-CRITICAL
dev_mode: No # Yes - for testing, nothing is send to the server, No - normal usage, sync to server is enabled
dev_mode: No # Yes - for testing, nothing is sent to the server, No - normal usage, sync to server is enabled

Binary file added files/SilolevelSensor_Pinout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/birdSilo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 26 additions & 15 deletions getStarted.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# Vorbereitung Pi
- Installiere den Raspberry Pi Imager auf deinem lokalen Computer (Den Imager findest du hier: https://www.raspberrypi.com/software/)
- Verbinde die SD Karte, die später einmal im Raspberry Pi genutzt wird, mit deinem Computer (in der Regel kannst du die Micro SD Karte mit einem beigelegten Adapter in deinen PC stecken)
- Da alle Daten auf der SD Karte gelöscht werden, solltest du eventuelle Daten vor den folgenden Schritten abgespeichert haben
- Verbinde die SD-Karte, die später einmal im Raspberry Pi genutzt wird, mit deinem Computer (in der Regel kannst du die Micro SD-Karte mit einem beigelegten Adapter in deinen PC stecken)
- Da alle Daten auf der SD-Karte gelöscht werden, solltest du eventuelle Daten vor den folgenden Schritten abgespeichert haben
- Starte den Raspberry Pi Imager und wähle dann im User Interface "Raspberry PI OS (32-BIT)" als Betriebssystem aus
- Wähle im User Interface des Raspberry Pi Imager, die SD Karte aus, die du eben mit deinem Computer verbunden hast
- Wähle im User Interface des Raspberry Pi Imager, die SD-Karte aus, die du eben mit deinem Computer verbunden hast
- Um den Prozess, der Betriebssystemübertragung zu beginnen, wähle entsprechend "SCHREIBEN" aus
- Bestätige, dass alle Daten auf der SD Karte gelöscht werden können
- Sobald die Bestätigung angezeigt wird, dass "Raspberry Pi OS (32-bit)" auf der eingelegten SD Karte gespeichert wurde, kann diese vom Computer entfernt werden und in den Raspberry Pi eingelegt werden (der Slot dafür ist auf der Unterseite des RaspberryPi, gegenüber der USB-Anschlüsse)
- Bestätige, dass alle Daten auf der SD-Karte gelöscht werden können
- Sobald die Bestätigung angezeigt wird, dass "Raspberry Pi OS (32-bit)" auf der eingelegten SD-Karte gespeichert wurde, kann diese vom Computer entfernt werden und in den Raspberry Pi eingelegt werden (der Slot dafür ist auf der Unterseite des RaspberryPi, gegenüber der USB-Anschlüsse)
- Solange das Überspielen auf die SD-Karte läuft, können schon die nächsten Schritte bis zum Stromanschluss durchgeführt werden
- Nutze zwei der vier USB Ports am Raspberry Pi um sowohl Tastatur, als auch eine Maus an den Raspberry Pi anzuschließen
- Nutze den Mini-HDMI Port mit der Aufschrift "HDMI0" um einen Bildschrim mit dem Raspberry Pi zu verbinden
- Nutze zwei der vier USB-Ports am Raspberry Pi um sowohl Tastatur, als auch eine Maus an den Raspberry Pi anzuschließen
- Nutze den Mini-HDMI Port mit der Aufschrift "HDMI0" um einen Bildschirm mit dem Raspberry Pi zu verbinden
- Optional wäre über "HDMI1" ein weiter Bildschirm verbindbar
- Schließe das RaspberryPi Netzteil an der Buchse mit der Bezeichnung "POWER IN" an, um den Raspberry Pi mit dem Strom zu verbinden
- Sofern dein Bildschirm eingeschaltet ist, sollte der Raspberry Pi nun starten und eine graphische Nutzerberfläche angezeigt werden, dies kann ein paar Minuten dauern.
- Sofern dein Bildschirm eingeschaltet ist, sollte der Raspberry Pi nun starten und eine grafische Nutzeroberfläche angezeigt werden, dies kann ein paar Minuten dauern.

# initiales Starten Raspberry Pi
- Es kann sein, dass es zu der Meldung kommt "Resized root file system. Rebooting in 5 seconds". Dann einfach abwarten und der Raspberry Pi startet selbständig erneut
Expand Down Expand Up @@ -61,13 +61,16 @@ Zur Info: Eingaben im Terminal können getätigt werden, wenn die (grüne) Zeile
- Für die vorherigen drei Schritte ist eine detaillierte Anleitung unter folgendem Link zu finden: https://github.com/Infineon/i2s-microphone/wiki/Raspberry-Pi-Audio-Processing-with-Python
- Eingabe im Terminal: `pip3 install SoundFile`

## Futtersilo Füllstand Sensor
- Eingabe im Terminal: sudo pip3 install adafruit-circuitpython-vl53l0x

# Hardware anschließen

Die Belegung und Nummerierung der Pins / Ports des Raspberry Pi kann unter anderem hier nachgeguckt werden: https://www.raspberrypi-spy.co.uk/wp-content/uploads/2012/06/Raspberry-Pi-GPIO-Header-with-Photo.png

## Kamera
- Das breite weiße Kamerakabel an einem Ende an die Kamera anschließen und am anderen Ende an den RasperryPi (an den Anschluss der mit Kamera betitelt ist), so, dass das blaue Ende zu den USB Anschlüssen zeigt
- Das Kabel lässt sich sowohl an Pi als auch an Kamera durch das hochziehen, der grauen Abdeckung befestigen. Dieses anschließend wieder runterdrücken um das Kabel zu fixieren
- Das breite weiße Kamerakabel an einem Ende an die Kamera anschließen und am anderen Ende an den RaspberryPi (an den Anschluss der mit Kamera betitelt ist), so, dass das blaue Ende zu den USB-Anschlüssen zeigt
- Das Kabel lässt sich sowohl an Pi als auch an Kamera durch das hochziehen, der grauen Abdeckung befestigen. Dieses anschließend wieder herunterdrücken um das Kabel zu fixieren

## Luftfeuchte und Temperatursensor
- "+" -> Port 1 (3,3 V)
Expand All @@ -94,20 +97,28 @@ Die Belegung und Nummerierung der Pins / Ports des Raspberry Pi kann unter ander
- GND -> Port 20 (GND)
- 3V -> Port 17 (3,3 V)

## Futtersilo Füllstand Sensor
- VIN -> Port 4 (5 V)
- GND -> Port 14 (GND)
- SCL -> Port 5 (GPIO 3/SCL)
- SDA -> Port 3 (GPIO 2/SDA)
- GPIO1 -> Port 7 (GPIO 4)
- XSHUT -> Port 37 (GPIO 26)

# Setup Birdiary
(Je nachdem mit welchen Benutzer man sich am RaspberryPi anmeldet, können die Verzeichnisse abweichen. Solltest du dich nicht mit dem Benutzer 'pi' anmelden, musst du den Verzeichnisnamen gegen Deinen austauschen. Aus /home/pi wird dann /home/<dein Benutzer>)
- Eingabe im Terminal: `cd /home/pi/`
- Eingabe im Terminal: `git clone https://github.com/CountYourBirds/station.git`
- Erstelle unter https://wiediversistmeingarten.org/react/createbox deine eigene Station
- Kopiere die Box-Id in die config.yaml-Datei im Ordner `/home/pi/station`
- Navigiere in den Ordner station und öffne die `config.yaml`-Datei mit geany (Rechtsclick auf die Datei -> Geany)
- Navigiere in den Ordner station und öffne die `config.yaml`-Datei mit geany (Rechtsklick auf die Datei -> Geany)
- Kopiere die Box-id an die entsprechende Stelle in der Datei
- Speichere die Datei (Shortcut: Str + S)

# Ermöglichung des Zugriffs auf den Raspberry Pi via VNC
- Eingabe im Terminal: `sudo nano /boot/config.txt` (detaillierte Anleitung für die Veränderung der Datei hier: https://www.shellhacks.com/raspberry-pi-force-hdmi-hotplug/)
- Navigiere mit den Pfeiltasten der Tastatur zu den den folgenden Zeilen, entferne die Rauten am Anfang der Zeilen und nimm die entsprechenden Anpassungen vor:
- Setze den Paramter hdmi_force_hotplug auf 1: `hdmi_force_hotplug=1`
- Navigiere mit den Pfeiltasten der Tastatur zu den folgenden Zeilen, entferne die Rauten am Anfang der Zeilen und nimm die entsprechenden Anpassungen vor:
- Setze den Parameter hdmi_force_hotplug auf 1: `hdmi_force_hotplug=1`
- Setze den Parameter hdmi_group auf 1: `hdmi_group=1`
- Setze den Parameter hdmi_mode auf 16: `hdmi_mode=16`
- Zum Speichern:
Expand All @@ -125,9 +136,9 @@ Die Belegung und Nummerierung der Pins / Ports des Raspberry Pi kann unter ander
- Auswahl von: Finish
- Auswahl von: Ja (Reboot)
- Kurz abwarten und das `Va` Icon anklicken oben rechts neben dem WLAN Zeichen
- IP Adresse die unter Konnektivität gelistet ist auf Rechner der auf PI zugreifen soll im VNC Viewer eintragen (vorheriger Download der VNC Viewer App für entsprechendes Betriebssystem: https://www.realvnc.com/de/connect/download/viewer/) und mit dem Raspberry Pi verbinden
- IP-Adresse die unter Konnektivität gelistet ist auf Rechner der auf PI zugreifen soll im VNC Viewer eintragen (vorheriger Download der VNC Viewer App für entsprechendes Betriebssystem: https://www.realvnc.com/de/connect/download/viewer/) und mit dem Raspberry Pi verbinden
- Passwort und Benutzername des pis entsprechend eintragen
- Verbindung sollte funktioneren
- Verbindung sollte funktionieren

# Automatische Ausführung ermöglichen
- Eingabe im Terminal: `sudo apt-get install xterm`
Expand Down
6 changes: 4 additions & 2 deletions get_pi_requirements.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ else
fi
printf "\033[0;35m####### Install general python packages#######\033[0m\n"
# General
pip3 install pyyaml
pip3 install pyyaml ruamel.yaml
pip3 install schedule
pip3 install --upgrade numpy

printf "\033[0;35m####### Install Senors #######\033[0m\n"
# Sensors
sudo pip3 install adafruit-circuitpython-dht
sudo pip3 install adafruit-circuitpython-dht adafruit-circuitpython-vl53l0x
sudo apt-get install libgpiod2

# Microphone
Expand All @@ -55,8 +55,10 @@ xrdb -merge ~/.Xresources
#add Desktop Starter
##change ~/station to absolute Path, because ~ is not working for Starter.
sed -i "s|~/station|$HOME/station|g" birdiary.desktop
sed -i "s|~/station|$HOME/station|g" silolevel_calibrate.desktop
## copy modified starter to Desktop
cp ~/station/birdiary.desktop ~/Desktop
cp ~/station/silolevel_calibrate.desktop ~/Desktop

# activate the HDMI output, even if no monitor is detected
sudo sed -i '3ahdmi_force_hotplug=1' /boot/config.txt
Expand Down
96 changes: 87 additions & 9 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import requests

dev_mode = False
silolevel_active: bool = False
if not dev_mode:
import requests

Expand Down Expand Up @@ -118,6 +119,36 @@
SENSOR_PIN = D16 # use not board but GPIO number
dht22 = adafruit_dht.DHT22(SENSOR_PIN, use_pulseio=False)

# Set Silolevel Sensor
logging.info("Setup Silolevel Sensor!")
if yamlData["environment_values"]["silolevel"]:
if yamlData["hardware"]["vl53l0x"]["empty_value"] == 0 and yamlData["hardware"]["vl53l0x"]["empty_value"] == 0:
silolevel_active = False
logging.warning("Silolevel Sensor not calibrated yet. Please calibrate the sensor first")
print("\033[91mSilolevel Sensor not calibrated yet. Please calibrate the sensor first. Will start without the "
"Sensor\033[0m")
time.sleep(1)
else:
try:
import silolevel
try:
silo = silolevel.SiloLevelSensor(int(yamlData["hardware"]["vl53l0x"]["GPIO1_PIN"]),
int(yamlData["hardware"]["vl53l0x"]["XSHUT_PIN"]),
yamlData["hardware"]["vl53l0x"]["i2cAddress"])
logging.debug("Silolevel Sensor initiated")
silolevel_active = True
except (ValueError, IOError):
silolevel_active = False
logging.error("Sensor not found! Check the connections")
except ModuleNotFoundError:
silolevel_active = False
logging.error("WARNING! Silolevel Sensor Library not installed, start Script without Sensor\n Please "
"restart get_pi_requirements.sh")
time.sleep(1)
else:
silolevel_active = False
logging.debug("Silolevel Sensor deactivated in configuration")
print("Silolevel Sensor deactivated in configuration")
# Setup Balance
logging.info("Setup balance!")
EMULATE_HX711 = False
Expand Down Expand Up @@ -147,8 +178,10 @@
from rec_unlimited import record
from multiprocessing import Process
from pydub import AudioSegment # for converting the raw to mp3

audio_gain = yamlData["station"]["audio_gain"]
logging.info("Setup finished!")
logging.info("Setup finished!")


def write_environment(environment_data):
filename = 'environments/' + environment_data['date'] + '.json'
Expand Down Expand Up @@ -198,8 +231,29 @@ def send_realtime_environment(environmentData):
write_environment(environmentData)
else:
send_data()

# Function to track a environment


def send_realtime_feed(box_id, feedData: dict = {}):
if dev_mode:
logging.warning('send_feed deactivated')
logging.warning('received: ' + str(feedData))
else:
try:
r = requests.post(serverUrl + "feed/" + str(box_id), json=feedData)
print("Silolevel Data send with the corresponding feed_id")
print(r.content)
logger.info('Silolevel send to Server')
logger.debug('Feed Post Request Data: URL: %s ; status_code: %s; Text: %s ;json: %s' %
(r.url, r.status_code, r.text, feedData))
except (requests.ConnectionError, requests.Timeout) as exception:
logging.warning('No internet connection. ' + str(exception))
logging.warning("Saving Silolevel data to send later")
# write_environment(environmentData)
else:
send_data()
# Function to track a environment


def track_environment():
try:
logging.info("Collect Environment Data")
Expand All @@ -215,7 +269,7 @@ def track_environment():
except Exception as e:
logging.error(e)


# predefined variables
environmentData = None
audio_filename = None
Expand All @@ -225,6 +279,7 @@ def track_environment():
temp_audio_filename = 'temp/audio.raw' # the filename extension has to be .raw to convert it later to mp3
data_filename = None
recorder = None
feedData: dict = {}


def tare():
Expand All @@ -250,13 +305,17 @@ def set_filenames(movementStartDate):
global data_filename
data_filename = 'savedMovements/' + str(movementStartDate) + '.json'


# Function to track a movement
def track_movement():
values = []

# schedule an environment track for every x minutes
schedule.every(environmentTimeDeltaInMinutes).minutes.do(track_environment)
track_environment()
if silolevel_active:
schedule.every(environmentTimeDeltaInMinutes).minutes.do(track_feed)
track_feed()
schedule.every(weightResetInMinutes).minutes.do(tare)

while True:
Expand Down Expand Up @@ -313,9 +372,9 @@ def track_movement():
# stop audio recording and move temporary file to output directory
terminate_recorder()
tags_json = dict(title=(movementStartDate.strftime("%Y-%M-%d %H:%m:%S") + '_' + boxId),
track=1, artist=boxId,
copyright='www.wiediversistmeingarten.org',
genre="Noise", date=movementStartDate.strftime("%Y-%M-%d"))
track=1, artist=boxId,
copyright='www.wiediversistmeingarten.org',
genre="Noise", date=movementStartDate.strftime("%Y-%M-%d"))
RawAudio = AudioSegment.from_raw(temp_audio_filename, sample_width=2, frame_rate=48000, channels=1)
RawAudioVolumeLifted = RawAudio.apply_gain(audio_gain) # lift up the volume
RawAudioVolumeLifted.export(audio_filename, format='mp3', tags=tags_json, id3v2_version="3")
Expand All @@ -340,7 +399,26 @@ def track_movement():
except (KeyboardInterrupt, SystemExit):
cleanAndExit()



def track_feed():
try:
print("Collect Feed Data")
logger.info('Collect Feed Data')
feed: dict = {"date": str(datetime.now()),
"silolevel": silo.read_Silolevel(int(yamlData["hardware"]["vl53l0x"]["empty_value"]),
int(yamlData["hardware"]["vl53l0x"]["full_value"]))
}

print("Feed Data: ", feed)
logger.info('Feed Data: %s' % feed)
send_realtime_feed(boxId, feed)
global feedData
feedData = feed
except Exception as e:
print(e)
logger.exception(e, exc_info=True)


def cleanAndExit():
camera.close()
terminate_recorder()
Expand Down
Loading