Arduino UDP Kommunikation

Nachdem der Arduino Uno bereits ein Ethernet Shield bekommen hat, soll der Arduino heute UDP Pakete senden und empfangen.

Hier ein kleines HowTo um mit dem Arduino UDP Pakete zu senden und empfangene Pakete zu verarbeiten.

Versuchsaufbau

Der Arduino UDP Versuchsaufbau besteht aus einer LED an Pin 7 und einem Taster an Pin 2. Die LED wird später über 071 (AN) und 070 (AUS) gesteuert. Der Taster sendet später ein 020 (gedrückt = LOW) und 021 (losgelassen = HIGH) an den Empfänger.Arduino UDP Steckplatine

Arduino UDP Sketch

Alles zu erklären wäre jetzt etwas viel. Das wichtigste ist MAC Adresse, IP Adressen und die UDP Ports anzupassen. Die Funktionen zum senden (sendUDP) und empfangen (checkUDP) habe ich ausgelagert um die Übersicht zu erhöhen.

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

// PIN Settings
#define Button 2
#define LED 7

// Network Settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 200);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

// Local UDP port to listen on
unsigned int localPort = 9000;

// Recipient IP
IPAddress RecipientIP(192, 168, 1, 100);

// Recipient UDP Port
unsigned int RecipientPort = 55056;

// Flag Buttonstate
char Buttonstate = 0;

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // for debug only
  Serial.begin(9600);
    
  // start Ethernet
  Ethernet.begin(mac,ip);

  // Start UDP
  Udp.begin(localPort);

  // Button 
  pinMode(Button, INPUT);
  digitalWrite(Button, HIGH);
  
  pinMode(LED, OUTPUT);   // LED an Pin7 
  
  // send UDP Ready 
  sendUDP("UDP Ready");

}

void loop()
{
  checkUDP();

// LED (Receive)
  if (!strcmp(packetBuffer, "070"))
  {
    digitalWrite(LED, LOW);
  }
  if (!strcmp(packetBuffer, "071"))
  {
    digitalWrite(LED, HIGH);
  }

// Button (Send)
  if (digitalRead(Button)==LOW && Buttonstate == 0)
  {
    sendUDP("020");
    Buttonstate = 1;
  }
  
  if (digitalRead(Button)==HIGH && Buttonstate == 1)
  {
    Buttonstate = 0;
  }
}

// Function to check for new UDP packets
void checkUDP()
{  
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    
    // for debug only
    // write packetBuffer to serial
    Serial.print("Packet Content: ");
    Serial.println(packetBuffer);
    
    // send "ACK" as reply
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write("ACK");
    Udp.endPacket();
  }
  delay(10);
}

// Function to send UDP packets
void sendUDP(String text)
{
    Udp.beginPacket(RecipientIP, RecipientPort);
    // Udp.write("Test");
    Udp.print(text);
    Udp.endPacket();
    delay(10);
}

 Test und Verwendungszweck

Testen kann man das ganze sehr gut mit dem Tool Packet Sender (externer Link: PacketSender.com) oder einem anderen UDP Tool. Mit diesem Grundgerüst ist es sehr schnell möglich über das Netzwerk z. B. ein 8-fach Relais Modul zu steuern oder Taster anzubinden. Mit einem Arduino Mega wären dann noch mehr Ein- und Ausgänge möglich. Wie das ganze in die Loxone eingebunden wird zeige ich im nächsten Beitrag.

34 Gedanken zu „Arduino UDP Kommunikation“

  1. Hi Stefan,
    vielen Dank für deinen Sketch! Hat mir für die UDP-Übertragung zwischen Arduino und Loxone massiv weitergeholfen!
    Der Schalter in deiner Zeichnung sollte aber über einen Widerstand – wie unter http://funduino.de/index.php/3-programmieren/nr-5-tastendruck erläutert – eingebunden werden, damit es korrekt funktioniert. Nach deiner Anleitung liefert ein Druck auf den Taster eine 0 und beim Loslassen eine 1.

    Grüße und bis bald mal wieder
    Jörg

    PS: Werde mit dem Arduino jetzt wohl erst einmal eine automatische Bewässerung einiger Topfpflanzen mit Regelung bzw. Steuerungsmöglichkeiten über Loxone umsetzen…

    1. Hallo Jörg,

      freut mich das dir die Beiträge geholfen haben! Einen Widerstand muss du nicht zwingend verwenden! Ich nutze den internen PullUp Widerstand vom AVR-Mikrocontroller und spare mir so die zusätzliche Verkabelung. Auf der Seite Arduino Playground ist der Unterschied anschaulich erklärt. Man muss nur den internen Pull Up Widerstand im Setup mit digitalWrite(pin, HIGH); aktivieren und die If-Abfrage auf LOW statt auf HIGH setzen, um einen Tastendruck zu erkennen. Also vom Prinzip wie bei der Loxone den Eingang invertieren wenn ein Dauerplus anliegt.

      Viele Grüße
      Stefan

  2. Hallo,

    Danke fur deine anleitungen. Ich mochte fragen wie soll ich UDP paket schicken im Loxone einstellen?
    Geht es so: das Loxone schickt UDP paket zu arduino (zu Relay ON) , dan kann es auch status ON/OFF bei Loxone lessen?

    Oder es geht nur so das Loxone schickt macht ON command, dann macht OFF command? Keine info uber status (fur web interface)

    oder man muss dafur Loxone RS485 oder ModBus extension kaufen?
    Ich mochte es fur Loxone -> Arduino -> Relays ON/OFF benutzen
    Danke

    1. Hallo David,

      hast du den Beitrag Loxone UDP Kommunikation schon gelesen? Hier war es eine LED die per UDP Befehl ein- und ausgeschaltet wurde. Im Endefekt nichts anderes als ein Relais.

      Ein RS485 Modul benötigst du für die Ansteuerung von Koppelrelais nicht. Wenn du viele Koppelrelais hast, ist eventuell ein MCP23017 I2C I/O Port sinnvoll.

      Viele Grüße
      Stefan

  3. Hallo,

    Ja klar hab ich nachher gefunden…Ich hab das jetzt uber Loxone und es lauft 🙂
    Geht es auch funktion Knopf “halten” machen? Veil wann ich mach druck und halte es schickt nur 1-druck.
    Ich bin nur gerade mit Arduino angefangen so ich kann noch nicht code schreiben von Anfang aber modifizieren kann ich schon etwas 🙂

    Hast du es auch mit Wifi Shield ausprobiert? oder da kann die pakete verloren sein ?

    1. Hallo David,

      freut mich das es funktioniert! Ich gehe mal davon aus das du an dem virtuellen Ausgang einen Taster angeschlossen hast?! Wenn ja kannst du eine “Halten” Funktion am einfachsten mit einem Taster Baustein in der Loxone aufbauen. Diesen einfach vor dem virtuellen Ausgang setzen und Taster an Eingang “Tr” anschließen. So wechselt das Relais bei jeden Tastendruck den Zustand.

      Egal ob du mit WLAN Modul, Ethernet Shield, 433 MHz Sender, RS485 oder irgendetwas anderem arbeitest, wenn alle Parameter stimmen ist die Kommunikation sehr stabil. Wenn du z. B. schlechten Empfang hast oder sich die Geräte gegenseitig blockieren musst du die Kommunikation bidirektional aufbauen und ggf. ein Errorhandling implementiert werden. Das wird dann aber schon komplexer.

      Viele Grüße
      Stefan

  4. Hallo,

    Danke fur dein tip. Jetzt habe ich noch andere Button2 / LED2 und RELAY 7,8 im code gegeben , aber bei Button 1 oder 2 druck es druck sich mehr mals. Deine original code version ist es ok, kannst du das anschauen was kann da falsch sein?

    Danke

    1. Hallo David,

      dein Sketch (habe ihn aus deinem Kommentar entfernt) war auf dem ersten Blick nur im Aufbau falsch. Abgesehen von den leeren Include Zeilen am Anfang waren darin zwei Loop Schleifen? Das funktioniert nicht. Hast du den richtigen Sketch gepostet?

      Bitte überarbeite den Sketch nochmal, sonst sah er schon ganz gut aus.

      Viele Grüße
      Stefan

  5. neue update:
    ich hab versucht simple code machen nur 1x led,button,relay (https://drive.google.com/open?id=0B1cE2_ezqj26all1cU9LMEw3RkU) und es geht wieder sofort am Loxone 7.4 und 8
    Dann wieder 2x led,button,relay, display, senzor DHT22 (https://drive.google.com/open?id=0B1cE2_ezqj26ZVdlVllLbXpLLWc)
    und es geht wieder ap und zu 🙁

    Wann hast du lust kanst du das vielleicht angucken wo kann das problem sein? Es fangt am line 162 und runter,

    Danke

    1. Hallo David,

      ich habe leider aktuell etwas wenig Zeit das ganze nachzustellen, habe es noch nicht mal geschafft die Loxone Config 8 zu installieren. Ich habe mir den Sketch Greenhouse2-working-inprogress3 angeschaut. Mir sind nur folgende Punkte aufgefallen:
      – In Zeile 158 und 180 hast du mittendrin geschweifte Klammern gesetzt. Ich weiß nicht was das für Auswirkungen hat?!
      – In Zeile 186 liest du den DHT Sensor nochmal. Das kannst du kürzen, schau dir doch mal den Sketch vom Arduino Info Display an.

      Viele Grüße
      Stefan

  6. hi David

    Did you allready fixed the reading on the dht 22 sensor
    now its like
    temp: 20 ° instead of 20.00°
    i tried with a long integer but it doesnt change
    hope you fixed this and can help me out

    greetz

    michael

    1. hello Michael,

      to be honest i dont remember :D, but if im not mistaken i try to contact loxone also and they werent much help.
      haven’t touch it for some time, busy with other things…
      But i will have a look definitely, as spring is coming and i have to come to that project again. Hope within 2 weeks 😉

  7. well ive checked it…

    So from arduino i was sending value like 265 C – in loxone as input is “v.2” and i was separating it by 10.
    hope it helps 😉

  8. Hallo Stefan,
    ich bin Arduino Neuling, habe einen Uno mit shield 2. Deinen sketch habe ich kopiert, aber leider wird die
    geänderte IP Adresse nicht übernommen. Mac habe ich selbstverständlich geändert. Die Leds vom shield
    blinken lustig vor sich hin. Hast Du eine Idee wo das Problem liegen könnte?
    Danke im voraus.
    LG Anton

    1. Hallo Anton,

      ich gehe jetzt davon aus, dass du das Ethernet Shield nicht über die IP Adresse die du gewählt anpingen kannst?! Es sollten auf der Platine dauerhaft die Link und natürlich auch die Power LED leuchten. Wenn die Link Lampe nicht dauerhaft leuchtet und er immer wieder versucht eine Verbindung aufzubauen kann es sein, dass die Auto-Negotiation nicht funktioniert und somit keine Verbindung zustande kommt. Probiere wenn möglich mal einen anderen Switch (möglichst keinen Gigabit Switch) um auf der sicheren Seite zu sein. Wenn die Link Lampe dauerhaft leuchtet, versuche mal mit folgender Zeile am Ende vom Setup die IP-Adresse über den Serial Monitor auszugeben.

      Serial.println(Ethernet.localIP());

      Probiere am besten auch mal das DhcpAddressPrinter Example Skript aus der Arduino IDE aus und lass dir eine IP Adresse vom DHCP Server ausstellen.

      Viele Grüße
      Stefan

  9. Hallo Stefan,
    danke für Deine Antwort. Die “link” und “power”Led leuchten permanent.
    Ich habe Deine Zeile eingefügt, es passiert jedoch nichts.
    Schön langsam glaube ich, dass die shield Baugruppe defekt ist.
    LG Anton

  10. Hallo Stefan,

    erst mal Danke für deine tollen Beiträge. Ich habe mittlerweile schon einige gelesen. Diese haben sehr für mein allgemeines Verständnis beigetragen.

    Ich habe jedoch ein Problem, welches ich nicht anhand deiner Beiträge lösen kann.
    Zwischen Arduino und Loxone sollen Arrays mit verschiedenen Werten hin und her geschickt werden, da die ganzen Ein- und Ausgänge auf dem Arduiono ankommen bzw rausgehen. Der Arduinoteil ist soweit fertig. Die jetztige Formatierung sieht wiefolgt aus, kann aber natürlich angepasst werden.

    1234 4 2 0 0 0 127 255 0 0 0

    Die ersten 6 Bytes sind der Header gefolgt von der Payload. Ist es möglich dies so oder so ähnlich mit der Loxone zu verarbeiten und so ähnlich auch an den Arduino zurück zu senden?

    Vielen Dank für deine Hilfe!

    Gruß
    Chris

    1. Hallo Chris,

      freut mich immer wieder so ein Feedback zu bekommen! Danke! Ich glaube ich habe dein Problem zwar verstanden, aber nicht wieso du diesen Weg gewählt hast?! Die Werte in ein Array zusammenfassen und dann übertragen ist an sich keine schlechte Idee, auf dem Loxone Miniserver hast du aber nur die Möglichkeit mit der Befehlserkennung die Werte zu zerlegen. Ob das mit deinem Array funktioniert, kann ich leider nicht beantworten. Arrays zu senden wäre dann noch ein weiteres Problem.

      Wieso ganze Arrays und nicht einfach die einzelnen Werte direkt auf die entsprechenden Eingänge schreiben bzw. über die Ausgänge versenden? Im Beitrag Arduino UDP und Analogwerte findest ein Beispiel dafür. Eigentlich musst du nur deinen Header um die Arrayposition erweitern und mit “v” in der Befehlserkennung arbeiten, egal ob Virtueller Ausgang oder UDP Eingang.

      Konnte ich dir weiterhelfen? Melde dich gerne nochmal!

      Viele Grüße
      Stefan

  11. Hallo Stefan,

    danke für deine Antwort.
    Ja…ohne deine praxisorientierten Beispiele wäre des Einstieg wesentlich schwieriger für mich. Programmiertechnisch bin ich zwar kein Neuling – hatte (und habe) aber von Loxone noch keine große Ahnung. So ziemlich alles was ich bis jetzt weiß, kommt von deinem Blog :))))
    Ich habe hier wohl zu kompliziert gedacht und den Wald vor lauter Bäumen nicht gesehen. Vielleicht schneide ich einfach kurz mein Projekt an.

    Es läuft lediglich ein Miniserver ohne Extensions und ich möchte es nach Möglichkeit vorerst dabei belassen. Alle Ein- und Ausgänge laufen über einen (Test-)Arduino. Die Arduinoseite ist auch soweit klar. Der wird später noch durch einen Teensy 3.6 ersetzt, da dieser wesentlich schneller ist, mehr Speicher hat und (vor allen Dingen) über deutlich mehr Ein- und Ausgänge verfügt.
    Ich benötige im Endeffekt ca. 30 PWM-Ausgänge, 55 Digitale I/O und 25 Analoge I/O. Das ist mir mit Loxone einfach viel zu teuer. Ich möchte aber trotzdem nicht auf Logik und das Interface der Loxone verzichten.

    Ursprünglich dachte ich, dass bei Veränderung irgendeines Wertes komplett ALLE Werte einmal per UDP an den Miniserver gesendet werden. Das ist wohl der falsche Weg und führt ohnehin zu unnötigem Traffic. Jetzt werde ich die Sache etwas einfacher gestallten und nur den Wert senden, der sich tatsächlich verändert hat. Das Gleiche gilt natürlich auch für die Kommunikation Arduino -> Loxone. Wenn ich das so richtig verstanden habe, muss ich dann leidlich den gleichen Befehl auf den passenden Virtuellen Ausgang legen.

    Die Befehle solle jetzt dann eher so aussehen:

    z.B. KZ1TEMPv

    Die ersten 3 Buchstaben bezeichnen den Raum (in diesem Fall: Kinderzimmer 1), die zweiten 3 Buchstaben den Sensor (Temperatur), Aktor oder Taster und dann kommt der Wert.
    Ist das soweit richtig? Bzw. gibt es hier schon Optimierungsmöglichkeiten?
    Kann ich mit einem Befehl mehrere Analoge oder Digitale Werte empfangen bzw. versenden? Z.B. wenn ich im Wohnzimmer 2 Temperatursensoren habe.

    Vielen Dank für dein Hilfe!

    LG
    Chris

    1. Hallo Chris,

      das hört sich soweit sehr gut an! Ich würde für die Temperatur im Wohnzimmer immer die beiden Werte getrennt verschicken. Also nach deinem Beispiel sollte das WZTEMP1v und WZTEMP2v sein.

      Ich arbeite auch gerade an einem neuen Beitrag für die I2C Input & Output Module mit allem (HTTP-API, Status Seite, OTA, Telnet, UDP, etc.) was man sich so wünscht. Eventuell erscheint demnächst bei Horter-Shop.de auch ein Platine für die Aufnahme eines Wemos D1 die dann in einen WAGO Platinenhalter passt. Vielleicht ist das für dich interessant?

      Noch eine Rückfrage aus reiner Neugier, wofür die vielen Analogen I/O und PWM Ausgänge?

      Viele Grüße
      Stefan

  12. Hi Stefan,

    irgendwie habe ich hier ein Verständnisproblem…..
    Wie bekommt der Arduino denn Zugang zu meinem Netzwerk, wenn ich nirgendwo mein Passwort hinterlegen muss…?
    Oder erstellt der Arduino hier in diesem Fall ein eigenes Netzwerk?

    Grüße, Martin

    1. Hallo Martin,

      die Verbindung wird über das Ethernet-Shield vom Arduino hergestellt. Du musst also nur die IP Adresse im Sketch anpassen und schon kannst du im Netzwerk Daten über UDP versenden. Dafür wird kein Passwort benötigt. Bei einem Wemos D1 mini (ESP8266) würdest du für die WLAN Verbindung natürlich ein Passwort benötigten.

      Viele Grüße
      Stefan

  13. Hallo
    Ich habe mir das Beispiel angesehen und auch benutzt. Leider bekomme ich die Fehlermeldung “lib etherntudp.h” fehlt. Leider habe ich sie per Google oder anderswo nicht gefunden. Aus “Fragmenten” habe ich versucht, mir eine zu “basteln” Leider funktioniert die nur sehr unzureichend. Für einzelne Punkte bekomme ich da immer die Fehlermeldung, das das nicht in dem “scope” ist. Hast Du eine Idee, wo man die lib. herbekommet?

    Mit freundlichen Grüßen Uwe

    1. Hallo Uwe,

      Welche Entwicklungsumgebung verwendest du denn? Wenn du die Arduino IDE verwendest, ist die Library sofort nach der Installation verfügbar. Die Library solltest du im Verzeichnis “C:Program Files (x86)ArduinolibrariesEthernetsrc” finden.

      Viele Grüße
      Stefan

      1. Hallo und Guten Abend Stefan

        Danke für deine Antwort. Sie hat mir weiter geholfen und ich kann jetzt einzelne Daten erfolgreich senden.
        Nun zu meiner nächsten Herausforderung. Ich möchte gerne ein “Array” senden und beim Empfänger wieder auslesen. Egal wie ich es mache, es kommt nicht das an, was ich erwartet habe. Das Array hat 10 Positionen welche mit “0” und “1” gefüllt ist. Wie kann ich “Udp.print” überzeugen, dieses Array zu senden.
        Der nächste Schritt wäre dann, das “Paket” wieder in ein Array einzulesen.

        schönen Abend

        Uwe

        1. Hallo Uwe,

          kurz gesagt, ich würde in einer foreach-Schleife durch das Array gehen und die Werte mit dem Key des Arrays verknüpfen um auf der anderen Seite die Position im Array zu erhalten. Als kleine Starthilfe ein kurzes Snippet:

          int arr [] = { 5, 3, 7, 6 };

          for (int i=0; i < sizeof(arr); i++) {
          int s = arr[i];
          sendUDP("A1" + i + s);
          }

          Damit sollte dann auf der anderen Seite A105, A113, A127 und A136 ankommen. Der erste Wert (A105) bedeutet also A1 als ID für das Array (falls du mehrere senden willst), 0 für die erste Stelle im Array und folgend die 5 als Wert. Schau dir sonst auch mal an wie ich sendUDP und receiveUDP in dem I2C WLAN Gateway verbaut habe.

          Probiere doch mal, ob du mit den Informationen weiterkommst. Falls nicht, melde dich nochmal.

          Viele Grüße
          Stefan

          1. Hallo Stefan

            ich habe mal wieder eine Frage zur Kommunikation per “UDP”. Bei mir kommt es zu dem Effekt, daß die Datenpakete “unterwegs” teilweise verfälscht werden. Gibt es eine “einfache” Möglichkeit das irgendwie zu verhindern?

            Vielleicht hast Du ja eine Idee
            Viele Grüße
            Uwe

          2. Hallo Uwe,

            das ist mir bisher noch nie passiert! Es könnten schlimmstenfalls Pakete verloren gehen aber was verstehst du unter verfälscht? Kannst du ein Beispiel senden? Um das ganze etwas einzukreisen, kannst du ein Muster erkennen? Bist du dir sicher das du keinen Fehler im Sketch hast bzw. die Daten erst im Arduino “verfälscht” werden?

            Leider läuft kein Wireshark auf dem Arduino, dann könnte man mehr sehen! 😉 😀

            Viele Grüße
            Stefan

  14. Hallo Stefan

    Ich wollte mich mal bei Dir für Deine Hilfe bedanken. Ich steuere mittlerweile 3 Arduinos über UDP erfolreich an.

    Viele Grüße Uwe

  15. Hallo Steffan!

    Ich möchte mittels zweier Arduinos mit Ethernetshield Schaltzustände auswerten bzw. fernanzeigen.
    Also am Arduino 1 einen Taster dücken und am Arduino 2 beginnt eine LED zu Leuchten und auch in die andere Richtung soll das so sein.
    Ich habe das alles auch hinbekommen (MAC, IP, Portnummern USW stimmen) aber nur solange der SERIAL MONITOR auf den beiden Rechnern laufen.

    Wie und an welcher Stelle Code muss ich Serial.begin schreiben?

    LG Karl

    1. Hallo Karl,

      ich kann mir gerade nicht erklären, was der Serial Monitor damit zu tun haben soll. Ohne den Sketch zu kennen, fällt mir da gerade nicht viel ein. Sende mir deinen Sketch doch einfach mal an die info@ Adresse und dann schaue schaue mir den mal an.

      Alternativ würde ich einfach sagen, lösche doch mal alles mit Serial raus?! Bestimmt ist dort irgendwo ein while (!Serial) eingebaut und der Sketch wartet die serielle Schnittstelle.

      Viele Grüße
      Stefan

  16. Hallo Steffan,
    ich sende und empfange UDP.
    Ich hänge an der Frage, wie groß Pakete sein dürfen. Kannst Du sagen, wo das festgelegt wird?
    Wodurch werden etwaig Limits festgelegt? Was passiert bei Überschreitung? Usw usf …
    Schöne Grüße,
    Caro

    1. Hallo Caro,

      so tief bin ich leider nicht im Thema und hatte bisher keine Berührungspunkte damit. Soweit ich gelesen habe, ist der Standard auf 24 byte voreingestellt. Vielleicht hilft dir eine Suche nach dem Begriff UDP_TX_PACKET_MAX_SIZE weiter.

      Viele Grüße
      Stefan

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert