Go Down

Topic: Ausgang per Web schalten mit PHP (Read 14178 times) previous topic - next topic

mkl0815

Quote
( #define NUMTIMER = 3; // wieviele timer es gibt (15,30,60 min) <-- Oder falsch verstanden ?

Leider ja, denn die 15,30 und 60 Minuten sind ja nur eine Zeit, von der Du eine auswählst, das hat ja noch nichts mit einem Timer zu tun.
Verschiedene Timer brauchst Du, wenn Du mehrere Ventile steuern willst.
Z.B. timerpin[0]=9, timerlength[0]=900 würde den ersten Timer für Pin 9 auf 900 Sekunden (15min) setzen.
timerpin[1]=10, timerlength[1]=3600 wäre dann der 2. Timer für Pin 10 und 60 Minuten.

Code: [Select]
digitalWrite(timerpin[t],!digitalRead(timerpin[t]));   
sieht seltsam aus, funktioniert aber.

Code: [Select]
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;

Die previousMillis sind richtig, aber das define nicht. Wie bereits geschrieben, müssen timerpin und timerlength beides Arrays sehen.
Also
Code: [Select]
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[NUMTIMER];
int timerlength[NUMTIMER];
...
void setup() {
...
}

Hinter das "#define" kommt kein Semikolon und die Zuweisung erfolgt auch nicht mit einem "=". "define" ist eine Präprozessoranweisung für den Compiler. Der geht einfach nur stumpf durch den gesamten Code und ersetzt überall das "NUMTIMER" durch die 3, das hat noch nichst mit dem Programm zu tun, das ist reine Textersetzung. Das Trick dabei ist, das man später die Anzahl der Arrayeinträge an einer einzigen Stelle ändern kann, ohne die 3 überall im Code zu ersetzen.

Die Auswertung für die vergangene Zeit darf auch nicht innerhalb des "if(client)" Blocks stehen, denn die Zeit läuft ja auch weiter wenn kein Client connected ist.
Am besten setzt Du den Zeit-Auswertungsblock gleich an den Anfang der loop().

Was bei der Auswertung des Kommandos "T" noch fehlt, ist das Setzen des übergebenen Timer-Wertes. Der muss ja irgendwo gespeichert werden, ebenso wie die Pin Nummer, die dem Timer zugeordnet ist.

Die Lösung selbst ist eigentlich nicht schwer, Du versuchst aber alles auf einmal zu machen und dafür fehlt die zur Zeit noch das Wissen und die Übersicht. Versuch daher erstmal den Ablauf wie Du ihn verstehst zu beschreiben. Sobald das stimmt und Du verstehst was, wann wie passieren soll, dann fängst Du an das in ein C Programm zu giessen.

Cetax

#31
May 04, 2012, 01:11 pm Last Edit: May 04, 2012, 02:11 pm by Cetax Reason: 1
Hallo Mario,
Danke für die super Erklärung !!
Quote
Hinter das "#define" kommt kein Semikolon und die Zuweisung erfolgt auch nicht mit einem "=". "define" ist eine Präprozessoranweisung für den Compiler. Der geht einfach nur stumpf durch den gesamten Code und ersetzt überall das "NUMTIMER" durch die 3, das hat noch nichst mit dem Programm zu tun, das ist reine Textersetzung. Das Trick dabei ist, das man später die Anzahl der Arrayeinträge an einer einzigen Stelle ändern kann, ohne die 3 überall im Code zu ersetzen.

So versteht das auch einer wie ich   XD

Dann mach ich mal...
Bis später... ;)
*greatz*

 CeTax

www dot blinkmann dot de

Cetax

#32
May 05, 2012, 03:13 pm Last Edit: May 05, 2012, 03:29 pm by Cetax Reason: 1
Hi,
ok, ich raff es nicht.  :smiley-red:
Mein Sketch sieht jetzt so aus, das er zwar kompiliert aber nicht mehr tut.
Rufe ich die Website auf, kommt die Fehlermeldung "Kommando konnte nicht abgesetzt werden"
Hier mein Sketch:
Code: [Select]
#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[NUMTIMER];
int timerlength[NUMTIMER];

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

void loop() {
 
  //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.");
        }
      } 
    }
  }
 
  // auf eine eingehende Verbindung warten
  EthernetClient client = server.available();
  //wenn verbindung, dann 4 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;
    byte timerpin = pinnumber;
   

    //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(timerpin);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(timerpin,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 den jetzt total vermurgst... Ich bin der Meinung ich habe alles übergeben, aber anscheinend fehlt irgendwas oder ist falsch gesetzt.

Hier der PHP Teil:
Code: [Select]

<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,"T".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="Senden">
</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="Senden">
</form>

</body
</HTML>

*greatz*

 CeTax

www dot blinkmann dot de

mkl0815

1) Du musst, wenn Du Dein Protokoll änderst, natürlich auch den PHP-Code anpassen. Dein Arduino-Sketch erwartet das bei JEDEM Kommando nun 4 Bytes gesendet werden. Da Du ber Beim Kommando "R" und "S" nur 3 Bytes sendest, wartet Dein Sketch entsprechend bis zum timeout und macht nicht weiter. Du kannst das auf zwei Arten beheben. Du kannst immer 4 Bytes schicken, das ist aber unpraktisch, da es ja irgendwann mit zusätzlichen Kommandos auch 5 oder 6 oder mehr werden können. Dann müßtest Du immer alles neu Anpassen, was zum Einen Fehleranfällig und zum Anderen Aufwändig ist.
Du kannst aber auch bei jedem Aufruf nur die Bytes schicken, die Du benötigst. Dein Sketch liest dann am Anfang immer nur die minimale Anzahl von Bytes von einem client und erst in switch - case Block liest Du die für das entsprechende Kommando notwendigen zusätzlichen Bytes ein. Lediglich die Variablen dafür würde ich bereits oben deklarieren, das ist übersichtlicher.

2) Wieso glaubst Du, das Du in Deinem Sketch alles korrekt übergeben hast? timerpin und timerlength sind Arrays, Du verwendest aber nirgendwo in der loop() ein Array. Im Gegenteil, Du deklarierst die Variablen timerlength und timerpin nocheinmal innerhalb von loop() als lokale Variablen vom Typ byte. Diese "verdecken" dann aber die globalen Arrays timerlength und timerpin. Die Schleife, die im Sekundentakt die einzelnen Timer abklappert erwartet aber, das die Variablen timerlength und timerpin auf ein Array zeigen und verwendet an dieser Stelle den Speicher auch so, womit Du plötzlich statt auf jeweils ein Byte, wie es deklariert ist auf 3x2x4 Bytes zugreifst und diese veränderst. Damit bringst Du Dein Programm total aus dem Tritt, da Du mit Sicherheit Speicherzellen veränderst, die vom Programm anderweitig verwendet werden.

Um das erstmal zum Laufen zu bekommen, ändere folgendes in Deinem Sketch:

1) Das "byte" vor timerlength und timerpin in dem Block wo die Daten gelesen werden muss weg.
2) Innerhalb von loop() änderst Du alle Vorkommen von timerlength in timerlength[0]
3) Innerhalb von loop() änderst Du alle Vorkommen von timerpin in timerpin[0]

Damit überschreibt dann Dein Programm innerhalb von loop() nicht mehr die globalen Variablen für die Timer und verwendet erstmal einen timer für das Zählen der Zeit.
Im übrigen zählt Dein Sketch die timer in Sekunden nicht in Minuten. Damit es Minuten werden solltest Du den übergebenen Wert noch mit 60 multiplizieren.

Leider ist Deine Lösung aber generell für eine Verwendung von mehreren Timern ungeeignet, da Du in Deinem Aufruf nicht übergibst welcher Timer verwendet werden soll. Sobald Du mehr als ein Ventil schalten willst, bekommst Du Probleme.

Cetax

#34
May 06, 2012, 01:27 am Last Edit: May 06, 2012, 08:43 am by Cetax Reason: 1
Hallo Mario,
sorry wenn ich verärgert habe, aber ich habe es nicht verstanden.
Ich habe es jetzt so verändert wie du es geschrieben hast und es funktioniert.
Quote

Um das erstmal zum Laufen zu bekommen, ändere folgendes in Deinem Sketch:

1) Das "byte" vor timerlength und timerpin in dem Block wo die Daten gelesen werden muss weg.
2) Innerhalb von loop() änderst Du alle Vorkommen von timerlength in timerlength[0]
3) Innerhalb von loop() änderst Du alle Vorkommen von timerpin in timerpin[0]


Habe ich getan, es läuft. <Danke!>

Quote
Im übrigen zählt Dein Sketch die timer in Sekunden nicht in Minuten. Damit es Minuten werden solltest Du den übergebenen Wert noch mit 60 multiplizieren.


Auch hier muss ich wieder passen, ich versuche seit 3 std heraus zu finden wo ich das eintragen muss, aber ohne erfolg. Egal wo ich es eintrage, nix, die Zeit wird nicht multipliziert.  :(

Quote
Leider ist Deine Lösung aber generell für eine Verwendung von mehreren Timern ungeeignet, da Du in Deinem Aufruf nicht übergibst welcher Timer verwendet werden soll. Sobald Du mehr als ein Ventil schalten willst, bekommst Du Probleme.

Ok, aber es soll auch immer nur ein Ventik zur Zeit geöffnet sein,niemals zwei.
Auch hier stehe ich auf dem Schlauch, meinst du mit mehreren TIMERN z.b. V1, V2, V3 für Ventil1, Ventil2 usw. ? So wie im PHP angegeben?
Wenn ich es so versuche, gibt er Fehlermeldungen raus:
Code: [Select]
int NUMTIMER[] = {0,1};
0 für V1 und 1 für V2 , Dachte ich :(


Ich habe jetzt mal die PHP Seite erweitert, es funktioniert, aber wie du schon sagst, im SerialMonitor, wird immer nur Timer 0 angezeigt.
Hier der Sketch:
Code: [Select]
#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;      

#define NUMTIMER 2

int timerpin[NUMTIMER];
int timerlength[NUMTIMER];

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

void loop() {
 
   //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("T Kommando empfangen, Timer ");
         Serial.print(t);
         Serial.println(" abeglaufen.");
       }
     }  
   }
 }

 // auf eine eingehende Verbindung warten
 EthernetClient client = server.available();
 
 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;

  case 'T':
    timerlength[0] = client.read(); // zeit für ventil öffnung
    timerpin[0] = pinnumber;
    Serial.print("T Kommando empfangen, setze Pin ");    
     Serial.print(timerpin[0]);
     Serial.print(" auf ");
     Serial.println(pinvalue);
     pinMode(timerpin[0],OUTPUT);
     digitalWrite(timerpin[0],pinvalue);
     Serial.print("T Kommando empfangen, setze Time auf ");
     Serial.print(timerlength[0]);
     Serial.print(" sec");
     Serial.println(" ");
    //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();
 }
}


und hier der PHP-Code:
Code: [Select]
<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,"T".chr(4).chr(1).chr($V1));
} else {
    
$V1 arduino_send($arduino_ip,$arduino_port,"R".chr(4).chr(0));
}

