veranstaltungen:hessen20162:arduino-workshop-notizen

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
veranstaltungen:hessen20162:arduino-workshop-notizen [02.10.2016 20:18] ipsecguyveranstaltungen:hessen20162:arduino-workshop-notizen [04.10.2016 11:01] (aktuell) – [Arduino Sketch (Programm):] ipsecguy
Zeile 7: Zeile 7:
 Das ganze lief über die IPv6 Adressen von Freifunk, hier Freifunk Frankfurt. Der Server ist als Client im Freifunk drin, natürlich könnte man ihn auch an zentraler Stelle oder im Internet aufstellen. Das ganze lief über die IPv6 Adressen von Freifunk, hier Freifunk Frankfurt. Der Server ist als Client im Freifunk drin, natürlich könnte man ihn auch an zentraler Stelle oder im Internet aufstellen.
  
-Sensoren+###Sensoren
  
 Wir haben einen DHT11 / DHT22 und einen OneWire Dallas DS18B20 an den Arduino angeschlossen. Das sind digitale Sensoren, d.h. man spricht sie über ein Bitprotokoll an und bekommt die Messwerte zurückgeliefert. Über die Arduino ADCs (Analog Digital Wandler) könnte man auch analoge Sensoren (Helligkeit oder Temperatur bei denen sich Widerstandswerte abhängig von der Messgröße andern) anschließen. Hier ist dann auch eine Kalibrierung des Messsystems notwendig und die Kabellängen oder Verbindungsstecker habe einen Einfluß. Bei den digitalen Sensoren wir versucht, dies komplett zu vermeiden und eine Kalibrierung direkt im Werk durchzuführen und dieGeräte so zu konstruieren, dass diese für 5 oder 10 Jahre keine größeren Veränderungen zeigen. Wir haben einen DHT11 / DHT22 und einen OneWire Dallas DS18B20 an den Arduino angeschlossen. Das sind digitale Sensoren, d.h. man spricht sie über ein Bitprotokoll an und bekommt die Messwerte zurückgeliefert. Über die Arduino ADCs (Analog Digital Wandler) könnte man auch analoge Sensoren (Helligkeit oder Temperatur bei denen sich Widerstandswerte abhängig von der Messgröße andern) anschließen. Hier ist dann auch eine Kalibrierung des Messsystems notwendig und die Kabellängen oder Verbindungsstecker habe einen Einfluß. Bei den digitalen Sensoren wir versucht, dies komplett zu vermeiden und eine Kalibrierung direkt im Werk durchzuführen und dieGeräte so zu konstruieren, dass diese für 5 oder 10 Jahre keine größeren Veränderungen zeigen.
Zeile 13: Zeile 13:
 Der DHT11/22 hat ein proprietäres Protokoll und benötigt einen PIN am Mikrocontroller. Zusätzlich wird er per Masse und 5V angeschlossen, der PIN per 10k Ohm Pullup Widerstand zusätzlich an 5V. Der DHT11/22 hat ein proprietäres Protokoll und benötigt einen PIN am Mikrocontroller. Zusätzlich wird er per Masse und 5V angeschlossen, der PIN per 10k Ohm Pullup Widerstand zusätzlich an 5V.
  
-Dallas OneWire Bus+###Dallas OneWire Bus
  
 Der OneWire DS18B20 nutzt den Dallas OneWire Bus als Kommunikationsmedium. Ein-Draht-Interface ist natürlich nicht ganz richtig, denn Masse benötigt man zusätzlich und diese Zweidraht-Lösung funktioniert nur, wenn man den Sensor vor dem Auslösen der Messung über die Datenleitung gewissermaßen „auflädt“, dort bekannt unter dem Stickwort „Parasite-Power". Alternativ kann man die Sensoren auch regulär mit Masse und 5V anschließen und eine Datenleitung verwenden, welche ebenfalls per Pullup, hier 4,7k Ohm, mit 5 V verbunden wird. Der OneWire DS18B20 nutzt den Dallas OneWire Bus als Kommunikationsmedium. Ein-Draht-Interface ist natürlich nicht ganz richtig, denn Masse benötigt man zusätzlich und diese Zweidraht-Lösung funktioniert nur, wenn man den Sensor vor dem Auslösen der Messung über die Datenleitung gewissermaßen „auflädt“, dort bekannt unter dem Stickwort „Parasite-Power". Alternativ kann man die Sensoren auch regulär mit Masse und 5V anschließen und eine Datenleitung verwenden, welche ebenfalls per Pullup, hier 4,7k Ohm, mit 5 V verbunden wird.
Zeile 19: Zeile 19:
 Das Gute ist, dass es für die Protokolle viele schöne Libraries für die Arduino gibt. Einmal kümmern sich diese um das korrekte Timing der Protokolle, außerdem um die Umrechnung der Rohdaten in z.B. Grad Celsius, relative Luftfeuchte oder auch Luftdruck umgerechnet auf diverse Höhenreferenzen. Das Gute ist, dass es für die Protokolle viele schöne Libraries für die Arduino gibt. Einmal kümmern sich diese um das korrekte Timing der Protokolle, außerdem um die Umrechnung der Rohdaten in z.B. Grad Celsius, relative Luftfeuchte oder auch Luftdruck umgerechnet auf diverse Höhenreferenzen.
  
-Andere Bussysteme+###Andere Bussysteme
  
 I2C - ein zweidraht Bus. Hier können Geräte ma Bus mit Kennungen angesprochen werden. Im Gegensatz zum Onewire haben die Geräte keine eindeutige ID sondern alle Geräte einer Modellreihe dieselbe ID. In Industriellen Anwendungen kann diese Vorteile haben, da dann jeder Bus identisch ist. Bestimmt hat der Zweidraht Bus auch noch elektrische Vorteile, davon habe zumindest ich keine Ahnung. I2C - ein zweidraht Bus. Hier können Geräte ma Bus mit Kennungen angesprochen werden. Im Gegensatz zum Onewire haben die Geräte keine eindeutige ID sondern alle Geräte einer Modellreihe dieselbe ID. In Industriellen Anwendungen kann diese Vorteile haben, da dann jeder Bus identisch ist. Bestimmt hat der Zweidraht Bus auch noch elektrische Vorteile, davon habe zumindest ich keine Ahnung.
Zeile 27: Zeile 27:
 Diese Schnittstelle ist schnell und kein Protokoll, t.b dpi dispalyHigh Speed Diese Schnittstelle ist schnell und kein Protokoll, t.b dpi dispalyHigh Speed
  
-Arduino Sketch (Programm):+##Arduino Sketch (Programm):
  
 Das Programm für den Arduino hat zwei Aufgaben: Auf der einen Seite spricht es mit den Sensoren in ihren Protokollen, auf der anderen mit dem OpenWrt Router über USB oder seriell. Das Programm für den Arduino hat zwei Aufgaben: Auf der einen Seite spricht es mit den Sensoren in ihren Protokollen, auf der anderen mit dem OpenWrt Router über USB oder seriell.
Zeile 34: Zeile 34:
  
 Im Prinzip läuft das Programm in folgender Endlosschleife: Im Prinzip läuft das Programm in folgender Endlosschleife:
 +<code>
 forever: forever:
 - warten auf Eingabe (CR/LF) - warten auf Eingabe (CR/LF)
