Pages: 1 [2] 3 4   Go Down
Author Topic: Ausgang per Web schalten mit PHP  (Read 10869 times)
0 Members and 1 Guest are viewing this topic.
Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo GOTT  smiley-wink
äh, ich meine Mario...

Also, es funktioniert jetzt!!!
Jetzt habe ich glaube ich auch kapiert, was ich falsch gemacht habe.
Manchmal sieht es erst wenn es fertig ist. Habe zwar schon ein bischen mit PHP gemacht,
aber leider zu wenig um die kurzform der schreibweise zu verstehen.
Du bist wohl auch PHP-Guru, oder ?
Was wir hier,nein was DU, hier gemacht hast, hat ja eigentlich nix mit Arduino zu tun.
Also echt Suuper !! Mein Respekt, das du die Gedult hattest mich da so ran zu führen, das ein Anfänger wie ich, das auch versteht und es letztendlich läuft. DANKE !!

Jetzt muss das ganze noch für 8 Ausgänge optimiert werden und ein büschen aufhübschen...  smiley-lol

Dennoch habe noch eine Frage, vieleicht bekomme ich das aber auch allein irgendwie raus.
Die Pins sind ja nun als Ausgänge deklariert "pinMode(Pin4, OUTPUT);" , wenn der Sketch startet, ist Pin4 AN, obwohl er AUS-geschaltet sein sollte.
Und wenn ich dann auf AN klicke schaltet er AUS, sozusagen sind 1 und 0 vertauscht.
Was ich aber nicht verstehe, da ich doch mit dem PHP-Script 1 (also AN) sende und er aber AUS macht.
Hier der funktionierende Sketch:
Code:
/*
  Webclient
  Es soll mittels einer PHP-Seite, die auf einem Webserver liegt,
  ein oder mehrere Ausgänge AN/AUS geschaltet werden.
*/

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

// Ethernet einrichten
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xEE, 0xF3 };
IPAddress ip(192,168,178,216);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255, 255, 255, 0);

// telnet defaults to port 23
EthernetServer server(23);
boolean gotAMessage = false; // whether or not you got a message from the client yet

int Pin4 = 4;
int Pin5 = 5;
int Pin9 = 9;

void setup() {
  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);
  // start listening for clients
  server.begin();
  // open the serial port
  Serial.begin(9600);
  pinMode(Pin4, OUTPUT);
  pinMode(Pin5, OUTPUT);
  pinMode(Pin9, OUTPUT);
}

void loop() {
  // wait for a new client:
  EthernetClient client = server.available();
 
  // when the client sends the first byte, say hello:
  if (client) {
    if (!gotAMessage) {
      Serial.println("We have a new client");
      gotAMessage = true;
    }
   
  //Achtung super simpler Quickhack ohne Püfung der Eingabe oder ob Daten vorhanden sind
char input[3];

for(int i=0;i<3;i++) {
    input[i] = client.read();   
}

//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
}
//pin lesen und an den Client schicken
if(input[0] == 'R') {
   client.print(digitalRead(input[1]));
}
 }
 client.stop();
 client.flush();
}
Klar, ich kann einfach 1 und 0 tauschen, aber damit habe ich es ja nicht verstanden.


Ansonsten, nochmal VIELEN DANK für deine Mühe und Geduld Mario aka "mkl0815"
« Last Edit: May 01, 2012, 07:21:00 am by Cetax » Logged

*greatz*

 CeTax

www dot blinkmann dot de


Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Kein Problem, der Aufwand war ja überschaubar und Du hast einiges gelernt. Mit HTML und PHP wurschtel ich schon seit über 10 Jahren herum. Ich wollte halt nur nicht sofort die komplette Lösung liefern, Du solltest schon selbst bestimmte Dinge machen. Es geht ja schliesslich darum, das Du am Ende etwas lernst.
Ansonsten würde ich noch aufpassen, beim Ethernet-Shield und beim Arduino-Ethernet wird das Pin 4 glaub ich für das Chip-Select der SD-Karte verwendet. Keine Ahnung, ob das einen Einfluss hat. Ich denke nicht zwar nicht, aber man weiss ja nie.
0 und 1 sollten eigentlich nicht vertauscht sein, ist es bei mir auch nicht. Schau mal nach, nicht das Dein HTML-Formular bei den radio-buttons die Werte vertauscht hat. Das ist der Grund warum ich GET statt POST verwende, da sehe ich in der URL sofort was verschickt wird.
Hier der Code auf dem Arduino, den ich verwende:
Code:
/*
 Arduino TCP Control
 
 A simple server that waits for incoming connections to set or read
 digital Output Pins
 
 Using an Arduino Wiznet Ethernet shield or an Arduino Ethernet.
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 2012-04-28
 by Mario Keller
 
 */

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

// MAC und IP Konfiguration
byte mac[] = {
  0xDE, 0xAD, 0xBC, 0xAF, 0xFE, 0xED };
IPAddress ip(192,168,0, 29);
IPAddress gateway(192,168,0, 252);
IPAddress subnet(255, 255, 255, 0);

// warten auf port 23
EthernetServer server(23);

void setup() {
  //Ethernet initialisieren
  Ethernet.begin(mac, ip, gateway, subnet);
  // Server starten
  server.begin();
  // serielle konsole öffnen (debug)
  Serial.begin(9600);
}

void loop() {

  // auf eine eingehende Verbindung warten
  EthernetClient client = server.available();
  //wenn verbindung, dann 3 bytes lesen;
  if (client) {

    char command =client.read();
    byte pinnumber =client.read();
    byte pinvalue =client.read();
    byte returnvalue = 0;

    //Kommando auswerten
    switch(command) {

    case 'S':
      Serial.print("S Kommando empfangen, setze Pin ");
      Serial.print(pinnumber);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(pinnumber,pinvalue);
      //gesetzten wert auch zurückliefern
      returnvalue=pinvalue;
      break;

    case 'R':
      returnvalue = digitalRead(pinnumber);
      Serial.print("R Kommando empfangen, lese Pin ");
      Serial.print(pinnumber);
      Serial.print(". Wert = ");
      Serial.println(returnvalue);
      break;

    default:
      Serial.println("Fehler, unbekanntes Kommando");    
      break;

    }  
    
    // rückantwort senden (1 byte) die "+48" sorgen dafür das der Wert 0 oder 1 als Zeichen "0" oder "1" übertragen werden.
    //das vereinfacht die verarbeitung in php.
    client.write(returnvalue+48);
    
    //übertragung erzwingen
    client.flush();
    
    //10ms delay damit daten sicher gesendet werden.
    delay(10);
    
    //wichtg! client verbindung beenden
    client.stop();
  }
}
« Last Edit: May 01, 2012, 08:40:28 am by mkl0815 » Logged

Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,
also dein Sketch sieht Professionell aus, mit Überprüfung und so, nicht schlecht  smiley
Ich habe rausgefunden, warum die LED immer an war, obwohl 0 gesendet wurde.
Ich würde mal sagen, klassischer Anfänger Fehler, ich hatte  verkehrtrum gepohlt.
 smiley-mr-green

Jetzt gehts  smiley-grin
Nun geht es weiter, das ganze per Zeit zu steuern, also das ich sage, öffne Ventil für 15min und dann wieder zu, mal sehen, wie weit ich da kommen... smiley-confuse

Mach ich das am besten per PHP und übergebe das dann an den Arduino ?
Oder sollte der Arduino das machen ? (Mit millis oderso ?)
Logged

*greatz*

 CeTax

www dot blinkmann dot de


Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Moin Moin,
kann man auch ein viertes Byte übertragen ?
Z.b. 15 ?
Soll bedeuten, das die LED für 15 min AN ist und sich dann wieder ausschaltet.
Ich dachte da an sowas wie, die "15" wird an millis/delay übergeben.
Code:
//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
   delay[3];
}
Auszug aus der PHP:
Code:
if(isset($_GET['led2'])) {
    $led2 = $_GET['led2'];
    arduino_send($arduino_ip,$arduino_port,"S".chr(9).chr(1).chr($led2[])); //Pin9 AN für x min
} else {
    $led2 = arduino_send($arduino_ip,$arduino_port,"R".chr(9).chr(0));
}
....
<form action="">
  <p>
   <select name="led2[]">
    <option value="15">15 min</option>
    <option value="30">30 min</option>
    <option value="60">60 min</option>
   </select>
  </p>
   <input type="submit" name="submit" value="Starten">
   <input type="reset" name="stop" value="Stop">
</form>
Geht sows oder mal wieder völlig daneben ?  smiley-red

« Last Edit: May 01, 2012, 04:21:51 pm by Cetax » Logged

