Schlagwort-Archive: Python

IR-Thermokamera an Raspberry PI

Lepton Camera Module

Ein vielleicht interessantes kleines Projekt ist, ein Lepton Kameramodul mit einem Raspberry zu betreiben.  In meinem Fall verwende ich ein Lepton Modul mit 80×60 Pixeln bei einer Pixelgröße von 17µm und einer spektralen Empfindlichkeit im langwelligen Infrarot Bereich von 8µm bis 14µm. Die Framerate beträgt maximal 8,6 Hz. Das Kameramodul wird in ein Breakout-Board gesteckt und dieses mit dem Raspberry PI verbunden. Die Infos dazu gibt‘s weiter unten. Es gibt auch im Entwicklerbereich der Website flir.lepton.com eine Anleitung wie das Breakoutboard mit dem Raspi betrieben wird.

Camera Module mit Breakout Board V1.4

Benötigt wird ein Raspberry PI (in diesem Beispiel habe ich einen Raspberry PI4 verwendet), ein Lepton Thermal Kamera Breakout Board V1.4 und ein wenig Drahtwerk für die Verbindungsleitungen. Die genaue Teileliste (um auch alles Aufbauen und in Betrieb nehmen zu können) ist unten angeführt:

  • Raspberry PI (Modell 2,3 oder 4)
  • Micro SD-Karte (ab 8GB)
  • USB-Steckernetzteil mit Micro USB (oder USB-C) Kabel (je nach Raspberry PI Modell)
  • LAN-Kabel und Zugang zu einem Switch oder Router mit bestehender Internetverbindung
  • Idealerweise einen Rechner mit (SD-Karten-Slot) um das Image für den Raspberry vorzubereiten
  • Ein Monitor für den Raspberry PI mit HDMI oder MINI-HDMI-Kabel
  • USB-Tastatur, Maus
  • Lepton Thermal Kamera Breakout Board

Ist alles vorhanden, dann ist die Verdrahtung des Kamera Moduls mit dem PI herzustellen. Am einfachsten verwendet man die Jumper-Kabel (Female-Female) die in der Modulbastelwelt sehr beliebt sind. Ein Lötkolben ist für viele Demo- und Testaufbauten nicht mehr notwendig… Die folgende Skizze zeigt die herzustellende Verdrahtung:

Klicken zum Vergrössern

Das Pinning ist hier nochmals angeführt:

  • Raspi GPIO PIN01 (3V3)     –>    Lepton Pin VIN
  • Raspi GPIO PIN03 (SDA)    –>     Lepton Pin SDA
  • Raspi GPIO PIN05 (SCL)      –>    Lepton Pin SCL
  • Raspi GPIO PIN06 (GND)   –>     Lepton Pin GND
  • Raspi GPIO PIN19(MOSI)  –>     Lepton Pin MOSI
  • Raspi GPIO PIN21(MISO)  –>     Lepton Pin MISO
  • Raspi GPIO PIN23(CLK)      –>     Lepton Pin CLK
  • Raspi GPIO PIN24(CEO)     –>     Lepton Pin CS

Als Betriebssystem für den Raspberry Pi habe ich Raspbian installiert. Das geht entweder über den Download des RASPBIAN Images von der Webseite https://www.raspberrypi.org/downloads/raspbian oder auch über den NOOBS Installer. Mit dem Tool „etcher“ oder „win32diskimager“ kann die Image Datei auf die SD-Karte geschrieben werden. Wer mit NOOBS arbeitet braucht nur die zip-Datei auf die FAT32 formatierte SD-Karte zu entpacken. Ist das erledigt, dann einfach die SD-Karte in den Raspberry stecken, Monitor, Keyboard und Maus an den PI anstecken und zum Schluss die Stromversorgung aktivieren. Wenn NOOBS auf der Karte ist, dann wird nach dem Start eine Auswahl an zu installierenden Betriebssystemen angezeigt. Hier am besten auch RASPIAN auswählen und die Installation starten. Ist das abgeschlossen, dann ist je nach gewähltem Image entweder nur eine Konsole oder eben ein Desktop zu sehen. Im letzten Fall ist dann ein Terminal zu öffnen, damit in der Konsole weitergearbeitet werden kann.

Mit sudo raspi-config ist nach dem login in die Konsole das Raspberry PI Config – Tool zu öffnen. Darin sind folgende Services zu aktivieren:

  • SPI (unter Advanced Options)
  • SSH (unter Advanced Options)
  • I2C (unter Advanced Options)
  • Enable Camera (im Hauptmenu des raspi-config tools)

Danach ist der Raspberry zu rebooten. Nach dem erneuten Start und login (als User pi mit default Passwort raspberry) muss das Paket openCV installiert werden. Mit sudo apt-get install python-opencv ist das erledigt.

Auf GitHub habe ich eine Python Library von brandoncurtis und kekiefer für das Lepton Board gefunden. Die Library nennt sich pylepton und ist auf https://github.com/groupgets/pylepton zu finden.

Mit git clone https://github.com/kekiefer/pylepton.git legen wir das Repository  an und wechseln danach in das Verzeichnis cd pylepton. Jetzt kann das Setup Skript ausgeführt werden: sudo python setup.py install.

Mit dem folgenden kleinen Codebeispiel wird die Lepton Kamera ausgelesen, das 80×60 Pixel große Bild auf 800% skaliert und angezeigt.

 

 import numpy as np  
 import cv2  
 from pylepton import Lepton  
 with Lepton() as lepi:  
  a,_ = lepi.capture()  
 cv2.normalize(a, a, 0, 65535, cv2.NORM_MINMAX) # extend contrast  
 np.right_shift(a, 8, a) #daten in 8bit anpassen 
 cv2.imwrite("thermobild.jpg", np.uint8(a)) #bild schreiben 
 img=cv2.imread('thermobild.jpg')  
 cv2.imshow('Thermobild', img)  
 print('Originalabmessungen: ',img.shape)  
 scale_percent = 800  
 width = int(img.shape[1] * scale_percent / 100)  
 height = int(img.shape[0] * scale_percent / 100)  
 dim = (width, height)  
 resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)  
 print('Achtfach vergroessert: ',resized.shape)  
 cv2.imshow("Thermobild 8x", resized)  
 cv2.waitKey(0)  
 cv2.destroyAllWindows()  
 exit()  

Das Ergebnis sieht dann zum Beispiel so aus:


 

 

Diodenkennlinie mit Sourcemeter und Matlab aufnehmen

Dieses Mal gibt es hier keinen Bericht über die Restauration oder die Vorstellung eines alten Gerätes. Im Rahmen meiner beruflichen Tätigkeit muss ich immer wieder Messaufbauten realisieren und diese nach Möglichkeit automatisieren, um die Messzeiten zu minimieren. Auch die Datenauswertung und das Postprocessing möchte ich immer gerne automatisieren. Dafür gibt es sehr viele unterschiedliche Lösungsansätze. Der Grundansatz ist aber immer gleich. Ein, oder mehrere Messgeräte sind über eine Schnittstelle mit einem Rechner oder Controller verbunden. Auf dem Rechner oder Controller läuft eine Software, die das Messgerät steuert und die gemessenen Daten an den Rechner zurücksendet. Auf dem Rechner werden die Daten dann gespeichert, den Anforderungen entsprechend aufbereitet und ausgegeben.

Die Schnittstellen zwischen Rechner und Messtechnik können je nach Ausstattung des Messgerätes dabei RS232, GPIP, IEEE1394, USB oder LAN sein. Bei vielen Geräten wird der einfache SCPI-Befehlssatz im ASCII Code zum Befehle senden und empfangen über das entsprechende Protokoll der gewählten Schnittstelle verwendet. Die Software am Rechner oder Controller muss in der Lage sein die Hardware anzusprechen und schon kann eine Datenkommunikation hergestellt werden. Als Software oder Skriptsprache kann hier beispielsweise NI-LabVIEW, Matlab, C-Code, C++ Code, C#, Python, etc. verwendet werden. Und die Rechner- oder Controllerhardware kann ein Windows, Mac, oder LinuxPC sein, aber auch ein einfacher Arduino, RaspberryPi, oder ein programmierter Mikro-Controller, der eine der benötigten Schnittstelleninterfaces besitzt.

Bei meiner Arbeit wird das gerne mit Matworks Matlab gemacht (bzw. ich mache es gerne mit Matlab, weil ich Programme und Skripten lieber tippe als sie zu zeichnen 😀 ), einer skriptorientierten Software. Im konkreten Beispiel habe ich ein SOURCEMETER des Herstellers Keithley, das Keithley2400 über die RS232 Schnittstelle an einem WIN10 PC mit Matlab 2017b angesteuert. Das Sourcemeter hat die Aufgabe eine Diodenkennlinie aufzunehmen. Das Sourcemeter ist imstande einen Strom zu sourcen, also eine steuerbare Stromquelle zu sein und gleichzeitig den gesourcten Strom und die an den Klemmen anliegende Spannung zu messen. Umgekehrt wiederum kann es auch als steuerbare Spannungsquelle eingesetzt werden, die Spannung an den Klemmen und den Strom durch den DUT (Device Under Test) messen.  Und das geht in allen vier Quadranten, also Stromquelle oder -Senke, oder Spannungsquelle oder -Senke sein.

Genau das benötigte ich in diesem supereinfachen Beispiel um die Kennlinie eines PN-Überganges aufzunehmen und zwar vom Diffusionsbereich bis in den Durchlassbereich und natürlich auch wenn der PN-Übergang unter Photonenbeschuss steht 🙂

Die folgenden beiden Matlab-Skripten ermöglichen diese einfache Kennlinienaufnahme. Der Messaufbau selbst besteht lediglich aus einer, an die Klemmen des K2400 angeschlossenen Diode (in diesem Fall eine Photozelle). Dabei stellt das erste Skript eine gesteuerte Stromquelle dar und im zweiten Skript wird die Spannungsquelle durchgesteuert und jeweils die Daten aufgezeichnet und zum Schluss als Plot dargestellt.

 Matlab Code stromgetrieben:

% IV Logger PN Kennlinie
% 2.05.2019 ingmarsretro
% der supereasysimple-code
% drive current and measure voltage
% with sourcemter über RS232 

 serialObject = serial('COM4','BaudRate',19200, 'DataBits',8);   

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Sourcemeter 2400 setup                             %
    % serial config: 8N1, 19200, termchar CR+LF          %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
    fopen(serialObject)
    s.InputBufferSize = 6000;
    fprintf(serialObject,'*RST');
    
    mincurr = -15E-3;  % maximaler negativer strom (load an der Zelle) 
    maxcurr = 10E-4;   % maximaler positiver strom 
    step = 1E-5;       % schrittweite
    

    %%%%%%%%%%%%%%%%%%%%%%%%%%
    % Messgeraet einstellen  %
    %%%%%%%%%%%%%%%%%%%%%%%%%%
    % SOURCING ->  CURRENT
    %
    %fprintf(serialObject,':INIT:CONT OFF;:ABOR');
    fprintf(serialObject,':FORM:DATA ASCII');
    fprintf(serialObject,':SOUR:FUNC CURR');
    fprintf(serialObject,':SOUR:CURR:MODE FIX');
    fprintf(serialObject,':SOUR:CURR:RANG 10E-2'); % -> 000.000mA
    fprintf(serialObject,':SOUR:CURR:LEV 0.0'); % -> Starteinstellung 0 A
    
    % MEASUREMENT -> Spannung 
    fprintf(serialObject,':SENS:FUNC "VOLT:DC"');
    fprintf(serialObject,':SENS:VOLT:PROT 8');     % -> compliance 8V
    fprintf(serialObject,':SENS:VOLT:RANG 10E-1'); % -> 0.00000 V
    fprintf(serialObject,':TRIG:COUN 1');
    
    %fprintf(serialObject,':CONF:VOLT:DC');
    
    fprintf(serialObject,':OUTP ON');

        %% Messen und Daten abholen
    count = 1; 
    v(1)=0; i(1)=0;  %init der arrays 
   
       for curr = mincurr:step:maxcurr
           
          strom=num2str(curr);
          command = strcat(':SOUR:CURR:LEV ',{' '},strom);
          fprintf(serialObject,char(command));
         

          fprintf(serialObject,':READ?');
          data=fscanf(serialObject);  % gesamten buffer des device einlesen
          c = strsplit(data,',');          % gelesenen string nach ',' in zellen zerlegen
          i(count) = str2num(cell2mat(c(2)));                 % stromzelle 
          v(count) = str2num(cell2mat(c(1)));                 % spannungszelle
        

        count = count +1;
       end
   
    
    figure(1);
    plot(v,i);
    grid on; hold on;
    xlabel('voltage [V]'); ylabel('current [A]')
    title('IV - Kennlinie ');
    
    %% instrument in local mode schalten
    fprintf(serialObject,':OUTP OFF');
    fprintf(serialObject,'SYSTEM:LOCAL');
    fclose(serialObject);

 

Matlab Code spannungsgetrieben:

% IV Logger PN Kennlinie
% 3.05.2019 ingmarsretro
% der supereasysimple-code
% drive current and measure voltage
% wit sourcemter über RS232 

 serialObject = serial('COM4','BaudRate',19200, 'DataBits',8);   

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Sourcemeter 2400 setup                             %
    % serial config: 8N1, 19200, termchar CR+LF          %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
    fopen(serialObject)
    s.InputBufferSize = 6000;
    fprintf(serialObject,'*RST');
    
    minvolt = -1;      % maximale negative spannung  
    maxvolt = 0.5;       % maximale positive spannung
    
    %mincurr = -20E-3;  % maximaler negativer strom (load an der Zelle) 
    %maxcurr = 10E-4;   % maximaler positiver strom 
    
    step = 1E-2;       % schrittweite
    
    % 
    %%%%%%%%%%%%%%%%%%%%%%%%%%
    % Messgeraet einstellen  %
    %%%%%%%%%%%%%%%%%%%%%%%%%%
    % SOURCING ->  VOLTAGE
    %
    %fprintf(serialObject,':INIT:CONT OFF;:ABOR');
    fprintf(serialObject,':FORM:DATA ASCII');
    fprintf(serialObject,':SOUR:FUNC VOLT');
    fprintf(serialObject,':SOUR:VOLT:MODE FIX');
    fprintf(serialObject,':SOUR:VOLT:RANG 10E-0');    % -> 00.0000 V
    fprintf(serialObject,':SOUR:VOLT:LEV 0.0');       % -> Starteinstellung 0 V
    
    % MEASUREMENT -> CURRENT 
    fprintf(serialObject,':SENS:FUNC "CURR:DC"');
    fprintf(serialObject,':SENS:CURR:PROT 40E-3');     % -> compliance 10.0000 mA
    fprintf(serialObject,':SENS:CURR:RANG 10E-2');     % -> 0.00000 mA  (muss kleiner als complience sein)
    fprintf(serialObject,':TRIG:COUN 1');
    
    %fprintf(serialObject,':CONF:VOLT:DC');
    
    fprintf(serialObject,':OUTP ON');


        %% Messen und Daten abholen
    count = 1; 
    v(1)=0; i(1)=0;  %init der arrays 
   
       for volt = minvolt:step:maxvolt
           
          spannung=num2str(volt);
          command = strcat(':SOUR:VOLT:LEV ',{' '},spannung);
          fprintf(serialObject,char(command));
           


          fprintf(serialObject,':READ?');
          data=fscanf(serialObject);  % gesamten buffer des device einlesen
          c = strsplit(data,',');          % gelesenen string nach ',' in zellen zerlegen
          i(count) = str2num(cell2mat(c(2)));                 % stromzelle 
          v(count) = str2num(cell2mat(c(1)));                 % spannungszelle
        
        

        count = count +1;
       end
   
    
    figure(1);
    plot(v,i);
    grid on; hold on;
    xlabel('voltage [V]'); ylabel('current [A]')
    title('IV - Kennlinie ');
    
    %% instrument in local mode schalten
    fprintf(serialObject,':OUTP OFF');
    fprintf(serialObject,'SYSTEM:LOCAL');
    fclose(serialObject);

 

Das Ergebnis der beiden Skripten ist der folgende Kennlinienverlauf:

USB Camera an Raspberry PI mit OSD

In diesem Projekt stelle ich eine Anwendung des Raspberry PI im Bereich Bilderfassung vor. Es gibt zu diesem Thema etliche Foren und Beiträge im Internet, doch eine direkt geeignete Lösung war nicht zu finden. Darum poste ich hier meine Lösung.

Als Aufgabenstellung  soll eine Platinenbohrmaschine der Firma Lemmen von der optischen Version (Bohrlochzentrierung per Lupe) in eine opto-elektronische Version (Bohrlochzentrierung auf Bildschimmonitor) kostengünstig umgebaut werden.

Lemmon „Variodrill“ Bild: Herstellerwebsite

Die Bohrmaschine soll dahingehend modifiziert werden, dass die zur Sichtkontrolle verwendete Lupe mit sechsfacher Vergrößerung durch eine Kamera ersetzt wird. Das Kamerabild soll auf einem LCD Computermonitor dargestellt werden. Eine geeignete Kamera war schnell gefunden. Hier gibt es günstige Mikroskopkameras, die eine variable Vergrößerung bis 200fach erreichen. Eine solche Kamera ist beispielsweise die DigiMicro Scale von „dnt“. Allerdings ist das eine USB-Kamera, die einen PC und eine geeignete Software benötigt, um ein Bild anzuzeigen. Und ein PC ist wiederum nicht unbedingt eine kostengünstige Lösung. Weiters käme auch eine CVBS Kamera (also eine analoge Videocamera) in Frage, die einfach an einen geeigneten Bildschim (oder PC-Monitor mit Upscaler/Converter) geschaltet werden müsste. Aber das ist nicht zeitgemäß … Weiters soll das Bild ja nicht nur das Bohrloch vergrößern, sondern auch noch die Vorzüge eines Zielvisieres, also eines Fadenkreuzes oder Kreisabsehens implementieren. Dafür bräuchte man im analogen Bereich wieder einen OSD- (OnScreenDisplay) Generator oder zumindest einen Edding, der das Kreuz gemalt auf dem Bildschirm darstellt 🙂

USB Microskopkamera

Also die Varianten PC oder analoges Kamerasystem fallen durch. Aber es gibt ja noch den Raspberry PI, den kleinen Einplatinencomputer mit einem integrierten USB-Host und wunderbaren Grafikfähigkeiten.  Das Projekt wird also mit einem Raspberry PI 3 realisiert.

 

Als Betriebssystem kommt das Raspian-Jessi zur Anwendung. Das Image kann hier heruntergeladen werden. Nach dem Entpacken der ZIP Datei und dem Beschreiben der MicroSD Karte mit dem Win32DiskImager, kann der Rasbperry gebootet werden. Jetzt gibt es zwei Möglichkeiten an den Raspberry eine Camera anzuschliessen: 

 

-mittels Flachbandkabel an den Cameraport (hier kann nur die PI-Camera angeschlossen werden)

 

-oder über den USB-Port jede USB2.0 Camera.

 

