RaspberryPi

Erstellt am 4.8.2020 für Raspberry Pi 3 Model B+ oder Raspberry Pi 4.

Ziel

Temperaturmessung und Darstellung der Werte über ein Mobile durch ansurfen einer Web-Page auf dem RaspberryPi.

1. Installation

SD-Karte formatieren im FAT32 Format über Windows-Explorer. Wenn SD-Card grösser als 32 GByte, so wird ein zusätzliches Tool benötigt wie z.B. AOMEI Partition Assistant Standard Edition.

Installation dauert über 1 Stunde! Von www.raspberrypi.org unter Download aktuelles NOOBS Lite „Network install only“ (nicht offline) downloaden. Voraussetzung ist Netzwerk-Zugriff. Anschliessend auf SD-Karte entpacken.

Dann SD-Karte in RaspberryPi einsetzen und starten. Zuerst Sprache Deutsch und Tastatur CH eingeben, dann WLAN verbinden. Raspbian mit Desktop ankreuzen. Achte auf den Speicherbedarf. Es kann auch ein Raspberry Pi OS mit Desktop mit weniger Speicherbedarf verwendet werden. Dann installieren und den Installationsanweisungen folgen.

Folgende Einstellungen bei Raspberry-Pi-Konfiguration vornehmen, über Einstellungen>Raspberry-Pi-Konfiguration>Schnittstellen mit folgenden Anpassungen:

  • Auflösung festlegen, sodass diese auch über Remote festgelegt ist, z.B. DMT 1920x1200 60Hz. 2)
  • aktivieren SSH (für Datei-Zugriff mit SFTP)
  • aktivieren VNC (für Remote-Desktop-Zugriff)
  • aktivieren I2C und SPI (für PIOLED und BME680-Sensor)
  • aktivieren Serial Port (für Modbus-Kommunikation mit RS485)
  • DEaktivieren Serial Console

Über die Konsole fragen wir die ip-Adresse ab mit

ifconfig

Anschliessend verbinden wir unser Notebook mit der RaspberryPi über den VNC Viewer und benötigen somit keine Bildschrim und Tastatur mehr.

Beispielprojekt installieren

Dir installieren das funktionierende Django-Beispiel von github.com/markstaler/djangoProjekt Wir beziehen dies direkt von Github in "home/pi" Verzeichnis und geben folgendes auf der Konsole ein:

git clone https://github.com/markstaler/djangoProjekt


SW-Pakete

Anschliessend werden einige Programme installiert. Wir könnten Spyder installieren, jedoch ist dies nicht performant und verwenden deshalb den IDE (Integrated Development Enviroment) "Thonny Python IDE". Die Bibliothek pil (Python Image Library) für das PIOLED-Display ist bereits installiert. Möchte man dieses installieren so ist der Linux-Package-Installer "apt-get" notwendig: "sudo apt-get install python3-pil" oder "sudo apt-get install spyder3".

Für die Python-Bibliotheken verwenden wir den Python-Package-Installer "pip3" für Python3. Die Pakete sind in der requirements.txt definiert, welche wir über git und dem Beispielprojekt in den Ordner "djangoProjekt" geladen haben.

sudo pip3 install -r requirements.txt

Darin sind die folgenden Pakete:

bokeh~=2.0.0 
django~=3.0.4
pandas~=1.0.1
pyserial~=3.4
adafruit-circuitpython-ssd1306
bme680

Wir arbeiten mit Python 3.x. Um Bibliotheken hierfür zu installieren muss darauf geachtet werden das die "3"-Version verwendet wird. Z.B. pip3 anstatt pip oder spyder3 anstatt spyder. Ohne "3" wird die Version für Python 2.x verwendet. Der Raspberry benötigt für das System beide Versionen! Standardmässig wird Python2.x verwendet. Erkennbar durch "python --version", oder man startet auf der Console "python" und führt die Division 3/2 durch. Python2.x liefert 1. Wird auf der Konsole "python3" gestartet ergibt 3/2 = 1.5.

2) Hinweis Raspberry Pi4: Auflösung bei nicht angeschlossenem Monitor (headless) über VNS kann nichtmehr im Menü eingestellt werden. Dies muss in der /boot/config.txt Datei erfolgen mittels:

hdmi_force_hotplug=1 
hdmi_group=2
hdmi_mode=0x45 

see: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=5851

Autostart Display

Erstelle eine Datei autostartRPI.desktop im neuzuerstellenden Ordner /home/pi/.config/autostart mit folgendem Inhalt:

[Desktop Entry]
Encoding=UTF-8
Name=autostartRPI
Exec=lxterminal -e "/home/pi/djangoProjekt/startRPI"
Icon=lxterminal
Type=Application
Categories=Utility;

Wir erstellen eine sh-Datei (wie bat-Datei unter Windows), welche das Python-Skript im Arbeitsordner startet, sodass die relativen Pfade stimmen. Datei startRPI (ohne Endung) im Ordner djangoProjekt anlegen:

#! /bin/sh
cd /home/pi/djangoProjekt
python3 daqStart.py


Rechte setzen: sudo chmod 755 dateiname, bei startRPI und startRPI.desktop

WLAN Einstellung

Die WLAN-Verbindung definieren wir direkt in der Konfigurationsdatei /etc/wpa_supplicant/wpa_supplicant.conf. Wir können hierfür den Editor nano auf der Konsole verwenden durch folgenden aufruf:

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

oder wir öffnen den Editor "sudo geany" auf der Oberfläche. In der Datei führen wir alle WLAN-Netzwerke an, wie z.B. das eduroam oder das WLAN-Netz zuhause.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=CH

network={
            ssid="wlan_zuHause"
            psk="passwort"
}

network={
            ssid="gast-ntb"
            psk="passwort"
}    

(eduroam funktioniert nicht)

Sensor BME680 anschliessen

Der RPI hat eine I2C Schnittstelle welche wir bereits durch das PIOLED verwenden. Natürlich können mehrere Busteilnehmer an eine I2C-Schnittstelle lögisch angeschlossen werden, jedoch wollen wir die Verdrahtung einfach halten mit Bückendrähte mit Buchsen (Jumper Wire Female). Deshalb konfigurieren wir eine zweite I2C-Schnittstelle auf

Pin 16 SDA (Serial Data)  - GPIO 23
Pin 18 SCL (Serial Clock) - GPIO 24
Pin 17 3V3
Pin 20 GND

i2c auf Standardkonfiguration: SMBus(1) SDA=GPIO2=Pin3 und SDL=GPIO3=Pin5 i2c auf SMBus(2) SDA=GPIO23=Pin16 und SDL=GPIO24=Pin18. Muss beim Rasperry Pi konfiguriert werden unter /boot/config.txt:

dtoverlay=i2c-gpio,bus=2,i2c_gpio_delay_us=1,i2c_gpio_sda=23,i2c_gpio_scl=24

BME Sensor auf zweiter I2C Schnittstelle

Bei RPI legen wir dies in der Datei /boot/config.txt fest, durch den Eintrag bei der I2C-Konfiguration:

dtoverlay=i2c-gpio,bus=2,i2c_gpio_delay_us=1,i2c_gpio_sda=23,i2c_gpio_scl=24

Anschliessend ist ein "sudo reboot" notwendig. Im Python-Script greifen wir auf den von uns konfigurierten Bus2 zu durch:

smbus2 = smbus.SMBus(2)    


Datenerfassung

Die Datenerfassung (data aquesition) erfolgt über die Datei daqStart.py Es wird das PIOLED-Display und der BME680-Sensor initialisiert. Anschliessend wird die IP-Adresse abgefragt und über diese der Django-Entwicklungsserver gestartet.

Nach diesen Startaktivitäten wird die while-Schleife begonnen, welche zyklisch die Sensordaten in eine SQLite-Datenbank speichert. Ist diese Datenbank nicht vorhanden, so wird diese angelegt.

Visualisierung Django

Die Visualisierung erfolgt über Django. Wir verwenden dabei die Webseite vom Tutotial Visualisierung von https://pv4ing.ch. Der Verlauf von Temperatur, relativer Luftfeuchte und Luftdruck wir als Bokeh-Diagramm dargestellt und in views.py erzeugt über die Funktion makeChart(nCycle) welche wir folgt angepasst wird:

def makeChart(nCycle):
    zeit = dt.datetime.now() - dt.timedelta(days=nCycle)
    zeit = zeit.strftime('%Y-%m-%d')
    db = sqlite3.connect('dataDB.sqlite3')
    df = pd.read_sql_query('SELECT * FROM tabelle WHERE zeit>strftime("%Y-%m-%d","'+zeit+'")', db)
    df = pd.read_sql_query('SELECT * FROM tabelle', db)
    db.close() 

    df['zeit'] = pd.to_datetime(df['zeit'])
    tStr = [] # Zeit als String um später mit Tool Tip anzeigen zu können
    for i in df['zeit']:
        tStr.append(i.strftime('%Y-%m-%d %H:%M:%S'))
    df['tStr'] = tStr

    werkzeuge =  "pan, box_zoom, reset, save, hover"
    tt = [('Zeit:','@tStr'), ('y:', '$y')]
    ph = 300
    pw = 1000

    ## Temperatur ##
    p1 = figure(title='Temperatur', plot_width=pw, plot_height=ph, /
                x_axis_type='datetime', tooltips = tt, tools = werkzeuge)
    p1.line(x = 'zeit', y = 'temp', source = df, legend_label = 'Temperatur',  color='green')
    p1.xaxis.axis_label = 'Zeit'
    p1.legend.location = 'top_right'
    p1.legend.click_policy="hide" # Kurve ein/ausschaltbar
    p1.toolbar.logo = None

    ## Rel.Feuchte ##
    p2 = figure(title='Relative Feuchte', plot_width=pw, plot_height=ph, /
                x_axis_type='datetime', tooltips = tt, tools = werkzeuge)
    p2.line(x = 'zeit', y = 'humi', source = df, legend_label = 'Rel. Feuchte',  color='blue')
    p2.xaxis.axis_label = 'Zeit'
    p2.legend.location = 'top_right'
    p2.legend.click_policy="hide" # Kurve ein/ausschaltbar
    p2.toolbar.logo = None    
    p2.x_range = p1.x_range

    ## Luftdruck ##
    p3 = figure(title='Luftdruck', plot_width=pw, plot_height=ph, /
                x_axis_type='datetime', tooltips = tt, tools = werkzeuge)
    p3.line(x = 'zeit', y = 'prea', source = df, legend_label = 'Luftdruck',  color='blue')
    p3.xaxis.axis_label = 'Zeit'
    p3.legend.location = 'top_right'
    p3.legend.click_policy="hide" # Kurve ein/ausschaltbar
    p3.toolbar.logo = None    
    p3.x_range = p1.x_range

    ## VOC ##
    p4 = figure(title='VOC', plot_width=pw, plot_height=ph, x_axis_type='datetime', tooltips = tt, tools = werkzeuge)
    p4.line(x = 'zeit', y = 'vocR', source = df, legend_label = 'VOC',  color='blue')
    p4.xaxis.axis_label = 'Zeit'
    p4.legend.location = 'top_right'
    p4.legend.click_policy="hide" # Kurve ein/ausschaltbar
    p4.toolbar.logo = None    
    p4.x_range = p1.x_range

    allCharts = column(p1, p2, p3, p4) 
    script, div = components(allCharts)
    chart = script + div
    return chart
In [ ]: