Problema comando relè via web con refresh pagina

Ciao,
mi sto cimentando con il mio primo progetto con Arduino, semplice semplice… si fa per dire :slight_smile:

Obiettivo
Comandare due relè per gestire, con uno l’apertura elettroserratura di un cancello pedonale e con l’altro l’avvio dell’apertura di un cancello carrabile elettrico.

Su questo forum ho trovato il codice per gestire 8 relè in modalità on/off e lo ho modificato per gestirne due in modalità pulsante, vanno in ON (viene chiuso circuito) e dopo 500 ms tornano a riposo.

Avevo il problema che al boot di aduino entrambi i relè andavano in ON ma ho risolto mettendo prima digitalWrite(,HIGH) e poi pinMode(, OUTPUT); e sarebbe stato non accettabile in caso di reboot volontario o involontario.

Risolto questo a banco funziona come mi aspetto tranne nel caso in cui venga fatto il refresh della pagina web, ricaricando la pagina con F5 viene inviato nuovamente l’ultimo comando dato, quindi se ho premuto Apri cancello pedonale il refresh provoca l’invio dello stesso comando.

Il problema penso sia dovuto al browser, se do il comando, attendo esecuzione, spengo e riaccendo arduino e faccio refresh pagina parte il comando che ho dato in precedenza.

se nello stesso momento faccio refresh da un altro browser dove ho solo caricato la pagina ma non ho dato nessun comando Arduino non fa nessuna azione.

Questo comportamento mi fa pensare a qualcosa che rimanga in memoria nel browser e che servirebbe un comando per cancellare il comando dato in precedenza.

Hardware utilizzato:
Arduino UNO R3
Ethernet Shield compatibile
Modulo Relay 2 canali

Qualcuno può darmi qualche dritta?

Grazie
Ciao
Patrizio

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


byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] =  { 192, 168, 25, 99 };
byte gateway[] = { 192, 168, 25, 254 };
byte subnet[] = { 255, 255, 255, 0 };

const int MAX_PAGENAME_LEN = 8; // max characters in page name
char buffer[MAX_PAGENAME_LEN+1]; // additional character for terminating null

EthernetServer server(80);

void setup()
{
  digitalWrite(7,HIGH);// turn relay ON
  digitalWrite(8,HIGH);// turn relay ON
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
}

void loop()
{
  EthernetClient client = server.available();
  if (client)
  {
    int type = 0;
    while (client.connected())
    {
      if (client.available())
      {
        // GET, POST, or HEAD
        memset(buffer, 0, sizeof(buffer)); // clear the buffer | scrive l'array con 0
        if (client.readBytesUntil('/', buffer, sizeof(buffer)))
        {
          if (strcmp(buffer, "POST ") == 0) //cerca la scritta post http://ruturajv.wordpress.com/2005/12/25/http-post-request/
          {
            client.find("\n\r"); // skip to the body
            // find string starting with "pin", stop on first blank line
            // the POST parameters expected in the form pinDx=Y
            // where x is the pin number and Y is 0 for LOW and 1 for HIGH
            while (client.findUntil("pinD", "\n\r")) {
              int pin = client.parseInt();       // the pin number
              int val = client.parseInt();       // 0 or 1
              //pinMode(pin, OUTPUT);
              if (pin == 10) {
                for (int i = 1; i < 10; i++) {
                  digitalWrite(i, val) ;
                }
              }
              else {
                digitalWrite(pin, val);
               }
            }
          }
          
            digitalWrite(7,HIGH);// turn relay ON
            digitalWrite(8,HIGH);// turn relay ON
          
          sendHeader(client, "Domotica 1.0");
          //create HTML button to control pin 8
          client.println("<h2>Controllo Cancelli</h2>");
          client.println("<table border='1' >");
        
            client.print("<tr><td>Cancello Pedonale ");
            //client.print(i - 1);
            client.print(7);
            client.print(" </td><td>");
            client.print("<form action='/' method='POST'><p><input type='hidden' name='pinD");
            client.print(7);
            client.print("'");
            client.println(" value='0'><input type='submit' value='Apri'/></form>");

            client.print("<tr><td>Cancello Carrabile ");
            //client.print(i - 1);
            client.print(8);
            client.print(" </td><td>");
            client.print("<form action='/' method='POST'><p><input type='hidden' name='pinD");
            client.print(8);
            client.print("'");
            client.println(" value='0'><input type='submit' value='Apri'/></form>");
  
          client.println("</td></tr>");
          client.println("</table>");
          client.println("</body></html>");
          client.stop();
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

void sendHeader(EthernetClient client, char *title)
{
  // send a standard http response header
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println();
  client.print("<html><head><title>");
  client.print(title);
  client.println("</title><body>");
}

Arduino - Apri cancello bozza.pdf (1.68 MB)

Qui più che un problema di arduino è com funziona la comunicazione client/server. Per come hai fatto il codice html quando premi refresh sul browser dovrebbe apparirti il messaggio del tipo "Eseguendo quest'azione i dati verranno di nuovo trasmessi al server ecc." ed è normale.
Dovresti cambiare modo di inviare le informazioni non usando una form con metodo post ma con sistemi differenti (Es. AJAX) tali da non far creare nuove azioni ad ogni refresh. Ma qui credo, anzi ne sono sicuro :slight_smile: , che l'argomento è fortemente OT quindi ti consiglio di controllare su internet/altri forum dedicati a codice Html/javascript per trovare la soluzione più adeguata

ThePatry:
Il problema penso sia dovuto al browser, se do il comando, attendo esecuzione, spengo e riaccendo arduino e faccio refresh pagina parte il comando che ho dato in precedenza.
se nello stesso momento faccio refresh da un altro browser dove ho solo caricato la pagina ma non ho dato nessun comando Arduino non fa nessuna azione.

Eh certo, tu hai una form con la quale mandi in POST il comando quindi se in un browser non hai mai cliccato “Apri” non manda alcun POST ma farà solo GET, ma se in un altro hai cliccato, quando fai F5 fa nuovamente lo stesso POST. Quindi è solo un problema di come tu imposti le “pagine”.

Se vuoi evitare che faccia POST, devi farlo fare al browser agganciando un evento onClick al pulsante e far fare al codice javascript, in modo che un eventuale reload della pagina non scateni lo stesso POST.

Per ulteriori informazioni, dato che non riguarda direttamente Arduino, ti conviene scrivere su qualche forum o cercare ad esempio su Stackoverflow.

Ciao,
Grazie ad entrambi per le risposte, indagherò nelle direzioni che mi avete indicato.

Una volta risolto il problema, posso aggiornare questo post con la soluzione in modo che sia disponibile per altri anche se, come temevo, è OT?

Patrizio

Direi di si, altrimenti credo che un moderatore avrebbe già chiuso il topic