if(isset(
$_GET['V2'])) {
    
$V2 $_GET['V2'];
    
arduino_send($arduino_ip,$arduino_port,"T".chr(5).chr(1).chr($V2));
} else {
    
$V2 arduino_send($arduino_ip,$arduino_port,"R".chr(5).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="Senden">
</form><br><br>
<form action="">
 <p>Timer 1<br>
  <select name="V1">
   <option value="15">15 min</option>
   <option value="30">30 min</option>
   <option value="45">45 min</option>
   <option value="60">60 min</option>
  </select>
 </p>
  <input type="submit" name="submit" value="Senden">
</form><br>
<form action="">
<p>Timer 2<br>
 <select name="V2">
 <option value="15">15 min</option>
 <option value="30">30 min</option>
 <option value="45">45 min</option>
 <option value="60">60 min</option>
 </select>
</p>
 <input type="submit" name="submit" value="senden">
</form>

</body
</HTML>
*greatz*

 CeTax

www dot blinkmann dot de

mkl0815

Guten Morgen,
Quote
Auch hier muss ich wieder passen, ich versuche seit 3 std heraus zu finden wo ich das eintragen muss, aber ohne erfolg. Egal wo ich es eintrage, nix, die Zeit wird nicht multipliziert.

Wo hast Du es denn eingetragen? Und was hat nicht funktioniert? Entschuldige wenn ich so direkt frage, aber hast Du einfach nur probiert, oder überlegt wo es passen könnte? Das ist nicht böse gemeint, aber ich glaube Du verfolgst bei der Programmierung immer noch einen falschen Ansatz. Erstmal irgendwelchen Code schreiben und dann schauen was der macht ist keine gute Taktik. Es hat einen Grund warum ich Dich schon zwei Mal versucht habe zu überzeugen erstmal die Schritte die in Deinem Programm passieren sollen in Worten als kleine Liste aufzuschreiben. Wenn Du da schon ein Problem mit dem Verständnis zum Ablauf hast, wird das beim Programmieren nicht besser, weil Du Dich dort noch zusätzlich auf die Syntax von C und die semantisch korrekte Umsetzung Deines Konzepts konzentrieren musst.
Am Beispiel der Umrechnung der Dauer in Minuten:

  • PHP sendet die Dauer als 4. Parameter in Minuten

  • Sketch liest im switch-case Block den zusätzlichen 4. Parameter, wenn Kommando "T" erkannt wurde in die Variable timerlength[0]

  • timerlength[0] muss aber in Sekunden angegeben werden, daher muss der gerade übermittelte Werte umgerechnet werden

  • Um auf Sekunden zu kommen, muss der Wert mit 60 multipliziert werden -> timerlength[0] = timerlength[0] *60



Quote
Ok, aber es soll auch immer nur ein Ventik zur Zeit geöffnet sein,niemals zwei.
Auch hier stehe ich auf dem Schlauch, meinst du mit mehreren TIMERN z.b. V1, V2, V3 für Ventil1, Ventil2 usw. ? So wie im PHP angegeben?
Wenn ich es so versuche, gibt er Fehlermeldungen raus:
Code:
int NUMTIMER[] = {0,1};
0 für V1 und 1 für V2 , Dachte ich smiley-sad

Wann welches Ventil geöffnet ist, ist für die Programmierung an der Stelle erstmal völlig uninteressant. Warum?
1) Weil man immer möglichst allgemeine Lösungen baut, in diesem Fall also mit der Möglichkeit "Ventile" (also Pins) unabhängig voneinander mit unterschiedlichen Timern zu schalten. Wie das dann von einer konkreten Anwendung genutzt wird, ist eine ganz andere Sache.
2) Ein PHP- und HTML-Script ist schnell geändert, dort steckt ja die eigentliche Anwendungslogik drin, den Arduino später neu zu flashen ist deutlich mehr Aufwand. Den Arduino interessiert ja im Prinzip auch nicht um "was" es eigentlich geht. Der bekommt nur "Kommandos" wie "schalte Pin 3 ein" , "lese Pin 4 aus", oder "Schalte Pin 9 für 15 Minuten auf HIGH, danach wieder auf LOW" und das sollte alles unabhängig voneinander funktionieren.

Du hast geschrieben, das Du das mit dem "#define NUMTIMER 3" verstanden hast, schreibst aber trotzdem wieder sowas : int NUMTIMER[] = {0,1};? Das ist das, was ich mit dem rumprobieren meine. Das führt leider in den seltensten Fällen zum Erfolg. Und selbst wenn, dann nur aus Glück und man versteht meistens am Ende trotzdem nicht warum es plötzlich funktioniert. Ergo -> kein guter Ansatz.

Du hast in Deinem Code ein
#define NUMTIMER 2 stehen. Das bedeutet, das die beiden Arrays timerlength und timerpin je 2 Einträge haben können. Du hast also schon 2 Timer zur Verfügung, die Du für V1 und V2 nutzen kannst (timerlength[0] und timerlength[1]. Was fehlt ist nur die Zuordnung. Dein Sketch muss ja irgendwo die Information herbekommen, welcher Timer für welches Pin verwendet werden soll.
Hier hast Du auch wieder zwei Möglichkeiten.
1) Die einfache Variante wäre einfach zu sagen wenn Pin 4 übergeben wird, nutze Timer 0 und bei Pin 5 nutze Timer 1. Das ist aber schlechter Stil, denn Du verlagerst damit Teile Deiner Anwendungslogik in den allgemeinen Arduino-Sketch. Die Gefahr besteht, das Du irgendwann im PHP-Code plötzlich Pin 6 übergibst, weil sich Deine Schaltung geändert hat und dann der Code nicht mehr greift.
2) Die allgemeinere Variante. Du übergibst mit dem Kommando "T" einfach noch ein zusätzliches Byte, das bestimmt, welcher Timer verwendet werden soll. Dieses wird dann, genauso wie timerlength per client.read() gelesen. Allerdings musst Du aufpassen, denn Du solltest ersten die Timer-Nummer übergeben, ehe Du mit timerlength[timernummer] = client.read() die Länge liest. (Du kannst Dir natürlich auch eine einfache "byte" Variable als "Zwischenspeicher" deklarieren.

Achso, ich bin auch nicht "verärgert". Leider versuchst Du immer noch den zweiten Schritt vor dem Ersten zu machen und stolperst dabei regelmäßig. Das ist, sagen wir mal eine kleine Gedulds-Herausforderung für mich  :D, gehört aber einfach dazu, wenn man jemanden etwas wirklich verständlich machen will. "Echtes" Lernen bedeutet nun mal, das man Prinzipien versteht und nicht einfach nur "auswendig" lernt. Damit habe ich mir als Tutor immer zusätzliche Arbeit gemacht und auch so machens "Opfer" zur Verzweiflung getrieben. Du bist also in guter Gesellschaft  ]:D

mkl0815

Code: [Select]
int ledPin[] = {7,8,9}; // LED-Array mit Pin-werten

Ist korrekt, aich Dein
Code: [Select]
int NUMTIMER[] = {0,1};
war, zumindest für diese Zeile, erstmal snytaktischkorrekt.
Allerdings wird im Sketch selbst das NUMTIMER nicht als Variable oder Array verwendet, sonder nur als Platzhalter für die Zahl 3 oder 5 oder 2 oder welche Anzahl von Timern Du haben willst. NUMTIMER ist also NICHT der Timer selbst sonder nur der Wert für die Anzahl der Timer die es geben soll.
timerlength[] und timerpin[] sind die beiden Arrays, die den eigentlichen Timer bilden, denn diese speichern ja die Länge der Laufzeit und den Pin für einen spezifischen timer, sprich Index der Arrays.

Schön, das Dein Projekt jetzt funktioniert. Du hast Dir natürlich für den Anfang auch ein recht komplexes Projekt ausgesucht. Aus meiner Sicht etwas zu komplex für eine sinnvolle Lernkurve, denn zu viele Baustellen und Prinzipien gleichzeitig mit denen man sich auseinandersetzen muss, überfordern einen doch leicht.
Nur nicht aufgeben und dran bleiben, irgendwann lichtet sich der Nebel :-)

Cetax

Hallo allerseits,
also Projekt läuft.
Nochmal vielen Dank an "mkl0815" für die tolle Hilfe und Unterstützung :D

Arduino Ausgänge werden mittels PHP für eine Vorgegeben Zeit geöffnet und dann automatisch geschlossen.
Den Code liefer ich später nach, muss den noch kommentieren.
Sollte jemand den schon vorher haben wollen, kurze PN.
*greatz*

 CeTax

www dot blinkmann dot de

mkl0815

Guten Morgen,

kann es sein, das aus diesem Thread Beiträge verschwunden sind? Speziell zwischen meinem letzten Post und dem vorletzten fehlt irgendwie der "es klappt jetzt" Post von Cetax. Daher mutet der Thread jetzt etwas seltsam an :-)

Cetax

Moin,
ja also wie soll ich sagen... :smiley-red:
Ups.. Ich habe den falschen Button angeklickt und da war es wech..
Sorry !
*greatz*

 CeTax

www dot blinkmann dot de

Cetax

Hallo allerseits,
ich wende mich nochmal mit einem Problem an Euch.
Ich versuche gerade die Rest-Zeit eines Timers auszulesen und auf einer Website mittels PHP auszugeben.
Was auch teils schon geht. Im SerialMonitor wird dann z.b. 900sec angezeigt, aber auf der Website nur die erste Zahl!
Wie kann ich die ganze Zahl ausgeben lassen ?
Hier mal der Sketch (Case 'U' ist der Teil) :
Code: [Select]

#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;       

#define NUMTIMER 6                    // 6 Timer
int TI;
int timerpin[NUMTIMER];
int timerlength[NUMTIMER];

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

void loop() {
 
    //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("T Kommando empfangen, Timer ");
          Serial.print(t);
          Serial.println(" abeglaufen.");
        }
      } 
    }
  }

  // auf eine eingehende Verbindung warten
  EthernetClient client = server.available();
 
  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;
     
   case 'U':
      Serial.print("U Kommando empfangen, lese Timer ");
      Serial.print(TI);
      Serial.print(" Wert = ");
      Serial.println(timerlength[TI]);
      client.print(timerlength[TI]);
      //client.print(returnvalue);
      break;

   case 'T':
     TI = client.read();
     timerlength[TI] = client.read(); // zeit für ventil öffnung
     timerpin[TI] = pinnumber;
     timerlength[TI] = timerlength[TI] *60; // die empfangenen sec*60=min
     Serial.print("T Kommando empfangen, ");
     Serial.print("Timer ");
     Serial.print(TI);
     Serial.println(" gestartet");
      Serial.print("T Kommando empfangen, setze Pin ");     
      Serial.print(timerpin[TI]);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(timerpin[TI],OUTPUT);
      digitalWrite(timerpin[TI],pinvalue);
      Serial.print("T Kommando empfangen, setze Time auf ");
      Serial.print(timerlength[TI]);
      Serial.print(" sec");
      Serial.println(" ");
     //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();
  }
}


Und die PHP-Ausgabe:
Code: [Select]

<?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 "Ventil = $ret <br>\n";
        //echo "1 = Zu | 0 = Auf <br>\n";
        
return $ret;
    } else {
        echo 
"Fehler, kein kontakt.<br>Kommando konnte nicht abgesetzt werden";
    }
}

  
$V1 arduino_send($arduino_ip,$arduino_port,"U".chr(4).chr(1).chr($V1));
  echo 
$V1;
?>



Ich hoffe Ihr versteht was ich meine  :smiley-red:
Im Serial Monitor sieht es so aus wie es eigentlich auch auf der Website zu sehen sein soll:
Code: [Select]

T Kommando empfangen, Timer 0 gestartet
T Kommando empfangen, setze Pin 4 auf 0
T Kommando empfangen, setze Time auf 900 sec
U Kommando empfangen, lese Timer 0 Wert = 900

Und auf der Website wird nur die 9 von der 900 angezeigt.

Vielen Dank...
*greatz*

 CeTax

www dot blinkmann dot de

Cetax

Moin,
keiner eine Idee, warum nur die erste Zahl (bsp. 9) angezeigt wird und nicht die ganze (bsp. 900) ?
Vieleicht kann ja nochma einer drauf schauen, wäre echt super  :smiley-mr-green:
*greatz*

 CeTax

www dot blinkmann dot de

mkl0815

Guten Morgen,

mal abgesehen davon, das Du in Deinem Sketch immer Timer 0 verwendest, da die Variable "TI" nie einen übergebenen Wert zugewiesen bekommt, ist die Lösung Deines Problems vermutlich recht einfach:
Code: [Select]

$ret =fread($res,10);

Damit werden im PHP Code 10 Zeichen aus der Verbindung gelesen und nicht nur 1 wie vorher.
Das mit den verschiedenen Timern solltest Du Dir aber nochmal ansehen.
Mario.

Ballibum

Hi, einfach eine kurze Zwischenfrage:
Um die verbindung zwischen Arduino und Pc herzustellen nutzt ihr da einen lokalen Webserver (wie z.B. Apache bei XAMPP) oder führt ihr die php-Dateien einfach von einem beliebigen Ordner im Browser (ja muss beim lokalen Webserver auch) aus?

mfg
Balli

mkl0815

Bei Cetax ist der Webserver glaub ich ein Synology-NAS, das auch PHP (+ Webserver) spricht. So wie die Umsetzung in diesem Projekt ist, braucht es zwingend einen Webserver. Wo der läuft ist erstmal egal, das kann auch ein lokaler XAMPP sein. Bei mir ist es ein MacMini Server :-)

Go Up