Zeile 43: Zeile 44:
   - Ausgabe eines Endemarkers, hier EOF   - Ausgabe eines Endemarkers, hier EOF
 end end
 +</code>
  
 Der steuernde Rechner kann damit einen Messvorgang auslösen und die Daten empfangen und weiterverarbeiten. Der steuernde Rechner kann damit einen Messvorgang auslösen und die Daten empfangen und weiterverarbeiten.
 +
 +<file text arduino-freifunk.ino>
 +#include <OneWire.h> 
 +OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary) 
 +
 +#include "DHT.h" 
 +#define DHTPIN 2     // what digital pin we're connected to 
 +#define DHTTYPE DHT11   // DHT 11 
 +//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321 
 +//#define DHTTYPE DHT21   // DHT 21 (AM2301) 
 +DHT dht(DHTPIN, DHTTYPE); 
 +
 +bool running = false; 
 +
 +void setup(void) { 
 +  pinMode(13, OUTPUT); 
 +  digitalWrite(13, HIGH); 
 +  Serial.begin(9600); 
 +  Serial.setTimeout(1000); 
 +  dht.begin(); 
 +  digitalWrite(13, LOW); 
 +
 +
 +void loop(void) { 
 +  byte i; 
 +  byte present = 0; 
 +  byte type_s; 
 +  byte data[12]; 
 +  byte addr[8]; 
 +  float celsius, fahrenheit; 
 +  float h,t; 
 +
 +  if( !running ){ 
 +    digitalWrite(13, LOW); 
 +    Serial.flush(); //flush all previous received and transmitted data 
 +    while(!Serial.available()){ 
 +      delay(500); 
 +    } 
 +    digitalWrite(13, HIGH); 
 +
 +    Serial.readString(); 
 +    Serial.flush(); //flush all previous received and transmitted data 
 +
 +    running = true; // start execution 
 +  } 
 +
 +if ( !ds.search(addr)) { 
 +    ds.reset_search(); 
 +
 +    //DHT11 Code 
 +    h = dht.readHumidity(); 
 +    t = dht.readTemperature(); 
 +    if (!isnan(h) && !isnan(t)) { 
 +      Serial.print("DHT "); 
 +      Serial.print(t); 
 +      Serial.print(" "); 
 +      Serial.println(h); 
 +    } 
 +    Serial.println("EOF"); 
 +
 +    running = false; // done with this cycle, wait again 
 +    return; 
 +  } 
 +
 +  if (OneWire::crc8(addr, 7) != addr[7]) { 
 +      Serial.println("CRC is not valid!"); 
 +      return; 
 +  }
 +  
 +  // the first ROM byte indicates which chip 
 +  switch (addr[0]) { 
 +    case 0x10: 
 +//      Serial.println("  Chip = DS18S20");  // or old DS1820 
 +      type_s = 1; 
 +      break; 
 +    case 0x28: 
 +//      Serial.println("  Chip = DS18B20"); 
 +      type_s = 0; 
 +      break; 
 +    case 0x22: 
 +//      Serial.println("  Chip = DS1822"); 
 +      type_s = 0; 
 +      break; 
 +    default: 
 +//      Serial.println("Device is not a DS18x20 family device."); 
 +      return; 
 +  }
 +  
 +  ds.reset(); 
 +  ds.select(addr); 
 +  ds.write(0x44, 1); // start conversion, without parasite power 
 + Serial.println(celsius); 
 +
 +
 +</file>
  
 Alternative: der Arduino sammelt im Hintergrund regelmäßig die Messwerte und liefert auf Anfrage die jeweils neuesten aus. Alternative: der Arduino sammelt im Hintergrund regelmäßig die Messwerte und liefert auf Anfrage die jeweils neuesten aus.
  
-LUA Skript zum Auslesen+##LUA Skript zum Auslesen
  
 Warum kein Bash: jedes öffnen der seriellen Schnittstelle erzeugt auf dem Arduino ein Reset. Bestimm kann ein bash Gott mein gruseliges Lua Skript locker in Bash/ash/Dash des Openwrt umschreiben. Warum kein Bash: jedes öffnen der seriellen Schnittstelle erzeugt auf dem Arduino ein Reset. Bestimm kann ein bash Gott mein gruseliges Lua Skript locker in Bash/ash/Dash des Openwrt umschreiben.
Zeile 55: Zeile 152:
  
 Was tun wir Was tun wir
 +<code>
 - öffnen der seriellen Schnittstelle - öffnen der seriellen Schnittstelle
 forever: forever:
Zeile 65: Zeile 163:
 - abwarten - abwarten
 end. end.
 +</code>
  
 Lua ist echt unterbelichtet in Bezug auf Timestamps und Sleeps, alles in Sekundenintervallen und dann noch Sleep per Shell ausführen. Und wenn man mehr will muss man Libraries laden, schönen Gruß an die Entwickler auch. Aber Hauptsache Code als Parameter übergeben können und Variablensätze als Rückgabewerte…. Lua ist echt unterbelichtet in Bezug auf Timestamps und Sleeps, alles in Sekundenintervallen und dann noch Sleep per Shell ausführen. Und wenn man mehr will muss man Libraries laden, schönen Gruß an die Entwickler auch. Aber Hauptsache Code als Parameter übergeben können und Variablensätze als Rückgabewerte….
  
-Collectd als Sammelprogramm+<file lua arduino.lua> 
 +hostname = os.getenv("COLLECTD_HOSTNAME")  
 +if hostname==nil then hostname="undefined-hostname" end  
 +interval = os.getenv("COLLECTD_INTERVAL")  
 +if interval==nil then interval=10 end  
 + 
 +rserial=io.open("/dev/ttyACM0","r")  
 +wserial=io.open("/dev/ttyACM0","w")  
 +rserial:flush()  
 + 
 +while true do  
 +  wserial:write(".")  
 +  tstart = os.time()  
 +  repeat  
 +    line=rserial:read()  
 +    line=string.gsub(line,"\r$","")  
 + 
 +    temp = nil  
 +    humidity = nil  
 +    temp, humidity = string.match(line, 'DHT%s+([%.,%d]+)%s+([%.,%d]+)')  
 +    if temp ~= nil and humidity ~= nil then  
 +      print("PUTVAL "..hostname.."/dht/temperature-temperature interval="..interval.." N:"..temp)  
 +      print("PUTVAL "..hostname.."/dht/humidity-humidity interval="..interval.." N:"..humidity)  
 +      line=""  
 +    end  
 + 
 +    romid = nil  
 +    temp = nil  
 +    romid, temp = string.match(line, '(%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x)%s+([%.,%d]+)')  
 +    if romid ~= nil and temp ~= nil then  
 +      print("PUTVAL "..hostname.."/onewire/"..romid.."-temperature interval="..interval.." N:"..temp)  
 +    end  
 + 
 +  until line=="EOF"  
 + 
 +  towait = interval - os.difftime(os.time(),tstart)  
 +  if towait>0 then  
 +    os.execute("sleep "..tonumber(towait))  
 +  end  
 + 
 +end 
 +</file> 
 + 
 +##Collectd als Sammelprogramm
  
 Collectd sammelt Metriken auf Hosts und unterstützt über Plugins eine Vielzahl von Servierprogrammen und läßt sich über generische Plugins leicht erweitern. Das Plugin das ich hier verwende ist das „exec“ plugin, welches beliebige Shell Skripte ausführen kann. Collectd sammelt Metriken auf Hosts und unterstützt über Plugins eine Vielzahl von Servierprogrammen und läßt sich über generische Plugins leicht erweitern. Das Plugin das ich hier verwende ist das „exec“ plugin, welches beliebige Shell Skripte ausführen kann.
  
-Collect Netz ohne Verschlüsselung und Authentisierung+<file text collectd.conf> 
 +#Hostname   "localhost" 
 +#FQDNLookup  true 
 +BaseDir "/var/run/collectd" 
 +#Include "/etc/collectd/conf.d" 
 +PIDFile "/var/run/collectd.pid" 
 +PluginDir "/usr/lib/collectd" 
 +TypesDB "/usr/share/collectd/types.db" 
 +#Interval    30 
 +#ReadThreads 2 
 + 
 +LoadPlugin load 
 +LoadPlugin cpu 
 +LoadPlugin wireless 
 +LoadPlugin network 
 + 
 +<Plugin network> 
 +  MaxPacketSize 1024 
 +  <Server "fddd:5d16:b5dd:0:dacb:8aff:fe00:2bdb" "25826"> 
 +    Interface "br-client" 
 +  </Server> 
 +</Plugin> 
 + 
 +LoadPlugin exec 
 +<Plugin exec> 
 +  Exec "nobody" "/root/arduino.sh" 
 +</Plugin> 
 + 
 +</file> 
 + 
 +Collectd kann verschlüsseln und/oder authentisieren. Dabei werden vom Clients die Pakete mit Benutzernamen und Passwort versehen und optional auch verschlüsselt. **Leider sind die openwrt collectd Pakete ohne die Crypto gebaut worden. 
 +**
  
 Caveat: das Skript muss unter einem anderen User als „root“ ausgeführt werden. Was auf einem großen Host sinnvoll ist macht auf einem Freifunk Router weniger Sinn. In unserem spezielle Fall müssten man z.B. einen neuen User anlegen und die ttyACM0 mit entsprechenden Rechten versehen. Oder die Schnittstelle für alle User verfügbar machen, beides am besten im Collectd Start Skript. Caveat: das Skript muss unter einem anderen User als „root“ ausgeführt werden. Was auf einem großen Host sinnvoll ist macht auf einem Freifunk Router weniger Sinn. In unserem spezielle Fall müssten man z.B. einen neuen User anlegen und die ttyACM0 mit entsprechenden Rechten versehen. Oder die Schnittstelle für alle User verfügbar machen, beides am besten im Collectd Start Skript.
Zeile 82: Zeile 255:
 Noch eine Alternative: Senden von HTTP PUT an einen der vielen IoT TimeSerien Anbieter im Markt. Aber wir wollen ja Dinge selbst tun. Noch eine Alternative: Senden von HTTP PUT an einen der vielen IoT TimeSerien Anbieter im Markt. Aber wir wollen ja Dinge selbst tun.
  
-Influx als TimeSeries Database+##Influx als TimeSeries Database
  
 influx generell influx generell
Zeile 89: Zeile 262:
 wird hinzugefügt unter hostname, metric, value etc wird hinzugefügt unter hostname, metric, value etc
  
-Grafana zur Darstellung+##Grafana zur Darstellung
  
 Query - DB, Host, Parameter etc Query - DB, Host, Parameter etc
  • veranstaltungen/hessen20162/arduino-workshop-notizen.1475439534.txt.gz
  • Zuletzt geändert: 02.10.2016 20:18
  • von ipsecguy