*greatz*

 CeTax

www dot blinkmann dot de


Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Du willst also eine Zeitshaltung bauen? Natürlich geht das, allerdings wird das aus verschiedenen Gründen etwas komplexer.
Aber der Reihe nach.
Code:
//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
   delay[3];
}
Das geht schon mal nicht, wenn schon dann delay(input([3]), was aber bei input[3]=15 nur 15 Millisekunden und nicht 15 Minuten wären. Ein 4. Byte übertragen ist kein Problem, das ist nur eine Anpassung im PHP Code, indem Du dem "$command" ein 4. byte hinzufügst. Dein Problem beim Delay ist aber, das der Arduino dann die nächsten X Minuten (im schlimmsten Fall eine Stunde) nicht auf weitere Verbindungen reagieren würde.
Die Zeitsteuerung über PHP zu machen ist auch keine gute Idee, da Du ja ständig "reloads" der Seite machen müßtest, bzw. mit Ajax arbeiten. Und wenn der User den Browser schliesst, dann geht dein Ventil im schlimmsten Fall nie wieder zu :-)

Ein guter Grundsatz bei komplexen Systemen ist immer, das Aufgaben nach Möglichkeit an den Stellen (in den Komponenten) gelöst werden, wo sie anfallen.
In Deinem Fall ist das der Arduino, der ja nach z.b. 15 Minuten das Ventil wieder schliessen muss.
Ich würde einfach für jedes "Ventil" (sprich Arduino Ausgang) eine Variable "unsigned long vtimer1 = millis() + (1000 * 60 * input[3])" definieren, wenn das "Ventil" über die PHP-Funktion geschaltet wird. vtimer1 (als Beispiel für Ventil 1) enthält dann den Zeitpunkt, wann das Ventil wieder umgeschaltet werden soll. Das kannst Du dann in jedem loop() Durchlauf mit dem aktuellen Wert von millis() vergleichen. Das kannst Du dann unabhängig für jedes Ventil machen, ohne ein delay() verweden zu müssen.

Zu Deinem PHP-Code:
Warum verwendest Du immer Arrays in den Variablennamen?
z.b.
Code:
<select name="led2[]">
Das ist eher unübersichtlich und eigentlich unnötig, außer Du willst ALLE "Ventile" in ein Array packen, dann würde es Sinn machen, müßte aber auch anders aussehen.
Mario.
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,
ja also, das habe ich mir schon gedacht, Einfach geht es ja nie  smiley-mr-green
Aber gut, ich hoffe das kriege auch irgendwie hin, ich werde heute abend mal eine "Nachtschicht" einlegen und mal schauen wie weit ich komme (wahrscheinlich garnicht weit  smiley-sad )
An millis hatte ich auch schon gedacht... (Obwohl Denke ja nicht so meine Stärke ist, wie wir festgestellt haben.. LoL )

Quote
Zu Deinem PHP-Code:
Warum verwendest Du immer Arrays in den Variablennamen?
z.b.
Code:

<select name="led2[]">

Das ist eher unübersichtlich und eigentlich unnötig, außer Du willst ALLE "Ventile" in ein Array packen, dann würde es Sinn machen, müßte aber auch anders aussehen.
Mmmh, das stammt doch aus dem Formular ? Oder irre ich da?
Code:
<select name="led2[]">
    <option value="15">15 min</option>
    <option value="30">30 min</option>
    <option value="60">60 min</option>
   </select>
Da wird doch bei "led2[]" die Zeit, die Ausgewählt wird, rein gepackt, oder nicht ?  smiley-confuse
Logged

*greatz*

 CeTax

www dot blinkmann dot de


Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Da wird doch bei "led2[]" die Zeit, die Ausgewählt wird, rein gepackt, oder nicht ?
Das ist schon richtig, aber was ist der Grund für das Array? Warum nicht eine "einfache" Variable also
Code:
<select name="led2">
    <option value="15">15 min</option>
    <option value="30">30 min</option>
    <option value="60">60 min</option>
   </select>
In Deinem PHP-Script hast Du dann ein $_GET['led2'] das den ausgewählten Wert aus dem select enthält. Du bekommst bei einem Formular immer nur den im select-Tag ausgewählten Wert zurück, nicht alle Werte als Array.
Was den Arduino Sketch angeht. Wie immer schrittweise vorgehen. Also erstmal mit einem Pin und der Zeitsteuerung und viel Debugausgaben, bis es funktioniert und dann schrittweise erweitern.
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Zur Motivation  smiley-grin
Ich habe das heute Morgen mal fix umgesetzt. Es war einfach zu warm um noch schlafen zu können  smiley-sweat
Es funktioniert. Sogar recht einfach. Auch die Steuerung der "Timer" über millis() ist eigentlich recht simple.
Hier der Auszug zur Steuerung:
Code:
  //prüfen ob eine Sekunde vergangen ist
  if(millis()-previousMillis >= 1000) {
    //aktuelle Zeit merken
    previousMillis = millis();

    //alle timer auswerten
    for(int t=0; t<NUMTIMER;t++) {

      //nur timer beachten, die auch verwendet werden sollen (positive PIN nummer)
      if(timerpin[t] > 0 ){

        //bei aktuellem timer eine sekunde abziehen, wenn "0", dann abgelaufen
        if( --timerlength[t] == 0) {

          //Ausgang umschalten ( HIGH -> LOW oder LOW -> HIGH)
          digitalWrite(timerpin[t],!digitalRead(timerpin[t])); 

          //timer deaktivieren ( timer mit pin "-1" sind inaktiv)
          timerpin[t] = -1;

          //debug
          Serial.print("Timer ");
          Serial.print(t);
          Serial.println(" abeglaufen.");
        }
      } 
    }
  }
Zur Erklärung. Ich verwende mehrere Timer deren Daten ich in zwei Arrays speichere. timerlength[] enthält die Dauer in Sekunden, die ein timer noch laufen muss. timerpin[] enthält die Pin-Nummer, die für diesen Timer geschaltet werden soll. Der Index der Arrays entspricht jeweils einem einzelnen Timer.
Setzt man z.B. timerlength[2]=30 und timerpin[2]=9, hat man den 3. Timer auf 30 Sekunden Dauer für Pin 9 gesetzt. Gleichzeitig setzt man noch Pin 9 z.B. auf HIGH. Nach Ablauf des Timers wird der Code dann Pin 9 automatisch wieder auf LOW setzen. Setzt man Pin 9 beim Starten des Timers auf LOW, wird es nach Ablauf des Timers auf HIGH gesetzt.
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Mario,
sage mal,wann schläfst du eigentlich ?  smiley-lol
Du hast ja Online Zeiten...  smiley-wink

So, aber erstmal vielen Dank für die Motivation...  smiley-eek-blue
Sieht schwierig aus, aber der Reihe nach, sollte ich nicht erstmal ein PHP/HTML Script erstellen ?
Ich habe mich mal versucht:
Code:
<html>
<head>
</head>
<body>

<h1>Test</h1>
<?php

$arduino_ip 
"192.168.178.216";
$arduino_port "23";

function 
arduino_send($ip,$port,$command) {
    
$res fsockopen($ip,$port);
    if(
$res) {
        
fwrite($res,$command);
        
$ret =fread($res,1);
        echo 
"arduino_send() returned = $ret <br>\n";
        return 
$ret;
    } else {
        echo 
"Fehler, Kommando konnte nicht abgesetzt werden";
    }
}

if(isset(
$_GET['led1'])) {
    
$led1 $_GET['led1'];
    
arduino_send($arduino_ip,$arduino_port,"S".chr(4).chr($led1));
} else {
    
$led1 arduino_send($arduino_ip,$arduino_port,"R".chr(4).chr(0));
}

if(isset(
$_GET['V1'])) {
    
$V1 $_GET['V1'];
    
arduino_send($arduino_ip,$arduino_port,"S".chr(4).chr(1).chr($V1));
} else {
    
$V1 arduino_send($arduino_ip,$arduino_port,"R".chr(4).chr(0));
}
?>

<form action="">
  <p>
LED 1 :
<input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >aus -
<input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >an
<br>
  </p>
  <input type="submit" name="submit" value="Abschicken">
</form><br><br>
<form action="">
  <p>
   <select name="V1">
    <option value="15">15 min</option>
    <option value="30">30 min</option>
    <option value="60">60 min</option>
   </select>
  </p>
   <input type="submit" name="submit" value="Starten">
   <input type="reset" name="stop" value="Stop">
</form>

</body>
</html>
Aber wahrscheinlich wieder falsch...  smiley-red
Ich trau mich schon garnicht mehr...  smiley-confuse Das ist absolutes Neuland für mich...
Bleibt aber noch die Frage, wie kann ich den Stop Button aktivieren? Wenn ich da rauf klicke, passiert nix... smiley-sad
Logged

*greatz*

 CeTax

www dot blinkmann dot de


Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
sage mal,wann schläfst du eigentlich ?
Regelmäßig, bin halt nur Frühaufsteher.
Der HTML-Code sieht schon mal ganz gut aus. Wenn Du zwei Formulare machst, kannst Du aber immer nur eins abschicken, das muss Dir klar sein. Wenn das gewollt ist, dann ist das kein Problem. Du kannst dann halt entweder die Pins direkt schalten oder alt mit Zeitverzögerung.
Das <input type=reset ...> verwendet man in Formularen, um diese wieder in den Zustand zu bringen, die sie beim Laden der Seite hatten. Also z.B. Textfelder ohne Inhalt oder wieder mit dem "default"-Inhalt, radio-buttons oder select-Tags die wieder die originäre Auswahl zeigen. Das gilt aber nur für das Formular zu dem das input-Tag gehört. Außerdem wird beim anklicken dieses Buttons das Formular nicht abgeschickt, das Zurückstellen passiert nur im Browser, daher passiert da auch nix weiter.
Auch der PHP-Code sieht gut aus, die Auswertung für "V1" ist korrekt und sollte funktionieren, wenn der Arduino-Code darauf angepasst wird.
Einen Verbesserungsvorschlag hätte ich aber trotzdem. Da die Funktionalität "Pin schalten" und "Pin auslesen" bereits vorhanden ist und funktioniert (Kommando "S" und "R") würde ich einfach neue Kommandos definieren, die zusätzlich die Funktion "T" -> Timer für Pin x auf n Minuten setzen und z.B. "U" -> liefere die Zeit die der Timer für Pin x noch läuft abbildet. Das sind dann einfach nur weitere Blöcke im switch-case Konstrukt im Arduino-Code. Den größten Teil kannst Du sogar von "R" und "S" klauen und nur um die Timer-Geschichte erweitern.

Wie Du siehst, warst Du mit Deinem "Aber wahrscheinlich wieder falsch... viel zu pessimistisch.

Ein kleiner Tip noch für den Arduino-Code. Den Rückgabewert kann man auch mittels "client.print()" statt client.write() zurückliefern. Dann kommt die zurückgelieferte Zahl (z.b. 125) als String "125" (also 3 Zeichen und nicht ein Byte) beim PHP an und kann direkt in einer Variablen weiter verarbeitet werden. Man muss dann nicht die Bytes einzeln lesen und den Wert zusammenrechnen.
Viel Erfolg im "Kämmerlein"  smiley-grin
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Quote
Einen Verbesserungsvorschlag hätte ich aber trotzdem. Da die Funktionalität "Pin schalten" und "Pin auslesen" bereits vorhanden ist und funktioniert (Kommando "S" und "R") würde ich einfach neue Kommandos definieren, die zusätzlich die Funktion "T" -> Timer für Pin x auf n Minuten setzen und z.B. "U" -> liefere die Zeit die der Timer für Pin x noch läuft abbildet. Das sind dann einfach nur weitere Blöcke im switch-case Konstrukt im Arduino-Code. Den größten Teil kannst Du sogar von "R" und "S" klauen und nur um die Timer-Geschichte erweitern.

meinst du so (bekomme Fehlermeldungen beim kompilieren,verstehe nicht was ich ändern muss, sorry  smiley-red ):
Code:
#include <SPI.h>
#include <Ethernet.h>

// MAC und IP Konfiguration
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xEE, 0xF3 };
IPAddress ip(192,168,178,216);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255, 255, 255, 0);

// warten auf port 23
EthernetServer server(23);

long previousMillis = 0;        // speichert wie viele Sekunden seit derletzten Änderung vergangen sind


void setup() {
  //Ethernet initialisieren
  Ethernet.begin(mac, ip, gateway, subnet);
  // Server starten
  server.begin();
  // serielle konsole öffnen (debug)
  Serial.begin(9600);
}

void loop() {
  
  // auf eine eingehende Verbindung warten
  EthernetClient client = server.available();
  //wenn verbindung, dann 3 bytes lesen;
  if (client) {

    char command =client.read();
    byte pinnumber =client.read();
    byte pinvalue =client.read();
    byte pintime =client.read();  //öffnungszeit Ventil zb. 15min
    long timerlength = client.read();
    byte returnvalue = 0;
    byte timerpin[] = pinnumber;  //<-- hier hagt es :-( Keine Ahnung was da hin mus...
    
    //prüfen ob eine Sekunde vergangen ist
  if(millis()-previousMillis >= 1000) {
    //aktuelle Zeit merken
    previousMillis = millis();

    //alle timer auswerten
    for(int t=0; t<NUMTIMER;t++) {

      //nur timer beachten, die auch verwendet werden sollen (positive PIN nummer)
      if(timerpin[t] > 0 ){

        //bei aktuellem timer eine sekunde abziehen, wenn "0", dann abgelaufen
        if( --timerlength[t] == 0) {

          //Ausgang umschalten ( HIGH -> LOW oder LOW -> HIGH)
          digitalWrite(timerpin[t],!digitalRead(timerpin[t]));  

          //timer deaktivieren ( timer mit pin "-1" sind inaktiv)
          timerpin[t] = -1;

          //debug
          Serial.print("Timer ");
          Serial.print(t);
          Serial.println(" abeglaufen.");
        }
      }  
    }
  }

    //Kommando auswerten
    switch(command) {

    case 'S':
      Serial.print("S Kommando empfangen, setze Pin ");
      Serial.print(pinnumber);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(pinnumber,pinvalue);
     //gesetzten wert auch zurückliefern
      returnvalue=pinvalue;
      break;

    case 'R':
      returnvalue = digitalRead(pinnumber);
      Serial.print("R Kommando empfangen, lese Pin ");
      Serial.print(pinnumber);
      Serial.print(". Wert = ");
      Serial.println(returnvalue);
      break;

   case 'T':
     Serial.print("T Kommando empfangen, setze Pin ");
      Serial.print(pinnumber);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(pinnumber,pinvalue);
      Serial.print(" für ");
      Serial.print(pintime);
      Serial.print(" min");
     //gesetzten wert auch zurückliefern
      returnvalue=pinvalue;
      break;
    
    default:
      Serial.println("Fehler, unbekanntes Kommando");    
      break;

    }  
    
    // rückantwort senden (1 byte) die "+48" sorgen dafür das der Wert 0 oder 1 als Zeichen "0" oder "1" übertragen werden.
    //das vereinfacht die verarbeitung in php.
    client.write(returnvalue+48);
    
    //übertragung erzwingen
    client.flush();
    
    //10ms delay damit daten sicher gesendet werden.
    delay(10);
    
    //wichtg! client verbindung beenden
    client.stop();
  }
}
  

Hier die Fehlermeldungen:
Code:
Mario_1.cpp: In function 'void loop()':
Mario_1:39: error: initializer fails to determine size of 'timerpin'
PHP_Ausgang_schalten_Mario_1:53: error: invalid types 'long int[int]' for array subscript
Ich verstehe die Zuordnungen nicht ... arg.. ;-(
NUMTIMER ?
timerpin ? <-- soll der aktive Pin sein?
timerlength ? <-- länge wie lange das Ventil geöffnet sein soll ?
« Last Edit: May 03, 2012, 03:59:23 pm by Cetax » Logged

*greatz*

 CeTax

www dot blinkmann dot de


Offline Offline
Edison Member
*
Karma: 21
Posts: 1397
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Auch auf die Gefahr hin, das ich mich wiederhole :-)
Schrittweise vorgehen. Wenn es nicht funktioniert, dann gehe einen Schritt zurück und prüfe ab wann es nicht mehr so läuft wie es sollte.
Was mir auf alle Fälle schon mal auffällt ist:
Code:
   char command =client.read();
    byte pinnumber =client.read();
    byte pinvalue =client.read();
    byte pintime =client.read();  //öffnungszeit Ventil zb. 15min
    long timerlength = client.read();
Hier liest Du viel mehr Daten als Du mit dem PHP-Script abschickst. Wenn pintime schon der Wert für den Timer ist, wofür ist dann timerlength gut?
Abgesehen davon, das Du mit client.read() nur ein Byte liest und keinen long-Wert.
timerpin[] und timerlength[] sind globale arrays, die außerhalb von loop() definiert werden müssen, damit sie ihre Werte zwischen den einzelnen loop() Duchläufen behalten. Eine Zuweisung zu diesen Arrays muss also immer mit einem Index erfolgen.
NUMTIMER ist ein "#define" mit dem man festlegt, wieviele timer es geben soll.

