FHEM Forum

Verschiedenes => Bastelecke => Thema gestartet von: dad401 am 03 März 2018, 20:57:14

Titel: Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: dad401 am 03 März 2018, 20:57:14
Hallo,

soweit ich googlen konnte, gibt es keine/wenige Beispiele für eine Steckdosensteuerung über Arduino Nano und Ethernet-Shield ENC28J60. Ich verwende hierfür die Libaries UIPEthernet.h und RCSwitch.h.
So oft programmiere ich nicht, aber ich fand es ganz spannend Speicher sparen zu müssen für die ganzen Texte (Stichwort: PROGMEM). Abgeschaut habe hier mir insbesondere die Quellen hier:
https://github.com/RuiSantosdotme/Random-Nerd-Tutorials/blob/master/Projects/Arduino_with_Ethernet_Shield.c (https://github.com/RuiSantosdotme/Random-Nerd-Tutorials/blob/master/Projects/Arduino_with_Ethernet_Shield.c)
https://www.tweaking4all.com/hardware/arduino/arduino-enc28j60-ethernet/ (https://www.tweaking4all.com/hardware/arduino/arduino-enc28j60-ethernet/)

Hier der Sketch:
#include <UIPEthernet.h> // Used for Ethernet
#include <RCSwitch.h>
#include <avr/pgmspace.h>

// **** ETHERNET SETTING ****
byte mac[] = { 0x54, 0x34, 0x41, 0x30, 0x30, 0x31 };                                     
IPAddress ip(192, 168, 1, 11);                       
EthernetServer server(80);
RCSwitch mySwitch = RCSwitch();
String readString;

//                                                    0          1        2         3         4            5        6         7        8         9         10       11        12      13       14      15        16      17        18       19       20
const unsigned long socketcode_on[21]   PROGMEM = {5526835,  5526979,  5527299,  5528835,  5534979,    5575987,  5576131,  5576451,  5577987,  5584131,  1234567, 1234567, 1234567, 1328465, 1331537, 1332305, 1332497, 1377617, 1380689, 1381457, 1381649};
const unsigned long socketcode_off[21]  PROGMEM = {5526844,  5526988,  5527308,  5528844,  5534988,    5575996,  5576140,  5576460,  5577996,  5584140,  1234567, 1234567, 1234567, 1328468, 1331540, 1332308, 1332500, 1377620, 1380692, 1381460, 1381652};
const int socketcode_puls[21]           PROGMEM = {186,      186,      186,      186,      186,        177,      177,      177,      177,      177,      294,     294,     294,     302,     302,     302,     302,     322,     322,     322,     322};
//char* socketnames[] =                           {"0308-1", "0308-2", "0308-3", "0308-4", "0308-ALL", "0316-1", "0316-2", "0316-3", "0316-4", "0316-5", "YK1-1", "YK1-2", "YK1-3", "BRN-A", "BRN-B", "BRN-C", "BRN-D", "POL-A", "POL-B", "POL-C", "POL-D"};
char* YK1codes[] = {"FFF0FF000001","FFF0FF000100","FFF0FF000001"};
//int numofsockets = 21;

int idx1 = 0;
int idx2 = 0;
long pulse;

void setup() {
  Serial.begin(9600);

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.print(F("IP Address: "));
  Serial.println(Ethernet.localIP());

  Serial.println(F("setup RC transmitter"));
  mySwitch.enableTransmit(9);
  mySwitch.setProtocol(1);
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();

  if (client)
  { 
    Serial.println(F("-> New Connection"));

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;

    while (client.connected())
    {
      if (client.available())
      {
        char c = client.read();
       
        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string
          readString += c;
          //Serial.print(c);
         }

        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        //if HTTP request has ended
        if (c == '\n' && currentLineIsBlank)
        {
          Serial.println(F("main request")); //print to serial monitor for debuging
          //Serial.println(F("main - request string:")); //print to serial monitor for debuging
          //Serial.println(readString); //print to serial monitor for debuging
          //Serial.println(F("end of request string")); //print to serial monitor for debuging

          client.println(F("<!DOCTYPE html><html>"));
          client.println(F("<body><center>"));
          client.println(F("<h1>Etekcity 0308 und 0316, YK1, Brennenstuhl RCS 1000N (BRN) und Pollin 26AY (POL)</h1>"));
         
          client.println(F("<p>0308-1 <a href=\"-0-ON\"><button>ON</button></a>&nbsp;<a href=\"-0-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0308-2 <a href=\"-1-ON\"><button>ON</button></a>&nbsp;<a href=\"-1-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0308-3 <a href=\"-2-ON\"><button>ON</button></a>&nbsp;<a href=\"-2-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0308-4 <a href=\"-3-ON\"><button>ON</button></a>&nbsp;<a href=\"-3-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0308-A <a href=\"-4-ON\"><button>ON</button></a>&nbsp;<a href=\"-4-OFF\"><button>OFF</button></a></p>"));
         
          client.println(F("<hr>"));
          client.println(F("<p>0316-1 <a href=\"-5-ON\"><button>ON</button></a>&nbsp;<a href=\"-5-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0316-2 <a href=\"-6-ON\"><button>ON</button></a>&nbsp;<a href=\"-6-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0316-3 <a href=\"-7-ON\"><button>ON</button></a>&nbsp;<a href=\"-7-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0316-4 <a href=\"-8-ON\"><button>ON</button></a>&nbsp;<a href=\"-8-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>0316-5 <a href=\"-9-ON\"><button>ON</button></a>&nbsp;<a href=\"-9-OFF\"><button>OFF</button></a></p>"));
         
          client.println(F("<hr>"));
          client.println(F("<p>YK1-1 <a href=\"-10-ON\"><button>ON</button></a>&nbsp;<a href=\"-10-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>YK1-2 <a href=\"-11-ON\"><button>ON</button></a>&nbsp;<a href=\"-11-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>YK1-3 <a href=\"-12-ON\"><button>ON</button></a>&nbsp;<a href=\"-12-OFF\"><button>OFF</button></a></p>"));
         
          client.println(F("<hr>"));
          client.println(F("<p>BRN-A <a href=\"-13-ON\"><button>ON</button></a>&nbsp;<a href=\"-13-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>BRN-B <a href=\"-14-ON\"><button>ON</button></a>&nbsp;<a href=\"-14-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>BRN-C <a href=\"-15-ON\"><button>ON</button></a>&nbsp;<a href=\"-15-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>BRN-D <a href=\"-16-ON\"><button>ON</button></a>&nbsp;<a href=\"-16-OFF\"><button>OFF</button></a></p>"));

          client.println(F("<hr>"));
          client.println(F("<p>POL-A <a href=\"-17-ON\"><button>ON</button></a>&nbsp;<a href=\"-17-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>POL-B <a href=\"-18-ON\"><button>ON</button></a>&nbsp;<a href=\"-18-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>POL-C <a href=\"-19-ON\"><button>ON</button></a>&nbsp;<a href=\"-19-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>POL-D <a href=\"-20-ON\"><button>ON</button></a>&nbsp;<a href=\"-20-OFF\"><button>OFF</button></a></p>"));

          client.println(F("</center></body>"));
          break;
        }

        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r')
        {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }

    // give the web browser time to receive the data
    delay(10);

    // close the connection:
    client.stop();
    Serial.println(F("   Disconnected\n"));

    //controls the Arduino if you press the buttons
    if (readString.indexOf("-ON") >0){
      // find socket number and convert it to integer
      idx1 = readString.indexOf('-');
      idx2 = readString.indexOf('-',idx1+1);
      readString=readString.substring(idx1+1, idx2);
      idx1 = readString.toInt();
      Serial.print(F("send ON code for socket number: "));
      Serial.println(idx1);

      Serial.print(F("set pulse length to: "));
      Serial.println(pgm_read_word(&socketcode_puls[idx1]));

      Serial.print(F("send pulse: "));

      mySwitch.setPulseLength(pgm_read_word(&socketcode_puls[idx1]));
      switch (idx1) {
        // YK1 sockets
        case 10:
        case 11:
        case 12:
            Serial.println(YK1codes[idx1-10]);
            mySwitch.sendTriState(YK1codes[idx1-10]);
            break;
        default:
            pulse = pgm_read_dword((&socketcode_on[idx1]));
            Serial.println(pulse);
            mySwitch.send(pulse, 24);
            break;
      }
    }
    if (readString.indexOf("-OFF") >0){
      // find socket number and convert it to integer
      idx1 = readString.indexOf('-');
      idx2 = readString.indexOf('-',idx1+1);
      readString=readString.substring(idx1+1, idx2);
      idx1 = readString.toInt();
      Serial.print(F("send OFF code for socket number: "));
      Serial.println(idx1);

      Serial.print(F("set pulse length to: "));
      Serial.println(pgm_read_word(&socketcode_puls[idx1]));

      Serial.print(F("send pulse: "));

      mySwitch.setPulseLength(pgm_read_word(&socketcode_puls[idx1]));
      switch (idx1) {
        // YK1 sockets
        case 10:
        case 11:
        case 12:
            Serial.println(YK1codes[idx1-10]);
            mySwitch.sendTriState(YK1codes[idx1-10]);
            break;
        default:
            pulse = pgm_read_dword((&socketcode_off[idx1]));
            Serial.println(pulse);
            mySwitch.send(pulse, 24);
            break;
      }
    }
    //clearing string for next read
    readString=""; 
    idx1=0;
  }
}



Das ganze läuft ähnlich auch auf einem ESP8266 über WLAN - ich wollte aber gern eine LAN-Lösung.
Der 433MHz-Transmitter ist hier an D9 angeschlossen!
Wer fliegend verkabelt, muss auch die 5V verkabeln, sonst funktioniert der ENC28J60 nicht. Wenn der Arduino sowieso aufgesteckt wird, ist dies sowieso verbunden.

Gruss
Marcus
Titel: Antw:Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: KölnSolar am 03 März 2018, 21:41:12
ist in Bastelecke besser aufgehoben  ;)
Markus
Titel: Antw:Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: dad401 am 05 März 2018, 23:37:14
Ich hoffe ein Mod kann das Verschieben. Selber kann ich es nicht...

Danke!
Titel: Antw:Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: Beta-User am 06 März 2018, 07:20:15
Verschieben: 1. Beitrag editieren, Knopf links unten...


Kurz, da mobil
Titel: Antw:Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: dad401 am 29 März 2018, 22:37:56
So, Verschieben hat geklappt :-)

Aufgrund folgender Hinweise (https://forum.arduino.cc/index.php?topic=425194.0), habe ich den Code noch etwas "optimiert", da ich auch das dort beschriebene Problem habe (ENC28J60 bzw. die Weboberfläche ist nach einer Weile nicht mehr erreichbar). Die String Klasse habe ich rausgeworfen und arbeite nur noch über char-arrays. Speicher hat es schon mal gespart.
Ob es geholfen hat, muss ich noch testen...

#include <UIPEthernet.h> // Used for Ethernet
#include <RCSwitch.h>
#include <avr/pgmspace.h>
#include <RCSwitch.h>


// **** ETHERNET SETTING ****
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };                                     
IPAddress ip(192, 168, 1, 1);                       
EthernetServer server(80);
RCSwitch mySwitch = RCSwitch();
char request[13];
char number[3] = {'0', '0', '\0'};
char *pch;
byte idx_char;

//                                                    0          1        2         3         4            5        6         7        8         9         10       11        12      13       14      15        16      17        18       19       20
const unsigned long socketcode_on[21]   PROGMEM = {5526835,  5526979,  5527299,  5528835,  5534979,    5575987,  5576131,  5576451,  5577987,  5584131,  1234567, 1234567, 1234567, 1328465, 1331537, 1332305, 1332497, 1377617, 1380689, 1381457, 1381649};
const unsigned long socketcode_off[21]  PROGMEM = {5526844,  5526988,  5527308,  5528844,  5534988,    5575996,  5576140,  5576460,  5577996,  5584140,  1234567, 1234567, 1234567, 1328468, 1331540, 1332308, 1332500, 1377620, 1380692, 1381460, 1381652};
const int socketcode_puls[21]           PROGMEM = {186,      186,      186,      186,      186,        177,      177,      177,      177,      177,      294,     294,     294,     302,     302,     302,     302,     322,     322,     322,     322};
//char* socketnames[] =                           {"0308-1", "0308-2", "0308-3", "0308-4", "0308-ALL", "0316-1", "0316-2", "0316-3", "0316-4", "0316-5", "YK1-1", "YK1-2", "YK1-3", "BRN-A", "BRN-B", "BRN-C", "BRN-D", "POL-A", "POL-B", "POL-C", "POL-D"};
char* YK1codes[] = {"FFF0FF000001","FFF0FF000100","FFF0FF000001"};
//int numofsockets = 21;

long pulse;

void setup() {
  Serial.begin(9600);

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.print(F("IP: "));
  Serial.println(Ethernet.localIP());

  //Serial.println(F("setup RC transmitter"));
  mySwitch.enableTransmit(9);
  mySwitch.setProtocol(1);
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();

  if (client)
  { 
    //Serial.println(F("-> New Connection"));

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    idx_char = 0;

    while (client.connected())
    {
      if (client.available())
      {
        if (idx_char < 12) {
          request[idx_char] = client.read();
          //Serial.print(idx_char);
          //Serial.print(request[idx_char]);
          idx_char++;
        } else {
          request[idx_char] = client.read();
        } 
             
        //read char by char HTTP request
        //if (readString.length() < 100) {
          //store characters to string
          //readString += c;
          //Serial.print(c);
         //}

        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        //if HTTP request has ended
        if (request[idx_char] == '\n' && currentLineIsBlank)
        {
          //Serial.println(F("main request")); //print to serial monitor for debuging
          //Serial.println(F("main - request string:")); //print to serial monitor for debuging
          //Serial.println(readString); //print to serial monitor for debuging
          //Serial.println(F("end of request string")); //print to serial monitor for debuging

          client.println(F("<!DOCTYPE html><html>"));
          client.println(F("<body><center>"));
          client.println(F("<h1>Etekcity 0308/0316, YK1, Brennenstuhl RCS 1000N, Pollin 26AY</h1>"));
         
          client.println(F("<p>308-1 <a href=\"-00-ON\"><button>ON</button></a>&nbsp;<a href=\"-00-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>308-2 <a href=\"-01-ON\"><button>ON</button></a>&nbsp;<a href=\"-01-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>308-3 <a href=\"-02-ON\"><button>ON</button></a>&nbsp;<a href=\"-02-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>308-4 <a href=\"-03-ON\"><button>ON</button></a>&nbsp;<a href=\"-03-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>308-A <a href=\"-04-ON\"><button>ON</button></a>&nbsp;<a href=\"-04-OFF\"><button>OFF</button></a></p>"));
         
          client.println(F("<hr>"));
          client.println(F("<p>316-1 <a href=\"-05-ON\"><button>ON</button></a>&nbsp;<a href=\"-05-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>316-2 <a href=\"-06-ON\"><button>ON</button></a>&nbsp;<a href=\"-06-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>316-3 <a href=\"-07-ON\"><button>ON</button></a>&nbsp;<a href=\"-07-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>316-4 <a href=\"-08-ON\"><button>ON</button></a>&nbsp;<a href=\"-08-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>316-5 <a href=\"-09-ON\"><button>ON</button></a>&nbsp;<a href=\"-09-OFF\"><button>OFF</button></a></p>"));
         
          client.println(F("<hr>"));
          client.println(F("<p>YK1-1 <a href=\"-10-ON\"><button>ON</button></a>&nbsp;<a href=\"-10-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>YK1-2 <a href=\"-11-ON\"><button>ON</button></a>&nbsp;<a href=\"-11-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>YK1-3 <a href=\"-12-ON\"><button>ON</button></a>&nbsp;<a href=\"-12-OFF\"><button>OFF</button></a></p>"));
         
          client.println(F("<hr>"));
          client.println(F("<p>BRN-A <a href=\"-13-ON\"><button>ON</button></a>&nbsp;<a href=\"-13-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>BRN-B <a href=\"-14-ON\"><button>ON</button></a>&nbsp;<a href=\"-14-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>BRN-C <a href=\"-15-ON\"><button>ON</button></a>&nbsp;<a href=\"-15-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>BRN-D <a href=\"-16-ON\"><button>ON</button></a>&nbsp;<a href=\"-16-OFF\"><button>OFF</button></a></p>"));

          client.println(F("<hr>"));
          client.println(F("<p>POL-A <a href=\"-17-ON\"><button>ON</button></a>&nbsp;<a href=\"-17-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>POL-B <a href=\"-18-ON\"><button>ON</button></a>&nbsp;<a href=\"-18-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>POL-C <a href=\"-19-ON\"><button>ON</button></a>&nbsp;<a href=\"-19-OFF\"><button>OFF</button></a></p>"));
          client.println(F("<p>POL-D <a href=\"-20-ON\"><button>ON</button></a>&nbsp;<a href=\"-20-OFF\"><button>OFF</button></a></p>"));

          client.println(F("</center></body>"));
          break;
        }

        if (request[idx_char] == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (request[idx_char] != '\r')
        {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }

    // give the web browser time to receive the data
    delay(10);

    // close the connection:
    client.stop();
    //Serial.println(F("   Disconnected\n"));

    //controls the Arduino if you press the buttons
    if (pch = strstr(request,"-ON"))
    {
      number[0]=request[pch-request-2];
      number[1]=request[pch-request-1];

      Serial.print(F("send ON code to socket: "));
      Serial.println(atoi(number));

      Serial.print(F("set pulse length to: "));
      Serial.println(pgm_read_word(&socketcode_puls[atoi(number)]));

      Serial.print(F("send pulse: "));
      mySwitch.setPulseLength(pgm_read_word(&socketcode_puls[atoi(number)]));

      switch (atoi(number)) {
        // YK1 sockets
        case 10:
        case 11:
        case 12:
            Serial.println(YK1codes[atoi(number)-10]);
            mySwitch.sendTriState(YK1codes[atoi(number)-10]);
            break;
        default:
            pulse = pgm_read_dword((&socketcode_on[atoi(number)]));
            Serial.println(pulse);
            mySwitch.send(pulse, 24);
            break;
      }
    }

    if (pch = strstr(request,"-OFF"))
    {
      number[0]=request[pch-request-2];
      number[1]=request[pch-request-1];

      Serial.print(F("send OFF code to socket: "));
      Serial.println(atoi(number));

      Serial.print(F("set pulse length to: "));
      Serial.println(pgm_read_word(&socketcode_puls[atoi(number)]));

      Serial.print(F("send pulse: "));
      mySwitch.setPulseLength(pgm_read_word(&socketcode_puls[atoi(number)]));

      switch (atoi(number)) {
        // YK1 sockets
        case 10:
        case 11:
        case 12:
            Serial.println(YK1codes[atoi(number)-10]);
            mySwitch.sendTriState(YK1codes[atoi(number)-10]);
            break;
        default:
            pulse = pgm_read_dword((&socketcode_off[atoi(number)]));
            Serial.println(pulse);
            mySwitch.send(pulse, 24);
            break;
      }
    }
  }
}



Titel: Antw:Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: Midrag am 19 Mai 2018, 10:06:08
Danke fürs Teilen!

Bindest du die Relais in FHEM mittels HTTPMOD ein?
Titel: Antw:Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60
Beitrag von: dad401 am 24 September 2018, 19:47:39
Falls Du es noch liest: ich habe es dann so in FHEM eingebunden (Beispiel für Steckdose 308 Nummer 4):

define FS_0308_4 dummy
attr FS_0308_4 userattr room_map structexclude
attr FS_0308_4 room Steckdosen
attr FS_0308_4 webCmd on:off

define FS0308_4_on notify FS_0308_4:on {system('wget http://192.168.1.1/-03-ON -O /dev/null -q >/dev/null');;}
define FS0308_4_off notify FS_0308_4:off {system('wget http://192.168.1.1/-03-OFF -O /dev/null -q >/dev/null');;}