[RISOLTO]inviare dati con ethernet shield al verificarsi di un evento

Salve a tutti i membri del forum,
da poco mi sono appassionato ad Arduino.
Ho letto in giro molte guide e numerosi forum su come collegare Arduino ad internet ed inviare dati. In effetti le guide sono molto semplici ed il risultato è arrivato molto in fretta.
Riesco ad inviare i dati ed inserirli in un database sulla mia pagina Web. Il problema che mi spinge a scrivere un nuovo post e che ancora non sono riuscito a capire quel’è la strada migliore per il mio progetto. Vorrei alcuni suggerimenti, da voi che siete più esperti, per sapere bene come muovermi con questa (per me nuova) tecnologia. In particolare io dovrei inviare i dati al server al verificarsi di un evento. ho usato un bottone e con l’interrupt intercetto l’evento e invio i dati. il problema e che Arduino funziona solo la prima volata alla seconda pressione del tasto non invia più, e sembra bloccarsi. posto anche il codice se può essere utile. Praticamente l’applicazione dovrebbe fare questo: ogni volta che il pulsante viene pigiato un dato deve essere inviato al mio sito, ma se non si verificano eventi non deve fare niente. il dubbio che mi veniva era anche sulla disconnessione dal server, se e dopo quando avviene o se conviene disconnettersi ogni volta visto che gli eventi si verificano a distanza di molte ore.
grazie in anticipo per la vostra collaborazione.

/**
 * Test web trasmission
 *
 * 
 * 
 */
#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; // cambiare con il proprio numero MAC scritto sulla scheda shield ethernet 
//byte gateway[] = { 192,168,10,1 }; //usare solo su reti con ip statico 
//byte ip[] = { 192, 168, 10, 3 };   //usare solo su reti con ip statico 
IPAddress server(111,111,111,111);  //sostituire con ip del proprio sito web
// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
int interrCount=0;
 
void setup()
{
  Serial.begin(9600);
  attachInterrupt(0, interrupt, RISING); //ho un pulsante collegato al pin2
}
 
void loop() {

  if (client.available()) {
      char c = client.read();
      Serial.print(c);
  }
}
 
void interrupt()
{
  // start the serial library:
  Serial.begin(9600);
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
   Serial.println("Failed to configure Ethernet using DHCP");

  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET http://www.iltuosito.estensione?latuavariabile=iltuovalore HTTP/1.0");//sostituire con la giusta richiesta
    client.println();
  } 
  else {
  // if you didn't get a connection to the server:
  Serial.println("connection failed");
  }
     // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
}

Premesso che sono un ignorante in material di scheda Ethernet, vorrei però farti un appunto. Gli interrupt generalmente sono da usarsi per eseguire compiti semplicissimi. Inserire in una routine di gestione dell'interrupt la spedizione di un dato via ethernet mi pare il modo migliore per piantare tutto l'Arduino.

Quando il microcontrollore esegue una ISR (Internet Service Routine) blocca l'esecuzione non solo del codice principale ma di tutte le altre ISR. Ecco perché si devono usare funzioni: 1) il più brevi possibile; 2) che non usino a loro volta interrupt. La seriale, ad esempio, che tu hai messo nella tua ISR, usa gli interrupt sia in RX che in TX (con l'IDE 1.x). Non so poi la libreria Ethernet cosa faccia ma visto che comunica via SPI con la scheda Ethernet, immagino possa usare gli interrupt anch'essa.

Io mi approccerei al problemi in un'altra maniera, usando la tua ISR solo per cambiare di stato ad una variabile che poi leggi dal loop principale. Ad esempio, potresti usare una variabile numerica che, ad ogni interrupt, viene incrementata di 1.

void interrupt()
{
  pressioni++;
}

In questo modo nel loop non devi far altro che controllare se pressioni è maggiore di 0 e sapere se e quante volte il pulsante è stato premuto, spedire i dati e poi azzerare la variabile

Se sia l'interrupt a bloccare tutto questo non lo so vedendo lo sketch, però non vedo il set della porta 2 che usi come pulsante, per default non è un input. Molto probabilmente stai collegando un uscita +V a GND.

dichiara nel setup correttamente il pin 2

sarebbe utile sapere che arduino usi e la vers dell'IDE

ciao

Gli interrupt operano in maniera parallela alla normale funzionalità della porta né necessitano che essa sia dichiarata come input.

@Leo Sto approfondendo anch'io il tema interrupt per cercare di semplificare e accelerare i controlli, però non ho capito una cosa riguardo "attachInterrupt" Tu dici in un altro post (quando stavi facendo la stazione meteo) che puoi associare quasiasi pin all'interrupt, quindi questa linea attachInterrupt(0, interrupt, RISING); o CHANGE va ripetuta per ogni INTx? ogni INT controlla un buffer da 8 porte o di più? grazie

Ci sono 2 tipi di interrupt, quelli definiti INT e quelli definiti PCINT. Gli interrupt INT sono quelli hardware di livello più elevato e sono in numero limitato e legati a particolari pin. Ad esempio, nel caso dell'Atmega328 sono solo 2 e legati a particolari pin. Essi sono gestibili con le funzioni integrate nel core di Arduino attachInterrupt e detachInterrupt: http://arduino.cc/en/Reference/AttachInterrupt

Nell'Atmega328 sono l'INT0 e l'INT1, legati rispettivamente ai pin D2 e D3. Quando scrivi attachInterrupt(numero, funzione, modalità) con "numero" non indichi il numero di pin ma il numero di interrupt.

Parlando dei PCINT, invece, questi interrutp sono quelli a cui ti riferisci tu. Sono interrupt hardware di un livello inferiore rispetto agli INT (gerarchicamente, hanno priorità inferiore rispetto ad un INT) ma sono disponibili su tutti i pin dell'hardware. Il problema dei PCINT è che sono gestiti, come hai detto, tramite registri ad 8 bit che raggruppano i PCINT di una determinata porta per cui se arrivano più PCINT su una stessa porta viene sollevato un evento unico relativo a quella porta ma non sai a priori quale è arrivato per primo.

pablos: @Leo Sto approfondendo anch'io il tema interrupt per cercare di semplificare e accelerare i controlli, però non ho capito una cosa riguardo "attachInterrupt" Tu dici in un altro post (quando stavi facendo la stazione meteo) che puoi associare quasiasi pin all'interrupt, quindi questa linea attachInterrupt(0, interrupt, RISING); o CHANGE va ripetuta per ogni INTx? ogni INT controlla un buffer da 8 porte o di più? grazie

Non facciamo confusione con gli interrupt INT0 e INT1 (rispettivamente pin2 e 3 di arduino 2009/UNO) e gli interrupt non triggerabili PCINT0 to PCINTxx. Gli interrupt PCINT sono non trigerabili e vengono triggerati da ogni cambio di stato, da questo viene il prefisso PC, appunto Pin Changed, gli altri interrupt invece posso essere triggerato sul fronte di salita, discesa o su entrambe.

PCINTxx sono disponibili su tutti i pin del microcontroller, ma il core Arduino implementa solo gli interrupt INTx, ma ovviamente nel playground c'è più di una lib per PCINT che però non uso preferendo le ISR nude e crude.

I vettori associati gli interrupt PCINT sono in numero uguale alle porte, nel caso del micro 328 sono appunto 3, per cui qualunque pin di porta C comporterà l'esecuzione della ISR associata alla porta C. Per sapere quale pin ha scatenato l'esecuzione della ISR bisogna testare il valore di ogni bit di quella porta, tramite un if (digitalRead(pin) == 1) ecc posta all'intero della ISR.

preceduto da leo.

Ciao.

Grazie ragazzi,
i vostri suggerimenti sono stati illuminanti. In effetti avevo due errori uno software e uno hardware. l’errore hardware da nubbio e che avevo collegato un led diretto a 5v ( hehehe!! ), per quanto riguarda il sftware ho seguito il consiglio di elaborare il segnale con una variabile, quando questa variabile e “positiva” invio il segnale e nel caso non riuscisse riprovo fino a quando non ho la conferma di avvenuta trasmissione. Al momento il codice fa questo : spingo un pulsante e lui invia un dato al server che lo immagazzina nel database, i dati vengono poi rielaborati e visualizzati in una pagina php.
Grazie a tutti posto il codice se vi può essere utile.
Non ho ancora visto in giro ma se dovessi far loggare con nome utente e password il mio Arduino prima di inviare io dati ??

/*
 Sept 2012
 by  http://www.openfranchising.info
*/

// include for ethernet shield
#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {0xXX, 0xXX, 0xAA, 0xBB, 0xAA, 0x99 };

// fill in an available IP address on your network here,
// for manual configuration:
// IPAddress ip(0, 0, 0, 0); //solo su reti con  ip fissi
// IPAddress myDns(0, 0, 0, 0);

IPAddress server(xxx,xxx,xxx,xxx); // IP of your server

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

// set pin numbers:
const int buttonPin = 2;     // the number of the signsl/pushbutton pin
const int ledPin =  8;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the signa/pushbutton status
int connessione = 0;
int trasmesso = 0;

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);     
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:   
    connessione = 1 ;
    digitalWrite(ledPin, HIGH);
    
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
  if (connessione == 1){  //se ho avuto l'impulso mi connetto e invio dati
        // Open serial communications and wait for port to open:
        Serial.begin(9600);
        //while (!Serial) 
        //{
        ; // wait for serial port to connect. Needed for Leonardo only
        //}

        // start the Ethernet connection:
        //Ethernet.begin(mac, ip, myDns); this line only if not DHCP
        if (Ethernet.begin(mac) == 0) { // this line no in DHCP
            // ,ip,miDns require only fix IP 
            Serial.println("Failed to configure Ethernet using DHCP"); // this line no in DHCP
        }
        // give the Ethernet shield a second to initialize:
        delay(1000);
        Serial.println("connecting...");

        // if you get a connection, report back via serial:
        if (client.connect(server, 80)) {
            Serial.println("connected");
            // Make a HTTP request:
            client.println("GET http://www.xxxx?latuavariabile=valore HTTP/1.0");
            client.println();
            //la trasmissione è andata a buon fine 
            connessione = 0;
            trasmesso = 1;
        } 
        else {
            // if you didn't get a connection to the server:
            Serial.println("connection failed");
        }
  }
  
  
  // if there are incoming bytes available 
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected() && trasmesso == 1) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    trasmesso = 0;
    // do nothing forevermore:
    //for(;;)
    //  ;
  }
  
}

Ho un problema simile.
Leggo i dati da un sensore collegato ad un microprocessore Intel Galileo (Arduino based) e li invio ad una pagina web su Altervista, che li interpreta e aggiorna il database. Dopo la prima richiesta gestita correttamente, la connessione al server fallisce sempre.

Ecco lo sketch:

//#include <SPI.h> - not needed on Galileo
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
//byte mac[] = { 0x98, 0x4F, 0xEE, 0x00, 0x55, 0xCD }; // Arduino's artificial mac address - not needed on Galileo
IPAddress server(78,46,227,17); // Google
const int pin_sound = A0; 
int sound_sample;
//int count=0;
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(57600);
   while (!Serial) {
	; // wait for serial port to connect. Needed for Leonardo only
  }
  delay(3000);
  
  Serial.println("connecting...");
 
}
void loop()
{
    // if you get a connection, report back via serial:
  if (client.connect(server,80)){
	Serial.println("connected");
	
        //lettura dati dal sensore
        sound_sample = analogRead(pin_sound);
        
        //creazione URL per inviare la richiesta alla pagina php
        String Url="GET http://magliani.altervista.org/arduino.php?sensore=";
        Url.concat(sound_sample);
        String B=" HTTP/1.1";
        Url.concat(B);
        
        // Make a HTTP request:
	client.println(Url);
        client.println("Host: www.altervista.org");
//        client.println("Content-Type: application/x-www-form-urlencoded");
        client.println("Connection: close");
	client.println();

        Serial.println(Url);
        Serial.println("Host: www.altervista.org");
        Serial.println("Connection: close");
        Serial.println();
        
      

 }
  /*else {
	// if you didn't get a connection to the server:
	Serial.println("connection failed");
  }*/
  
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
	char c = client.read();
       // count++;
            // if (count<=1000)
       	Serial.print(c);
  }
  // if the server's disconnected, stop the client:
  if (!client.connected()) {
	Serial.println();
	Serial.println("disconnecting.");
        client.stop();
	// do nothing forevermore:
	for(;;)
	  ;
  }
}

Come posso risolvere?

Ilthebest: Leggo i dati da un sensore collegato ad un microprocessore Intel Galileo (Arduino based) e li invio ad una pagina web ...

La Galileo, a parte l'IDE e alcune header, non ha molto a che vedere con Arduino e per risolvere ... ... ti devi rivolgere al Forum di supporto Intel per la Galileo .

Guglielmo

Salve,
oltretutto se volessi inviare l’aggiornamento pagina html, ogni qualvolta un ingresso (pin) cambia stato, per ora sto usando questa funzione con questo codice,
ribadisco che vorrei richiamare la funzione solo quando il pin cambia stato d’ingresso.

                       cl.print(F("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'html://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'><html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>"));
                        cl.println(F("<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>"));
                        cl.println(F("<body onload=\"GetSensorState()\">"));
                        cl.println("<script>");
                        cl.println("function GetSensorState() {");
                        cl.println(" var request = new XMLHttpRequest();");
                        cl.println(" request.onreadystatechange = function() {");
                        cl.println(" if (this.readyState == 4) {");
                        cl.println(" if (this.status == 200) {");
                        cl.println(" if (this.responseText != null) {");
                        cl.println("document.getElementById(\"ilMio\").innerHTML = this.responseText;");
                        cl.println("}}}}");
                        cl.println(" request.open(\"GET\", \"/\", true);");
                        cl.println(" request.send(null);");
                        cl.println("}");
                       [color=red] cl.println(" setInterval('GetSensorState()', 20000);");  [/color]
                        cl.println("</script>");

Grazie ragazzi! Sempre top! :)


La mia firma personale

La mia firma è un esposizione di articoli su eventi nuziali che creo per famosi blog. Come questo che riguarda l'organizzazione del matrimonio: Noemi Wedding a Venezia e che ho pubblicato sul suo sito.

Estratto dell'articolo per un evento nuziale

Tieni i tuoi ospiti impegnati e intrattenuti durante il giorno delle nozze con dei giochi! Offrire giochi da cerimonia nuziale per farli divertire può intrattenere gli ospiti mentre voi e il vostro sposo siete fuori per essere fotografati.

E se hai amici e familiari che non si sono mai incontrati, i giochi del ricevimento possono essere un modo fantastico per rompere il ghiaccio in un evento nuziale, basta non esagerare; ricorda, l'evento è ancora un matrimonio, e l'attenzione principale dovrebbe essere su di te! Guarda la nostra guida completa ai migliori giochi per matrimonio per i tuoi ospiti.

>kalipsos: … potresti rileggere il punto 16.4 del REGOLAMENTO ? … perché in un thread ok, in due pure, ma che tutti i tuoi post siano così … non va molto bene eh :wink:

Grazie.

Guglielmo