Ich würde sagen, wir gehen die Umsetzung des Arduino-Codes diesmal etwas anders an. Versuch mal stuchpunktartig zu beschreiben, was der Code machen soll, wenn das Kommando "T" an den Arduino geschickt wird.
Sowas wie
  • "T" aus verbindung gelesen
  • 1. Byte "Pinnumber" gelesen und in pinnumber gespeichert
  • 2. Byte "Pinvalue gelesen
  • ...

Damit kannst Du Dir schrittweise (da ist es wieder :-)) klar machen was passieren soll und es dann entsprechend programmieren.
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Moin,
ich verstehe diese Code Zeile nicht, bzw. was mir die Fehlermeldung sagen will.. grrr
Die Codezeile wird Makiert:
Quote
//alle timer auswerten
    for(int t=0; t<NUMTIMER;t++) {
Also, t=0; heißt doch es soll mit 0 beginnen, oder ?
Aber wo steht das t=0 ist ?  smiley-confuse
Und "t < NUMTIMER;" bis dahin soll gezählt werden
( #define NUMTIMER = 3; // wieviele timer es gibt (15,30,60 min) <-- Oder falsch verstanden ?

Fehlermeldung:
Code:
Mario_1.cpp: In function 'void loop()':
Mario_1:47: error: expected primary-expression before '[' token
Mario_1:47: error: expected primary-expression before ']' token
Mario_1:47: error: expected primary-expression before ';' token
Mario_1:47: error: expected `)' before ';' token
Mario_1:47: error: name lookup of 't' changed for new ISO 'for' scoping
Mario_1:47: error: using obsolete binding at 't'
Mario_1:47: error: expected `;' before ')' token
Mario_1:125: error: expected `}' at end of input
Mario_1:125: error: expected `}' at end of input
Mario_1:125: error: expected `}' at end of input

Vor dem "setup()" habe ich folgendes festgelegt:
Code:
unsigned long previousMillis = 0;       // speichert wie viele Sekunden seit derletzten aenderung vergangen sind
#define NUMTIMER[] = 3;          // wieviele timer es gibt (15,30,60 min)
int timerpin;
int timerlength;

Und im "loop()" steht das (hoffe ich habe dich da richtig verstanden (4. byte):
Code:
    char command =client.read();
    byte pinnumber =client.read();
    byte pinvalue =client.read();
    byte timerlength = client.read(); // zeit für ventil öffnung
    byte returnvalue = 0;


Hier nochmal der ganze Code:
Code:
#include <SPI.h>
#include <Ethernet.h>

// MAC und IP Konfiguration
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xEE, 0xF3 };
IPAddress ip(192,168,178,216);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255, 255, 255, 0);

// warten auf port 23
EthernetServer server(23);

unsigned long previousMillis = 0;       // speichert wie viele Sekunden seit derletzten aenderung vergangen sind
#define NUMTIMER = 3;          // wieviele timer es gibt (15,30,60 min)
int timerpin;
int timerlength;


void setup() {
  //Ethernet initialisieren
  Ethernet.begin(mac, ip, gateway, subnet);
  // Server starten
  server.begin();
  // serielle konsole öffnen (debug)
  Serial.begin(9600);
}

void loop() {
 
  // auf eine eingehende Verbindung warten
  EthernetClient client = server.available();
  //wenn verbindung, dann 3 bytes lesen;
  if (client) {

    char command =client.read();
    byte pinnumber =client.read();
    byte pinvalue =client.read();
    byte timerlength = client.read(); // zeit für ventil öffnung
    byte returnvalue = 0;
   
   
    //prüfen ob eine Sekunde vergangen ist
  if(millis()-previousMillis >= 1000) {
    //aktuelle Zeit merken
    previousMillis = millis();

    //alle timer auswerten
    for(int t=0; t<NUMTIMER;t++) {

      //nur timer beachten, die auch verwendet werden sollen (positive PIN nummer)
      if(timerpin[t] > 0 ){

        //bei aktuellem timer eine sekunde abziehen, wenn "0", dann abgelaufen
        if( --timerlength[t] == 0) {

          //Ausgang umschalten ( HIGH -> LOW oder LOW -> HIGH)
          digitalWrite(timerpin[t],!digitalRead(timerpin[t])); 

          //timer deaktivieren ( timer mit pin "-1" sind inaktiv)
          timerpin[t] = -1;

          //debug
          Serial.print("Timer ");
          Serial.print(t);
          Serial.println(" abeglaufen.");
        }
      } 
    }
  }

    //Kommando auswerten
    switch(command) {

    case 'S':
      Serial.print("S Kommando empfangen, setze Pin ");
      Serial.print(pinnumber);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(pinnumber,pinvalue);
     //gesetzten wert auch zurückliefern
      returnvalue=pinvalue;
      break;

    case 'R':
      returnvalue = digitalRead(pinnumber);
      Serial.print("R Kommando empfangen, lese Pin ");
      Serial.print(pinnumber);
      Serial.print(". Wert = ");
      Serial.println(returnvalue);
      break;

   case 'T':
     Serial.print("T Kommando empfangen, setze Pin ");
      Serial.print(pinnumber);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(pinnumber,pinvalue);
      Serial.print(" für ");
      Serial.print(timerlength);
      Serial.print(" min");
     //gesetzten wert auch zurückliefern
      returnvalue=pinvalue;
      break;
     
    default:
      Serial.println("Fehler, unbekanntes Kommando");   
      break;

    } 
   
    // rückantwort senden (1 byte) die "+48" sorgen dafür das der Wert 0 oder 1 als Zeichen "0" oder "1" übertragen werden.
    //das vereinfacht die verarbeitung in php.
    client.write(returnvalue+48);
   
    //übertragung erzwingen
    client.flush();
   
    //10ms delay damit daten sicher gesendet werden.
    delay(10);
   
    //wichtg! client verbindung beenden
    client.stop();
  }
}

Irgendwie habe ich wohl was falsch deklariert oderso, kann aber nichts mit den Fehlermeldungen Anfangen  smiley-red
« Last Edit: May 04, 2012, 04:33:21 am by Cetax » Logged

*greatz*

 CeTax

www dot blinkmann dot de


Offline Offline
God Member
*****
Karma: 9
Posts: 721
42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Die Variable "t" deklarierst du ja direkt in der for-Schleife.

Das einzige, was ich jetzt gefunden hab ist folgende zeile, die ich mir nicht erklären kann:
         
Code:
digitalWrite(timerpin[t],!digitalRead(timerpin[t])); 
digitalRead liefert HIGH oder LOW (1 oder 0 intern) - sagst du damit, dass es das Gegenteil von dem gelieferten Wert sein soll? Weiß nicht, ob das so funktioniert...
« Last Edit: May 04, 2012, 04:42:58 am by Marcus W » Logged


Germany
Offline Offline
Sr. Member
****
Karma: 1
Posts: 275
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
laut Mario´s Sketch-Auszug, soll das wohl funktionieren.
Er hatte das ganze wohl schon getestet.
Quote
Zur Motivation  smiley-grin
Ich habe das heute Morgen mal fix umgesetzt. Es war einfach zu warm um noch schlafen zu können  smiley-sweat
Es funktioniert. Sogar recht einfach. Auch die Steuerung der "Timer" über millis() ist eigentlich recht simple.
Code:
//prüfen ob eine Sekunde vergangen ist
  if(millis()-previousMillis >= 1000) {
    //aktuelle Zeit merken
    previousMillis = millis();

    //alle timer auswerten
    for(int t=0; t<NUMTIMER;t++) {

      //nur timer beachten, die auch verwendet werden sollen (positive PIN nummer)
      if(timerpin[t] > 0 ){

        //bei aktuellem timer eine sekunde abziehen, wenn "0", dann abgelaufen
        if( --timerlength[t] == 0) {

          //Ausgang umschalten ( HIGH -> LOW oder LOW -> HIGH)
          digitalWrite(timerpin[t],!digitalRead(timerpin[t])); 

          //timer deaktivieren ( timer mit pin "-1" sind inaktiv)
          timerpin[t] = -1;

          //debug
          Serial.print("Timer ");
          Serial.print(t);
          Serial.println(" abeglaufen.");
        }
      } 
    }
  }

Damit versuche ich mich,also daraus einen ganzen SKETCH zu machen... Klapp nur irgendwie nicht, weil ich einiges (noch) nicht verstehe.  smiley-red
Logged

*greatz*

 CeTax

www dot blinkmann dot de


Pages: 1 [2] 3 4   Go Up
Jump to: