Standby und Ethernetprobleme

Hallo,

ich habe mir mit einem Arduino Uno eine Türklingel gebaut, die dann bei mir im Haus bestimmte Telefone klingeln lässt.
An der Haustüre sind ganz normale Klingeltaster, die mir dann das Signal auf einen Digitalen Port geben.

Grundsätzlich funktioniert das ganze auch - allerdings hab ich zwei "kleine" Probleme mit meinem Code.

  1. Nachdem die Klingel einmal gedrückt wurde, passiert nichts mehr wenn sie danach ein zweites Mal drücken lässt.
    Hier habe ich allerdings Abhilfe geschafft, indem ich den Arduino Softwaremäßig nachdem er seine Aktionen ausgeführt hat, neu starten lasse.
    (Vielleicht ist das auch der Grund für Problem #2, aber ich fand das war in dem Moment die einfachste Quick&Dirty-Lösung um die Klingel erst einmal zum laufen zu bekommen.)

  2. Anscheinend geht der Arduino in eine Art Standby-Modus, da mir folgendes aufgefallen ist:
    Ich habe Abends die Klingel getestet => hat problemlos funktioniert.
    Dann habe ich frühs die Klingel wieder gedrückt => nichts ist passiert.
    Daraufhin habe ich ein zweites Mal gedrückt und das Telefon hat geklingelt.
    => Es scheint also, wie wenn der Arduino nach irgendeiner bestimmten Zeit in eine Art Standbymodus geht, durch den 1. Druck auf die Taste aufwacht und beim zweiten Druck erst seine Aktionen auslöst.
    Das ist natürlich nicht so ganz Sinn der Sache, da das ja der User nicht weiß.

#include <Ethernet.h>
#include <SPI.h>
#include <avr/wdt.h>

byte server[] = { 192,168,2,230 };

String getURL = "/tuerklingel/arduino_call.php HTTP/1.0";

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

EthernetClient client;


void setup() {
  Ethernet.begin(mac); 
  client.connect(server, 80);
  pinMode(1, OUTPUT);
}

void loop() {
  if(digitalRead(1) == HIGH) {
    client.print("GET ");
    client.println(getURL);
    client.println(); 
    delay(1000);

    // Hier wird der Arduino neu gestartet
    cli();
    wdt_enable(WDTO_15MS);
    while(1);
  } 
}

gerch:

  1. Nachdem die Klingel einmal gedrückt wurde, passiert nichts mehr wenn sie danach ein zweites Mal drücken lässt.

Mit was für einem Server verbindest Du Dich mit der Zeile:
client.connect(server, 80);
Sieht aus wie ein HTTP-Server?

Kein HTTP-Server hält eine Verbindungen "ewig".
Üblicherweise wird eine aufgebaute Verbindung für genau eine Anfrage offen gehalten und dann geschlossen.

Dein Code ist daher vollkommen ungeeignet. Du kannst die Verbindung nicht nur im Setup aufbauen und dann auf ewig damit arbeiten wollen.

Richtig ist: Verbindung bei Bedarf aufbauen, Anfrage senden, bearbeiten und Verbindung auch auf der Clientseite schließen.

Das mit dem Neustarten des Arduino in der loop-Funktion ist natürlich nur eines: a-ben-teu-er-lich!

void loop() {
  if(digitalRead(1) == HIGH) {
    client.connect(server, 80);
    client.print("GET ");
    client.println(getURL);
    client.println(); 
    delay(1000);
    client.stop();
  } 
}

Und noch ein Fehler: Du liest über digitalRead den Status des Pins 1 ein. Dieser ist bei dir als Ausgang deklariert.

sth77:
Und noch ein Fehler: Du liest über digitalRead den Status des Pins 1 ein. Dieser ist bei dir als Ausgang deklariert.

Aber es funktioniert, hatte ihn vorher auch als INPUT deklariert, da hat es nicht funktioniert?
Verbunden ist dieser kabeltechnisch übrigens einfach mit dem 5V

jurs:

gerch:

  1. Nachdem die Klingel einmal gedrückt wurde, passiert nichts mehr wenn sie danach ein zweites Mal drücken lässt.

Mit was für einem Server verbindest Du Dich mit der Zeile:
client.connect(server, 80);
Sieht aus wie ein HTTP-Server?

Kein HTTP-Server hält eine Verbindungen "ewig".
Üblicherweise wird eine aufgebaute Verbindung für genau eine Anfrage offen gehalten und dann geschlossen.

Dein Code ist daher vollkommen ungeeignet. Du kannst die Verbindung nicht nur im Setup aufbauen und dann auf ewig damit arbeiten wollen.

Richtig ist: Verbindung bei Bedarf aufbauen, Anfrage senden, bearbeiten und Verbindung auch auf der Clientseite schließen.

Das mit dem Neustarten des Arduino in der loop-Funktion ist natürlich nur eines: a-ben-teu-er-lich!

void loop() {

if(digitalRead(1) == HIGH) {
    client.connect(server, 80);
    client.print("GET ");
    client.println(getURL);
    client.println();
    delay(1000);
    client.stop();
  }
}

Deinen Code werde ich mal ausprobieren.
Klingt schon logisch was du sagst ..
Ich verbinde mich mit nem HTTP-Server, der läuft dauerthaft. Ist auch der auf dem die Telefonanlage läuft.

Hast du eine Idee wie man die Sache mit dem neu starten umgehen kann?

gerch:
Hast du eine Idee wie man die Sache mit dem neu starten umgehen kann?

Falls es Dir nicht aufgefallen ist: Mein loop-Code IST OHNE NEUSTART!

Ein Input-Pin muss immer als INPUT oder INPUT_PULLUP deklariert sein.
Bei Deinem Code benötigt der Klingeltaster in der Schaltung einen externen PullDown-Widerstand.
Wenn Du den Klingeltaster direkt und ohne PullDown-Widerstand anschließen möchtest, kannst Du wahlweise auch den internen PullUp-Widerstand aktivieren und auf LOW (betätigter Taster) statt HIGH testen. Code dazu:

void setup() {
  Ethernet.begin(mac); 
  client.connect(server, 80);
  pinMode(1, INPUT_PULLUP); // Klingeltaster angeschlossen an GND und Pin-1
}

void loop() {
  if(digitalRead(1) == LOW) {
    client.connect(server, 80);
    client.print("GET ");
    client.println(getURL);
    client.println(); 
    delay(1000);
    client.stop();
  } 
}

gerch:
Aber es funktioniert, hatte ihn vorher auch als INPUT deklariert, da hat es nicht funktioniert?
Verbunden ist dieser kabeltechnisch übrigens einfach mit dem 5V

Wenn Du auf einen OUTPUT deklarierten Pin im LOW-Zustand eine Spannung von 5V draufschaltest, dann ist das der klassische KURZSCHLUSS! Da ist es nur eine Frage der Zeit, bis dieses Beinchen des Arduino-Controllers DURCHGEBRANNT sein wird, wenn Du es mit Kurzschluss betreibst. Weil Du genialerweise Pin-1 nimmst, was gleichzeitig auch der TX-Sendepin für die serielle Schnittstelle ist, würde ein Durchbrennen dieses Pins dazu führen, dass Du nicht nur ein durchgebranntes Beinchen am Controller verlierst (also einen digitalen I/O), sondern dass Du über den Bootloader überhaupt keine neuen Sketche mehr auf den Controller hochladen kannst.

Du darfst NIE auf einen OUTPUT geschalteten Pin einen gegensätzlichen Spannungspegel anlegen:
OUTPUT LOW verbunden mit +5V ==> KURZSCHLUSS
OUTPUT HIGH verbunden mit GND ==> KURZSCHLUSS

Nur hochohmig eingestellte Pins (INPUT oder INPUT_PULLUP) darfst Du mit verschiedenen Spannungspegeln verbinden. Wenn Du ein Signal messen möchtest, kommt nur INPUT oder INPUT_PULLUP für den Pin in Frage.

Einen Ausgang (OUTPUT) verwendest Du, um irgendwas mit einem abgehenden Signal anzusteuern, z.B. wenn eine LED leuchten oder ein Relais schalten soll. Oder wenn Du wie bei Dir einen Kurzschluss fabrizieren und den Arduino killen möchtest.

So, jetzt meld ich mich auch nochmal.

Mein Code sieht jetzt wie folgt aus:

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

byte server[] = { 192,168,2,230 };
String getURL = "/tuerklingel/arduino_call.php HTPP/1.0";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetClient client;

void setup() {
  Ethernet.begin(mac);
  client.connect(server, 80);
  pinMode(1, INPUT);
  digitalWrite(1, HIGHT);
}

void loop() {
  if(digitalRead(1) == LOW) {
    client.connect(server, 80);
    client.print("GET ");
    client.println(getURL);
    client.println();
    delay(1000);
    client.stop();
  }
}

Ich hab das mit dem pinMode Input und dem digitalWrite HIGH deswegen so gemacht, weil ich noch die IDE 1.0 benutze (war froh dass ich das auf meinem Squeeze-Server zum laufen gebracht hab, deswegen hab ich das jetzt erstmal nicht geupdatet).

Wenn ich mich da jetzt richtig belesen habe, müsste das die richtige Vorgehensweise sein um den Pullup unter < 1.0.1 zu aktivieren?

Es funktioniert jetzt übrigens ebenfalls :slight_smile: .. wenn das aber mit dem Pullup wirklich rund läuft, ist es ja definitiv die bessere und langlebigere Variante :slight_smile: