Steckdosensteuerung mit Arduino Nano und Ethernet-Shield ENC28J60

Begonnen von dad401, 03 März 2018, 20:57:14

Vorheriges Thema - Nächstes Thema

dad401

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://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
--
aktuelles FHEM auf einem RPI3 mit
HM-MOD-RPI-PCB, CUL868, nanoCUL (868MHz), Signalduino (433MHz), SignalESP (433 MHz) zur Nutzung folgender Systeme:
FS20/Homematic/IT-Steckdosen/OW/Sonstiges

KölnSolar

RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

dad401

Ich hoffe ein Mod kann das Verschieben. Selber kann ich es nicht...

Danke!
--
aktuelles FHEM auf einem RPI3 mit
HM-MOD-RPI-PCB, CUL868, nanoCUL (868MHz), Signalduino (433MHz), SignalESP (433 MHz) zur Nutzung folgender Systeme:
FS20/Homematic/IT-Steckdosen/OW/Sonstiges

Beta-User

Verschieben: 1. Beitrag editieren, Knopf links unten...


Kurz, da mobil
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

dad401

So, Verschieben hat geklappt :-)

Aufgrund folgender Hinweise, 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;
      }
    }
  }
}



--
aktuelles FHEM auf einem RPI3 mit
HM-MOD-RPI-PCB, CUL868, nanoCUL (868MHz), Signalduino (433MHz), SignalESP (433 MHz) zur Nutzung folgender Systeme:
FS20/Homematic/IT-Steckdosen/OW/Sonstiges

Midrag

Danke fürs Teilen!

Bindest du die Relais in FHEM mittels HTTPMOD ein?

dad401

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');;}

--
aktuelles FHEM auf einem RPI3 mit
HM-MOD-RPI-PCB, CUL868, nanoCUL (868MHz), Signalduino (433MHz), SignalESP (433 MHz) zur Nutzung folgender Systeme:
FS20/Homematic/IT-Steckdosen/OW/Sonstiges