Mittwoch, 12. Oktober 2016

Mein erstes Arduino Projekt

Ständig taucht beim Lesen dieser Name "Arduino" auf, der wie ein kleiner Italiener klingt. Und die Leute schreiben dafür einen Sketch - was für mich bisher ein gespielter Witz war.
Sicher ging es auch lustig zu, in der Bar von Ivrea wo vor über 10 Jahren von zwei Italienern diese Technologie entwickelt wurde.
Es interessierte mich und ich suchte schon eine Weile ein simplere Lösung um die S0 Schnittstellen meiner Zwischenzähler endlich mal auswertbar zu erfassen. Die seinerzeit gekaufte PM2 von Allnet (ALL3691) war nur als Mäusekino zu gebrauchen und hatte zu viele Macken. Da tauchte beim Stöbern im FHEM Forum der Begriff ArduCounter auf, das wird es doch!
Die kleinen Platinen des Arduino nano gibt es in vielen Ausführungen, sie kosten wenige Euro, man kann sie direkt aus China holen - aber letztendlich brauchte ich erstmal was zum probieren, was auch sofort funktioniert! Ich habe mich etwas belesen und dann den bei Amazon bestellt: Aptotec Nano V3.0 Pro mit Org.ATmega328P/ FT232RL Chip. Ein FTDI Chip sollte er haben, damit die USB Anbindung erstmal ohne große Probleme läuft!
Wobei scheinbar alle Probleme mit dem CH340 Chip behoben sind, auch ein solcher Arduino Nano läuft ohne Probleme. Allerdings, wenn man mehrere USB Geräte betreiben möchte: siehe Abschnitt am Ende "Probleme".

Was braucht man noch?

  • Ein USB Kabel passend zum Board (USB mini). Bei meinem Board war ein Kurzes dabei.
  • Ein Breadboard, das ist kein Brettchen fürs Brot sondern ein Steckbrett auf dem man sich elektronische Schaltungen einfach zusammenstecken kann.
  • Den FTDI USB Treiber falls der Arduino nicht beim anstecken sofort erkannt wird.
  • Die IDE für den Arduino um einen Sketch zu schreiben. Es empfiehlt sich die von der arduino.cc Webseite obwohl die derzeit eine niedrigere Versionsnummer (1.6.12) trägt. Die Alternative von arduino.org ist unvollständiger.

Hardwareinstallation und Vorbereitung

Den Arduino auf Steckbrett, USB Kabel dran und los geht es. Zunächst leuchtet nur die Power LED. 
  1. Zuerst im Gerätemanager schauen ob der Treiber installiert ist, es sollte eine neue COM Schnittstelle da sein, ohne Ausrufezeichen! Die Nummer merken (bei mir COM3).
  2. Die IDE in ein Verzeichnis entpacken und die Arduino.exe starten. Wir benötigen keine erweiterten Rechte.
  3. Die Konfiguration der IDE - Im Menü: Werkzeuge->Board "Arduino nano" wählen, dann Werkzeuge->Port "COM3" wählen.
  4. Das Fenster zeigt einen leeren Sketch, so etwas wie der Grundrahmen. Für einen kleinen Funktionstest öffnen wir: Datei->Beispiele->01.Basisc->Blink
  5. Jetzt einfach den Pfeil nach rechts in der Symbolleiste oder Menü->Sketch->hochladen oder Strg-U drücken. Wenn keine Fehlermeldungen erscheint wird nach wenigen Sekunden die LED des Arduino im Sekundentakt blinken. Der Arduino nano hat eine "Signal" LED die mit PIN D13 on Board verbunden ist. Neben der Power LED zeigen noch zwei LEDs die Datenübertragung der seriellen Schnittstelle an.
Meine Zähler sind schon mit RJ11 Kabeln beschaltet, für einen schnellen Test muss ich meinem Arduino nur noch ein "Interface" verpassen. Ich habe mir ein altes RJ45 Netzwerkkabel zerschnitten und die Leitungen an einen Pfostensteckverbinder gelötet. Dieses Kabel kommt aufs Steckbrett und mit zwei Drahtbrücken wird die Verbindung zu Pin 4 und 5 hergestellt. Hier muss man auf die Polung achten, viele Zähler S0 Schnittstellen sind "Open-Collector" und mit + und - bezeichnet. Das sieht alles nicht spektakulär aus, ich habe trotzdem mal ein Foto gemacht.