Voraussetung hierbei ist, dass die Cam auch erkannt wird. Hier kann mit >lsusb in der Linuxconsole nachgesehen werden, ob die angeschlossene Cam auch in der Deviceliste erscheint. Als einfaches Tool, um am Desktop das Camerabild zu sehen, kann guvcview verwendet werden. Das würde jetzt auch schon genügen, wenn man nur das Bild sehen will. Unser Ziel ist jedoch, in das Camerabild ein Overlay mit Fadenkreuz einzublenden.

 

Das lässt sich in Python mit der PI-camera und der der picamera Library wunderbar lösen. Die Library besitzt eine integrierte Overlayfunktion. Es geht aber auch mit der USB-Kamera. Hierfür müssen ein paar Module installiert werden. In der Linuxkonsole sind folgende Zeilen einzugeben:

 

zuerst einmal die üblichen Aktualisierungen:

 

>sudo apt-get update >sudo apt-get upgrade

dann installieren wir numpy >sudo apt-get install python-numpy und danach das Bildverarbeitungstool schlechthin: OpenCV >sudo apt-get install python-opencv

Die Python-Version die ich hier verwende ist 2.7.9

Jetzt kann ein Pythonscript erstellt werden, das die USB-Camera initialisiert, und in einer Endlosschleife die Bilder an ein Desktopfenster übergibt. Mit den Bildbearbeitungsfunktionen in opencv lässt sich auch das Erstellen eines Fadenkreuzes realisieren. Auch das Fixieren des Ausgabefensters am Desktopbildschirm ist möglich. Siehe folgendes Script:

 

 

 

</p>
<p style="text-align: justify;">#usb camera mit osd für platinenbohrsystem
#version 1.0 03/2017 by bihlo


import numpy as np
import cv2


cam = cv2.VideoCapture(0)
cam.open(0)

cam.set(3,800)
cam.set(4,600)

while(True):

# bei jedem schleifendurchlauf wird ein frame genereriert

# frame von der camera holen
ret, frame = cam.read()

# fadenkreuz mit der funktion line zeichnen mit 2 pixeln linienbreite
cv2.line(frame,(0,300),(800,300),(255,0,0),2)
cv2.line(frame,(400,0),(400,600),(255,0,0),2)

# zwei kreise zeichnen
cv2.circle(frame,(400,300), 50, (255,0,0), 2)
cv2.circle(frame,(400,300), 100, (255,0,0), 2)

#text ins bild einblenden
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame,'Platinenbohrsystem V1.0',(10,50), font, 1,(255,255,255),2)

# ausgabe des frames in fenster/ beenden mit taste "q"
cv2.nameWindow('Platinenbohranlage CAM')
cv2.moveWindow('Platinenbohranlage CAM',0,0)
cv2.imshow('Platinenbohranlage CAM',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# nach beendigung das device freigeben und das fenster schlissen
cap.release()
cv2.destroyAllWindows()</p>
<p style="text-align: justify;">

 

Nach Starten des Scripts sollte am Bildschirm das Camerabild und das Fadenkreuz zu sehen sein:

Will man, dass das Pythonscript (in meinem Fall habe ich es "camtest9.py" genannt) nach dem Hochfahren und Laden des Desktops automatisch gestartet wird, so kann man am einfachsten im LXSession Configurationsfenster einen Eintrag hinzufügen. Dazu ist  im Desktopmenu unter >Einstellungen >Default applications for LXSession anzuklicken.

Im LXSession Menue ist dann unter "Autostart" der folgende Eintrag hinzuzufügen:

@python /(pfad zum pythonscript)/camtest9.py

Jetzt muß nur mehr neu gestartet werden und das Script sollte nach dem Start direkt ausgeführt werden. Die folgenden Bilder zeigen den umgebauten Variodrill...

Raspberry als Datenlogger Teil2…Die Sensoren und Python

DSC_4789
Raspberry PI samt Powerbank im Gehäuse

In Teil1 dieses Projektes haben wir dem Raspberry ein Betriebssystem verpasst und das ein wenig für die Anwendung aufbereitet. Wir wollen ja an den PI mehrere Sensoren anschließen und diese dann zyklisch auslesen und die Daten in einer Datei auf einem USB-Stick speichern. Die Aufzeichnung soll so lange laufen, bis ein Taster gedrückt wird, der den Prozess beendet. Die einzige Anzeige des PI sind zwei Leuchtdioden, die, sowie auch der Taster, an die GPIOs des PI angeschlossen sind. Darum haben wir folgende Punkte bereits erledigt:

  • Die PI Platine gemeinsam mit einer USB Powerbank in ein Gehäuse eingebaut
  • Anschlüsse wie Ethernet, USB, HDMI durch Ausschnitte im Gehäuse nach außen geführt
  • Zwei Leuchtdioden und einen Taster ins Gehäuse eingebaut und auf die GPIOs geschaltet
  • Den I²C Bus des PI auf eine Buchse im Gehäuse geführt
  • Eine MicroSD Karte mit einem Raspi-Wheezy Image bespielt
  • Einen USB-Stick mit FAT32 formatiert
  • Das Betriebssystem soweit konfiguriert, dass das Filesystem für den Stick, alle Module für den I²C, sowie Python geladen werden.
DSC_4790
Raspberry PI im Plastikgehäuse

Der Pi sieht fertig zusammengebaut nun so aus (siehe Bild rechts). Nun können die Sensoren angeschlossen werden. In diesem Fall handelt es sich um Luftfeuchtigkeits-/Temperatursensoren mit der Bezeichnung HYT939 des Herstellers Hygrochip. Hier ein Auszug der technischen Daten aus dem Datenblatt des Herstellers:

Ausführung: Feuchtesensor im TO39 Gehäuse, druckfest, mit Edelstahl-Sinterfilter
Genauigkeit:
Feuchte ±1,8% rF, Temperatur ±0,2 °C
Genauigkeit 0…10% rF (0 … 50°C): ±(0,1% rF + 17% aw)
Messbereich: Feuchte 0 … 100% r.F. (max. dp = +80 °C), Temperatur – 40 … +125 °C
Abmessungen: 5,2 x 9 mm
Anschlüsse: TO 39 Footprint
Auflösung Feuchte: 0,02% rF
Hysterese bei 50% rF: < ±1% rF
Linearitätsfehler: < ±1% rF
Ansprechzeit t63: < 10 sec (Mit Edelstahl-Sinterfilter)
Auflösung Temperatur: 0,015 °C
Digitale Schnittstelle: I2C, Adresse 0x28 oder Alternativadresse
Betriebsspannung: 2,7 … 5,5 V
Stromaufnahme (typ): < 1µA in Bereitschaft < 22µA bei 1Hz Messrate 850 µA maximal

DSC_4792
HYT939 Sensor

Eine kleine Platine dient als „Sensorboard“. Hier besteht die Möglichkeit, vier HYT´s anzustecken. Natürlich müssen auch die Adressen der Sensoren unterschliedlich sein. Der HYT939 ist per default auf hex 0x28 eingestellt. Will man diese Deviceadresse ändern, so muss der der HYT in den Command-Mode versetzt werden, um dann die Konfigurationsdaten empfangen und in sein EEprom schreiben zu können. Dazu muß der Sensor innerhalb der ersten 10ms nach seinem PowerUp in den Command-Mode gebootet werden. Das lässt sich am einfachsten mit einem ArduinoUno bewerkstelligen… Dabei wird der Powerpin des HYT über einen Digital Out Pin des Arduino versorgt. So ist es möglich, das Timing genau einzuhalten und den Command Mode zu erreichen.

Nachdem der Sensor nun an den Raspberry angeschlossen ist, fehlt nur mehr ein Programm, um ihn oder auch mehrere anzusteuern und auszulesen. Hier verwende ich den Python Interpreter. Damit lassen sich auf einfache Weise die Daten auslesen und auch auf Datenträgern speichern. Das „Programm“ besteht aus zwei Teilen:

  • Hauptscript: beinhaltet nur eine Endlosschleife, die die LEDs steuert, den Taster abfragt, die Sensorfunktion aufruft, deren ausgelesene Werte übergibt, aufbereitet und auf den Stick speichert.
  • Funktion Sensor auslesen: addressiert den I²C Bus, liest die Sensordaten aus, rechnet sie in lesbare Werte um und übergibt den Output an die Funktion
# /usr/bin/python
# License: GPL 2.0
# edited by Ingmar B. Aug.2015

import os
from time import *
import time
import threading
import hyt939o 
import RPi.GPIO as GPIO

# Setup LED Ports (pin12 = LED rot, pin18 = LED gruen)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(16, GPIO.IN)

# LED Gruen einschalten sobald das Script gestartet ist
GPIO.output(18, GPIO.HIGH)

#gpsd = None #seting the global variable
address = [0x2a, 0x29] 
#hyt939 = [0, 0]
hum = [0, 0]
temphyt = [0, 0]
loopon = True         #set variable for loop
i=1             #counter for address selection
os.system('clear')     #clear the terminal (optional)
 
while loopon:
        # bei beginn des auslesens aller daten die rote Led einschalten
    GPIO.output(12, GPIO.HIGH)
    if GPIO.input(16)== GPIO.HIGH:
      loopon = False
        os.system('clear')
         
      # Variablen fuer Sensor HYT 939 uebergeben 
    for i in range(2):
                
        hyt939=hyt939o.ReadMeasurement(address[i])            
        time.sleep(0.1)
        hum[i]=hyt939[0]
        temphyt[i]=hyt939[1]
      
                print '--------------------------------------- '
            print 'SENSORS reading Sensor Nr.:' , i
            print
            print 'humidity    hyt939         ' , hum[i]
            print 'temperature hyt939         ' , temphyt[i]
            print '--------------------------------------- '
            print
    print 'data to write:' , str(hum[0]), str(temphyt[0]), str(hum[1]), str(temphyt[1])
    print ("date :" + time.strftime("%x"))         
        print ("time :" + time.strftime("%X"))
    print
    date = time.strftime("%x")
    zeit = time.strftime("%X")
    
      ## write all data to usbstick
      
        fileout = open("/media/usbstick/wetterfrosch.txt", "a")

    time.sleep(0.1)

        fileout.write(date+";"+zeit+";"+str(hum[0])+";"+str(temphyt[0])+";"+str(hum[1])+";"+str(temphyt[1])+"\n") 
    
        time.sleep(0.1)
        fileout.close()
        time.sleep(0.1)

      # nach schreiben bzw auslesen der daten rote LED wieder abschalten
        GPIO.output(12, GPIO.LOW)
        time.sleep(0.8) #set to whatever

GPIO.output(18, GPIO.LOW) # gruene Led ausschalten

print "Ende" 

Das folgende Listing liest den Sensor aus:

# Reading mesaurements from HYT 939 humidity and temperature sensor
# First Version by Caerandir May 2014 modified by i.bihlo 2015

import smbus, time
bus = smbus.SMBus(1)    # Raspberry Rev. 2
address = 0x28          # Fixed default address of HYT 939

# Initialize sensor to acquire measurements
def MeasurementRequest():
        void = bus.write_quick(address)
    time.sleep(0.1)

# Read Humidiy and Temperature to 14 bit accuracy
def ReadMeasurement():
    void= bus.write_quick(address)

    time.sleep(0.1)    
        # Acquire 4 byte from sensor
        #time.sleep(0.1)
    Readout = bus.read_i2c_block_data(address,0,4)

    # Calculiere die relLF in % aus den vier Bytes in "Readout"
    RelHum = Readout[0]<<8 | Readout[1]
    RelHum = RelHum & 0x3FFF
    RelativeHumidity = 100*RelHum/(2**14)

    # Calculiere die Temperatur vom Sensor
    Readout[3] = Readout[3] & 0x3F
    temp = Readout[2]<<6 | Readout[3]
    Temperature = 165.0*temp/(2**14)-40
       
        print "Hrel: ", RelativeHumidity, " %"
        print "T: ", Temperature, " C"

        return RelativeHumidity, Temperature

MeasurementRequest()
time.sleep(0.2)

ReadMeasurement()

 

Eine Versuchsmessung über einen Tag und eine Nacht mit drei Sensoren hat folgendes Ergebnis geliefert. Hier sind die Temperaturwerte der Sensoren dargestellt. (Die Daten vom USB-Stick wurden mit Matlab importiert und daraus ein Plot erstellt.)

temperature_3sensoren

Raspberry als Datenlogger Teil1…Das Betriebssystem einrichten

Der Raspberry Pi ist ja mittlerweile ein bekannter und beliebter Scheckkartenplatinen-Computer mit dem sich allerlei anstellen lässt. Vom TV-Frontend mit Kodi, über Spielekonsolenemulatoren mit Retropi bis hin zum Bürorechner, ist damit fast alles möglich. In diesem Projekt möchte ich vorstellen, wie mit Hilfe des Raspberry Pi Model2 physikalische Größen wie Temperatur und Luftfeuchtigkeit gemessen und auf einem Speichermedium geloggt werden. Und zwar mit einem Feuchtesensor der Type HYT939 der am I²C Bus angeschlossen wird, genauer gesagt: mehrere I²C Feuchtesensoren am Bus…

DSC_4789Wir beginnen zuallererst mit der Versorgung des Raspberry PI. Im Bild ist ein Pi2 in ein einfaches Kunststoffgehäuse eingebaut und an eine 2Ah USB-Powerbank von RS-Components angeschlossen. Der Ladeanschluss der Powerbank ist vom Gehäuse nach aussen geführt. So kann der Pi wahlweise über die Powerbank (mit einer nicht rechenintensiven Anwendung bis zu 3h) oder über eine externe USB-Versorgung (z.Bsp. einem Handyladeadapter) betrieben werden. Der I²C Bus des PI (Pin 3 SDA und Pin 5 SCL sowie Pin 2,4 +5V und GND an Pin 6,14…) ist auf einen RJ Stecker im Gehäuse ausgeführt. Um später irgendwelche Statusmeldungen ausgeben zu können, sind zwei LEDs an die GPIOs 24 und 18 (an Pin18 und Pin12) angeschlossen. Ein weiterer GPIO wird über einen 22k Pulldown-Widerstand an einen Taster an 5V geschaltet. (GPIO23 an Pin16).

Für die USB Anschlüsse, Ethernet und HDMI wurden im Gehäuse passende Ausschnitte gemacht, an eine USB Schnittstelle ein Keyboard und an den HDMI Port ein Monitor angeschlossen. Die LAN Verbinung mit Internetzugang sollte auch hergestellt sein, um nach der Ersteinrichtung die benötigten Module und Updates laden zu können.

Jetzt fehlt nur noch das Speichermedium mit Betriebssystem. Der PI2 ist mit einem Micro-SD Slot ausgestattet. Ich habe hier eine 4GB Micro SD mit einem raspian-wheezy image bespielt. Um das Imagefile auf einfache Weise auf die SD-Karte zu bekommen, empfiehlt es sich, das Tool win32diskimager zu verwenden. Ist die Speicherkarte dann fertiggestellt, kann man beginnen.

Der Raspberry zeigt nach dem Einschalten kurz seinen Farbverlauf und dann beginnt auch schon der Bootprozess. Ist der dann beendet, so startet das OS am PI erstmal eine Setup-Routine.

Hier sind nun folgende Schritte durchzuführen:

  • im Menu internationalisation options unter I1 die entsprechenden locals einstellen -> DE_UTF_8
  • in advanced options unter A2… einen Hostname vergeben z.Bsp.:“raspisensor“, in A4… SSH enablen, in A7 …I²C enablen und „load per default“ und in A8 … „serial enable“ und „login shell“ aktivieren
  • dann noch expand  filesystem wählen damit der Speicherplatz der gesamten SD-Karte genutzt wird
  • jetzt noch mit finish -> reboot neu starten

Jetzt fährt der PI wieder hoch und bleibt beim Login-Prompt stehen. Mit login: pi und dem passwort: raspberry loggt man sich nun ein. Mit den folgenden Kommandos werden Updates und benötigte Module installiert:

sudo apt-get update
sudo apt-get install python-smbus    
(installiert den system management bus)
sudo modprobe i2c_bcm2708             (kernelmodule für I²C von Hand laden)
sudo modprobe i2c_dev
lsmod                                                         (geladene Module listen)
sudo i2cdetect -y 1                                  (I²C ports scannen)

Es empfiehlt sich, die Kernelmodule per Autostart zu laden. Das geht wie folgt:

sudo nano /etc/modules                        (mit dem Nano-Editor die Datei modules öffnen …)

dann folgende Zeilen hinzufügen:

i2c_bcm2708
i2c_dev

dann mit STRG+X den Editor beenden und bei Speichern JA wählen.
danach mit:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

überprüfen, ob hier bereits ein Eintrag „blacklist i2c-bcm 2708“ existiert.
Falls ja, ist der auszukommentieren oder zu löschen.

jetzt wieder neustarten mit:

sudo shutdown -r now

danach wieder einloggen und mit

lsmod

überprüfen ob die gwünschten Module korrekt geladen sind.

Da wir später die Daten von den Sensoren in eine Datei loggen wollen und diese Datei auf einem USB-Stick gespeichert werden soll, sind folgende Schritte notwendig:

  • einen USB-Sick mit FAT32 Filesystem auf einem Windowsrechner formatieren
  • auf dem PI das Filesystem FAT32 installieren
  • den Stick in den PI stecken und die Mountlist um den Stick erweitern

Zuerst laden und installieren wir das Filesystem:

sudo apt-get -y install ntfs-3g hfsutils hfsprogs exfat-fuse

dann legen wir folgendes Verzeichnis an:

sudo mkdir /media/usbstick (usbstick dient hier als beispielname…)

sudo blkid -o list -w /dev/null

(listet die IDs der Datenträger auf -> unser Stick sollte in der Liste als vfat mit einer ID in dem Format XXXX-XXXX erscheinen)

sudo mount -t vfat -o utf8,uid=pi,gid=pi,noatime /dev/sda /media/usbstick

nun öffnen wir folgende Datei mit dem Editor:

sudo nano -w /etc/fstab

die ID des USB-Sticks von vorher tragen wir nun samt folgender Zeile ein und speichern dann wieder ab:

UUID=XXXX-XXXX /media/usbstick/ vfat utf8,uid=pi,gid=pi,noatime 0

weiter geht’s mit der Einrichtung der GPIOs und den Python libraries:

sudo apt-get install python-dev
sudo apt-get install python-rpi.gpio

Noch ein paar allgemeine Einstellungen:

sudo nano /etc/networks/interfaces  (Wir wollen eine fixe IP Adresse vergeben, um später einfach per SSH auf den PI zugreifen zu können)

folgende Zeile ersetzen:

iface eth0 inet dhcp

durch:

iface eth0 inet static
address xxx.xxx.xxx.xxx
netmask yyy.yyy.yyy.yyy
gateway zzz.zzz.zzz.zzz

und wieder speichern:

Das zu Anfang gestartete Setup Script lässt sich immer über folgenden Befehl aufrufen:

sudo raspi-config

Die Systemzeit des Raspi (für meine Anwendung benötige ich auch einen Zeitstempel) lässt sich mit folgendem Befehl stellen:

sudo date „MMTThhmmJJ“

Das war´s für den Anfang. Im zweiten Teil beschreibe ich dann die Sensorhardware und die Python-Scripts, die die Sensoren dann auslesen…