Zähler programmieren

Die IDE legt im Dokumente Ordner des Benutzers einen Arduino Ordner als Arbeitsverzeichnis an.
Dahin kopieren wird den Sketch "ArduCounter.ino" entweder vom contrib/arduino Ordner unsere FHEM Installation oder direkt vom github
Mit Datei öffnen wird die ArduCounter.ino geladen und anschließend auf den Arduino hochgeladen. Wenn keine Fehler angezeigt werden sind wir fertig, wir können den Arduino von der USB Schnittstelle abziehen.

Am FHEM Server anschließen

Bisher haben wir alles am Desktop jetzt müssen wir kurz überprüfen ob der Arduino am FHEM Server erkannt wird. Mit Putty loggen wir uns am Raspberry ein und haben den Arduino noch nicht angesteckt! 
Mit ls /dev/ttyUSB* schauen wir uns die Liste der seriellen/USB Schnittstellen an und merken die uns. Wenn bisher keine vorhanden ist wird eine Meldung ausgegeben
ls: cannot access /dev/ttyUSB*: No such file or directory
Jetzt stecken wir das USB Kabel mit dem Arduino und warten einen Moment. Jetzt sollte die Ausgabe mindesten eine Schnittstelle zeigen, werden mehrere gezeigt ist die neue unsere Schnittstelle, bitte wieder die Nummer merken, bei mir /dev/ttyUSB0.
Das RJ11 Kabel vom Zähler verbinde ich einfach mit einer RJ45 Kupplung mit meinem Kabel zum Steckbrett.

Einbindung in FHEM

Seit Januar 2017 ist ArduCounter Bestandteil vom normalen FHEM, vorher war es ein "contrib" Modul. Die ersten beiden Schritte sind also obsolete:
Mit putty am raspberry:
sudo cp /opt/fhem/contrib/98_ArduCounter.pm /opt/fhem/FHEM/
Auf diese Weise gehört die Datei zwar root aber es darf jeder lesen und fhem sollte damit zurecht kommen. Man kann auch noch die Rechte gerade ziehen:
sudo chown fhem:dialout /opt/fhem/FHEM/98_ArduCounter.pm
Jetzt in der Kommandozeile im Browser das Gerät anlegen:
define AC ArduCounter /dev/ttyUSB0@38400 
Jetzt noch den Messeingang definieren:
attr AC pinD4 rising pullup
Wenn alles richtig lief (Logfile) steht das Gerät auf opened und die Readings für pin4 und power4 sollten sich füllen. Mit get AC info könnte man eine Zwischenabfrage starten (Ergebnis -> Logfile).

Feintuning

Das power Reading liefert den momentane Leistung am Zähler. Damit die stimmt muss auch der Faktor stimmen. 
  • Mein Zähler SMD630 liefert 400 Impulse pro 1 kWh. 
  • 1 Impulse entspricht also 0,0025 kWh.
  • Um den Zählerstand in kWh zu ermittteln, muss man einfach die Anzahl der Impules durch die Zahl Impulse/kWh dividieren. 
  • ArduCounter ermittelt den Wert für die momentane Leistung in Impulsen/h ((delta count) / (delta time) * factor). Liefert der Zähler 1 Impuls pro 1 W/h, dann erhält man mit dem Faktor 1000 den Wert in kW angezeigt. Da mein Zähler 1 Impuls pro 2,5 W/h liefert, muss ich 2500 (statt Standardwert 1000) als Faktor einstellen.
Der folgende Abschnitt muss überarbeitet werden.
attr AC factor 2500
Ich will ja eigentlich meinen Zählerstand abbilden. Dazu definiere ich ein userReadings
attr AC userReadings Zaehler {ReadingsVal("AC","pin4",0)/400 + gggg.gg }
gggg.gg ist der Grundwert. Es ist der Zählerstand der bei Start der Zählung der S0 Impulse auf dem Zähler stand. Damit kann jederzeit der echte und der ermittelte Zählerstand abgeglichen werden.

Wenn der Arduino mal vom Strom genommen wird, dann sind die gespeicherten Impulse natürlich gelöscht. Damit man einfach den Zählerstand wieder setzen kann, habe ich mir noch einen Dummy gebaut dem ich einfach meinen aktuellen Zählerstand gebe und der rechnet dann sofort den Grundwert aus:
define ZStart dummy
attr ZStart userReadings Grundwert {ReadingsNum("ZStart","state",0)- ReadingsNum("AC","pin4",0)/400 }
Man stellt sich also einfach vor den Zähler und tippt den abgelesenen Wert in das set vom Dummy. Der Grundwert wird sofort ermittelt und das veränderte userReading von oben liest dann den Grundwert direkt aus:
attr AC userReadings Zaehler {ReadingsVal("AC","pin4",0)/400 + {ReadingsNum("ZStart","Grundwert",0) }

Fertig

Nachdem das alles ziemlich einfach war und gut läuft, muss das Ganze noch weg vom Provisorium. Es soll ja einfach so in der Verkabelung verschwinden. Also muss ein Arduino nano ohne Beinchen her. Habe ich ich doch überall gesehen und die meisten haben sich beim Kauf aufgeregt, dass sie selbst noch löten mussten. Das war dann aber doch gar nicht so einfach, vor allem stimmen denn die Produktfotos? 
Ich habe den Nano 3.0 Arduino kompatibel ATmega328P-AU 16MHz Mini USB mit CH340G V3.0 5V ICSP bei ebay bestellt, der war zumindest innerhalb ein paar Tage lieferbar. Er kam wirklich ohne Beinchen. Allerdings hat dieser eine unschöne Eigenheit: Am Ende des Hochladens des Sketches meldet er ein paar Fehler:  
avrdude: verification error, first mismatch at byte x....  0xf1 != 0xb1
avrdude: verification error; content mismatch
Sieht irgendwie aus als wäre ein bit Fehlerhaft. Es passiert offenbar beim Kontrolllesen, scheint aber kein wirkliches Problem zu sein. Das aufgespielte Programm läuft ohne Probleme. 
Ich habe eine Weile alles mögliche probiert und im Internet dazu gefunden: man könnte die Firmware tauschen, die ist eventuell fehlerhaft. Dazu bräuchte ich einen ISP Programmer. Aber außer das es "philosophisch" vielleicht interessant ist, stört es mich erstmal wenig. Ich habe einfach ein Stück RJ45 Kabel an das Board gelötet, zwei Stück Isolierschlauch drüber gezogen und fertig!
Nachtrag: Dieser Nano war wirklich defekt! Die serielle Kommunikation mit dem FHEM Modul brachte immer mal wieder unsinnige Zeichen zu Tage. Mit einem anderen Nano lief es sofort alles Fehlerfrei. An der Firmware lag es jedenfalls nicht, das USB-Seriell Chip war defekt. Ich habe mir einen neuen CH340G bestellt und diesen getauscht. Jetzt läuft auch dieser Nano wieder ohne Fehler! Klar auch das war rein Interessehalber: die Reparatur eines Nano Wert 4,49€ mit einem CH340G für 1,12 € lohnt unter wirtschaftlichen Gründen nicht wirklich. Aber ich wollte wissen ob ich den SMD Chip tauschen kann und es geht! 
Beinchen am besten mit einem kleinen Seitenschneider einzeln trennen, Reste mit dem Lötkolben herunter "wischen", neuen Chip an einer Ecke fixieren und genau positionieren, alle Pins anlöten, zuviel Zinn und Brücken sind nicht schlimm. Anschließend mit Entlötlitze großzügig "absaugen" - dabei passiert bei einigen Pins erst der wirkliche Lötvorgang!

Probleme

Die Zählung der Impulse funktionierte bei mir nicht auf Anhieb. Ich habe im laufenden Zustand den Resetknopf am Arduino gedrückt. Danach funktionierte alles wie gewollt. Das war aber ein Bug im Modul, der ist inzwischen behoben.
Hat man versehentlich falsche Pins definiert bleiben die Readings erhalten. Mit deletereading AC xxx kann man diese Readings löschen.

Sollte die USB Schnittstelle des Arduino nicht sofort erkannt werden, hilft nochmaliges Ab- und Anstecken. 
Mit lsusb kann man schauen ob die Schnittstelle überhaupt erkannt wird. 
Mit dmesg | grep FTDI könnte man schauen ob ein FTDI Chip erkannt wurde.

Es gibt wohl generell, dass Problem, dass die USB Sticks unter Linux einfach durch nummeriert werden, in der Reihenfolge wie sie erkannt werden. Was zunächst mal interessant war: Den ersten Arduino nano ab und den neuen dran - er bekommt auch wieder USB0. Bei einem einzelnen Stick kann das ja schick sein, aber bei mehr als einem?

Dazu gibt es offenbar eine Lösung "/dev/serial/by-path".
Mit ls /dev/serial/by-path/ kann man sich die gesteckten USB Stick mit kompletten Pfad anzeigen lassen.

platform-3f980000.usb-usb-0:1.2:1.0-port0
platform-3f980000.usb-usb-0:1.5:1.0-port0
Die :1 ist der interne USB Hub des Pi, die folgende Ziffer nach dem Punkt der Port (siehe unten). Steckt an Port 3 (0:1.3) noch ein Hub, kommen dessen Anschlüsse als weitere Punkt dazu (0:1.3.1:). Man kann dann meist die Ports am Hub mechanisch / logisch zuordnen.

Mit ls -l bekommt man die Info ausführlicher und sieht die Verbindung auf USBx. Die USB Nummerierung ist abhängig von der Reihenfolge der Erkennung!

Mit lsusb -t bekommt man die Port Zuordnung im Klartext.
lsusb liefert hingegen nur die Device Auskunft, die ist abhängig von der Reihenfolge der Erkennung!

 /:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/5p, 480M
        |__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=smsc95xx, 480M
        |__ Port 2: Dev 4, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
        |__ Port 5: Dev 6, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
Spätestens wenn noch ein USB Hub verwendet wird ist diese Auskunft auch nicht mehr "logisch", da hilft nur probieren (abziehen/stecken).

Portnummerierung am Raspberry Pi 3

ist simpel zu merken: Wie "man schreibt", die Ethernetschnittstelle ist USB Port 1. In der Mitte ist oben USB Port 2 und darunter USB Port 3, naja und klar Rechts oben ist USB Port 4 und unten USB Port 5.
   2  4
1  3  5

Um festzulegen, dass der USB Stick in einem bestimmten Port (Port 2) genommen wird, muss das define im FHEM so aussehen:
define AC ArduCounter /dev/serial/by-path/platform-3f980000.usb-usb-0:1.2:1.0-port0@9600

3 Kommentare:

  1. attr AC userReadings Zaehler {ReadingsVal("AC","pin4",0)/400 + {ReadingsNum("ZStart","Grundwert",0) }

    Hier ist ein Fehler mit den Geschweiften klammern, da muss eine weniger. bitte überprüfen. ;)

    AntwortenLöschen
  2. hallo, ich hab zwei Jeelinks in Verwendung, einen für Lacrosse, und einen für PCA301. Ab und an kommen die USB-Zuordnungen durcheinander.
    Ich hab es schon versucht mit /dev/serial/by-id und nun noch mit /by-path. aber nach der Anpassung des DEF werden die Jeelinks jeweils auf "disconnected" gesetzt. sobald ich wieder auf "/dev/ttyUSB0@57600" zurückwechsel werden die wieder initialisiert.
    wollte die Verbindung der USB-Jeelinks einegentlich stabiler machen. woran kann das liegen, dass die Jeelinks nicht connected/initialisiert werden?
    danke und Gruß
    Adrian

    AntwortenLöschen
    Antworten
    1. Es sollte genauso gehen, wenn alles richtig geschrieben ist sollte keine Unterschied zwischen ttyUSB0 und by-path sein. Da habe ich keine Idee.
      Gruß Otto

      Löschen