Progetto Push Botton Ethernet

Ciao a tutti,
vorrei realizzare un push botton ethernet.
(arduino Uno+shield Ethernet)

Molto semplicemente vorrei collegare agli ingressi di arduino degli interruttori distanti una 50 di metri collegati con cavo udp cat 5e

Ad ogni interruttore vorrei dedicare una socket ex; 5001,5002,5003 etc

Quando l'interruttore viene azionato se presente una connessione client deve essere inviata una stringa di evento.

Meglio usare contatti analogici o digitali?
E possibile che il client si connetta alla porta e riceva direttamente le stringhe senza prima inviare nulla?

Dove posso trovare la documentazione per l'invio UDP dei dati?

Scusate ma sono nuovo, ho bisogno di orientarmi un po.
Grazie in anticipo

Ciao, puoi realizzare la cosa in 2 modi, ovvero tramite Ethernet Shield fai fare da Server o Client ad Arduino..

Ti consiglio il primo caso, ovvero quando Arduino parte tira su il servizio TCP su una determinata porta e sta in ascolto.
Il software che presumo dovrai scrivere per girare su un PC o altro, non deve far altro che gestirsi le connessioni con l'arduino, per individuare quando il socket su Arduino è pronto e al limite gestire la disconnessione e riconnessione automatica.

A questo punto ti basta inviare una stringa sulla connessione Ethernet in base all'evento che vuoi gestire.. in modo che questa raggiunga via Ethernet il sw. su PC, e puoi ovviamente fare il contrario, ovvero da PC inviare i dati ad Arduino, ti devi fare un parser dei dati in ricezione però.

Se devi gestire più di 1 bottone su Arduino, non ti consiglio di aprire più socket, anche perchè forse non si può fare. Ma inviare comandi diversificati, ovvero specificare con una sorta di ID univoco l'intestazione di ogni messaggio che identifica il pulsante che ha scatenato l'evento. Lato PC ti scompatti il messaggio e identifichi da dove arriva.

Mi pare che però Arduino di base crea un server solo su TCP, in UDP non ho mai provato. Altra cosa da tenere in considerazione è che lo shield Ethernet non permette più di 5 connessioni contemporanee, la cosa migliore è avere 1 solo client che si collega ad Arduino e tiene aperta la connessione finchè è necessario.

Verifica anche quale shield Ethernet stai usando, io ho avuto parecchi problemi con la vecchia relase poichè dopo un tot di connessioni si inchiodava tutto e non comunicava più. Mi pare che nella nuova versione abbiano risolto il problema a livello Hardware.

Altre info le trovi qui Ethernet - Arduino Reference

Grazie mille per le dritte.
Il server socket funziona come si deve e consente anche più di una connessione server per volta. Mi riservo di testare fino a quanti layer riesce a gestire.

Ancora una domanda.
Da quanto ho capito devo collegare il bottone tra i 5 volt e un digital input.
Negli esempi noto che c'è sempre una resistenza di carico prima dell'interrutore.

La situazione corretta dovrebbe essere interruttore normalmente aperto con un leggero carico che serve per dare uno stato logico alla corrente?

Ho provato cosi e funziona. Mi chiedevo se è possibile evitare la resistenza e utilizzare solo la chiusura di un circuito.

Grazie ancora, quando avrò finito pubblicherò il lavoro. Sarà anche una cosa banale ma in commercio un dispositivo a 4 porte del genere costa 400?...

Sulla resistenza credo che sia necessaria, ma di elettronica non sono molto ferrato :wink:
Cmq. è vero che in giro ci sono prodotti così cari, ma di solito fanno altre mille cose che mediamente non servono.. come nel tuo caso credo...
Datti un'occhiata anche a questi prodotti..

Personalmente se dovessi solo gestire dei bottoni come nel tuo caso,forse sceglierei queste soluzioni.. li ho usati e vanno veramente bene, il linguaggio di programmazione è ancora + semplice di Arduino e forse sulla parte di connessioni Ethernet sono un passo avanti (non me ne voglia nessuno, ma non è una critica su Arduino ;)).

Avevo pensato di utilizzate gli analog input e di sfruttare i 5 volt come segnale,
Il problema è che cmq rileva delle tensioni.
Il programma di esempio webserver produce questo output
analog input 0 is 1022
analog input 1 is 1023
analog input 2 is 689
analog input 3 is 519
analog input 4 is 376
analog input 5 is 331

Senza il giochino delle resistenze non ho una tensione bassa di riferimento.
Forse devo cercare uno shield apposta o creare il piastrino, cosa che vorrei evitare..

Qualcuno ha fatto esperienze simili?

Ma scusa, se sono solo delle chiusure contatto (come se fosse un pulsante) non ti conviene usare i pin digitali in lettura ?
Se fossero tutti occupati, puoi forzare gli input analogici a lavorare come se fossero digitali, semplicemente dichiarandoli nella fase di setup in questo modo
pinMode(14, INPUT); // Pin Analog 0
pinMode(15, INPUT); // Pin Analog 1
..
pinMode(19, INPUT); // Pin Analog 5

vedi anche qui http://www.arduino.cc/en/Tutorial/AnalogInputPins

Domanda..
ok.. ho usato i digital input e funzionano. Usato l'ethernet sheld ho intuito che non devo usare i pin dal 10 al 13.

In riferimento al listato sottostante avrei bisogno di scrivere al posto del messaggio "contatto off" o "on" un messaggio molto semplice del tipo
1 char status - 0 = contatto aperto, 1= contatto chiuso
1 char Port - da 0 a 3
15 char ip address

Inoltre mi trovo in difficoltà in una serie di conversioni e sintassi.
Io le butto li poi chi ha tempo mi dica.. ::slight_smile:

Come faccio a creare una struttura contenente le 4 porte (classe server) in modo da poterci ciclare semplicemente con un ciclo for?

Come faccio a buttare un array di byte, nello specifico l'indirizzo IP, in una stringa per passarla poi sul socket tramite il metodo write?

Scusate la banalità delle domande ma con la sintassi ANSI C(l'unica che conosco.. più o meno..) non ci sono saltato fuori

/*
  Four Digital dry push botton ethernet server
 
 A simple socket server for retry button status changing using digital input pins.
 Arduino Ethernet SD shield platform is required. 
  
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Digital attached to pins 0 through 3
 
 Protocol
 For each port use a socket. To 5001 through 5004
 When b
 
 Created 24 Nov 2010
 by Marco BRUNO, Ivrea, Italy
 Rev 2010.02 25 Nov 2010 Marco BRUNO, Ivrea, Italy: Adding comments

 
 */

#include <SPI.h>
#include <Ethernet.h>
//#include <String.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/wdt.h>
#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}  // Cane da guardia, se il timer si inchioda riavvia arduino
// Per resettare alla bisogna via softwqware usare
//  Reset_AVR();

//#include <Udp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
byte gateway[] = {192, 168, 1, 1};      
byte subnet[] = {255, 255, 255, 0};


// Initialize the Ethernet server library
// with the IP address and port you want to use 
Server port1(5001);
Server port2(5002);
Server port3(5003);
Server port4(5004);

int Button1State = 0;  // Variable for reading the pushbuttons status
int Button2State = 0;  // Variable for reading the pushbuttons status 
int Button3State = 0;  // Variable for reading the pushbuttons status 
int Button4State = 0;  // Variable for reading the pushbuttons status   
int Button1StateOld = 0;            // 
int Button2StateOld = 0;            // 
int Button3StateOld = 0;            // 
int Button4StateOld = 0;            // 


String sIp="";

String sIpSep=".";
//itoa(int(ip[0]),sIP,10);
//+"."+string(ip[0])+"."+String(ip[0])+"."+String(ip[0]);

  


  
void setup()

{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
    
 // start listening for clients
  port1.begin();
  port2.begin();
  port3.begin();
  port4.begin();
  
  // initialize the pushbutton pin as an input:
  pinMode(0, INPUT); 
  pinMode(1, INPUT); 
  pinMode(2, INPUT); 
  pinMode(3, INPUT); 


  digitalWrite(0, HIGH);   // sets the LED on
  digitalWrite(1, HIGH);   // sets the LED on
  digitalWrite(2, HIGH);   // sets the LED on
  digitalWrite(3, HIGH);   // sets the LED on

}

void loop()
{
  
// Controllo su porta1 --------------------------------------
  Button1State = digitalRead(0);
  if (Button1State != Button1StateOld)
       {     
        if (Button1State == HIGH)
           {     
           port1.write("Conttato 1 On");
           } 
           else 
           {
           port1.write("Conttato 1 Off");
           }
       } 
       Button1StateOld=Button1State;
       
// Controllo su porta2 --------------------------------------
  Button2State = digitalRead(1);
  if (Button2State != Button2StateOld)
       {     
        if (Button2State == HIGH)
           {     
           port2.write("Contatto 2 On");
           } 
           else 
           {
           port2.write("Contatto 2 Off");
           }
       } 
       Button2StateOld=Button2State;
       
// Controllo su porta3 --------------------------------------
  Button3State = digitalRead(2);
  if (Button3State != Button3StateOld)
       {     
        if (Button3State == HIGH)
           {     
           port3.write("Contatto 3 On");
           } 
           else 
           {
           port3.write("Contatto 3 Off");
           }
       } 
       Button3StateOld=Button3State;
       
// Controllo su porta4 --------------------------------------
  Button4State = digitalRead(3);
  if (Button4State != Button4StateOld)
       {     
        if (Button4State == HIGH)
           {     
           port4.write("Contatto 4 On");
           } 
           else 
           {
           port4.write("Contatto 4 Off");
           }
       } 
       Button4StateOld=Button4State;
       
      delay(10);
}


[code]/*
  Four Digital dry push botton ethernet server
 
 A simple socket server for retry button status changing using digital input pins.
 Arduino Wiznet Ethernet shield platform is required. 
  
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Digital attached to pins 0 through 3
 
 Protocol
 For each port use a socket. To 5001 through 5004
 When b
 
 Created 24 Nov 2010
 by Marco BRUNO, Ivrea, Italy
 Rev 2010.02 25 Nov 2010 Marco BRUNO, Ivrea, Italy: Adding comments

 
 */

#include <SPI.h>
#include <Ethernet.h>
//#include <String.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/wdt.h>
#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}  // Cane da guardia, se il timer si inchioda riavvia arduino
// Per resettare alla bisogna via softwqware usare
//  Reset_AVR();

//#include <Udp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
byte gateway[] = {192, 168, 1, 1};      
byte subnet[] = {255, 255, 255, 0};


// Initialize the Ethernet server library
// with the IP address and port you want to use 
Server port1(5001);
Server port2(5002);
Server port3(5003);
Server port4(5004);

int Button1State = 0;  // Variable for reading the pushbuttons status
int Button2State = 0;  // Variable for reading the pushbuttons status 
int Button3State = 0;  // Variable for reading the pushbuttons status 
int Button4State = 0;  // Variable for reading the pushbuttons status   
int Button1StateOld = 0;            // 
int Button2StateOld = 0;            // 
int Button3StateOld = 0;            // 
int Button4StateOld = 0;            // 


String sIp="";

String sIpSep=".";
//itoa(int(ip[0]),sIP,10);
//+"."+string(ip[0])+"."+String(ip[0])+"."+String(ip[0]);

  


  
void setup()

{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
    
 // start listening for clients
  port1.begin();
  port2.begin();
  port3.begin();
  port4.begin();
  
  // initialize the pushbutton pin as an input:
  pinMode(0, INPUT); 
  pinMode(1, INPUT); 
  pinMode(2, INPUT); 
  pinMode(3, INPUT); 


  digitalWrite(0, HIGH);   // sets the LED on
  digitalWrite(1, HIGH);   // sets the LED on
  digitalWrite(2, HIGH);   // sets the LED on
  digitalWrite(3, HIGH);   // sets the LED on

}

void loop()
{
  
// Controllo su porta1 --------------------------------------
  Button1State = digitalRead(0);
  if (Button1State != Button1StateOld)
       {     
        if (Button1State == HIGH)
           {     
           port1.write("Conttato 1 On");
           } 
           else 
           {
           port1.write("Conttato 1 Off");
           }
       } 
       Button1StateOld=Button1State;
       
// Controllo su porta2 --------------------------------------
  Button2State = digitalRead(1);
  if (Button2State != Button2StateOld)
       {     
        if (Button2State == HIGH)
           {     
           port2.write("Contatto 2 On");
           } 
           else 
           {
           port2.write("Contatto 2 Off");
           }
       } 
       Button2StateOld=Button2State;
       
// Controllo su porta3 --------------------------------------
  Button3State = digitalRead(2);
  if (Button3State != Button3StateOld)
       {     
        if (Button3State == HIGH)
           {     
           port3.write("Contatto 3 On");
           } 
           else 
           {
           port3.write("Contatto 3 Off");
           }
       } 
       Button3StateOld=Button3State;
       
// Controllo su porta4 --------------------------------------
  Button4State = digitalRead(3);
  if (Button4State != Button4StateOld)
       {     
        if (Button4State == HIGH)
           {     
           port4.write("Contatto 4 On");
           } 
           else 
           {
           port4.write("Contatto 4 Off");
           }
       } 
       Button4StateOld=Button4State;
       
      delay(10);
}

up

marco ma il software che hai messo in linea funziona io vorrei creare con ethernet sheld un supervisore x gestire l'arduino in remoto

si funziona ma vorrei migliorare la formattazione delle stringhe e la parametrizzazione dei cicli sulle stesse.

Tra l'altro sarebbe bello riuscire a scrivere qualcosa che permetta l'utilizzo di un indirizzo tramite dhcp e un micro (dico mico) web server che permetta la configurazione di alcuni parametri.
Eventualmente di può salvare qualche cosa su la micro sd che c'è on board sullo shield ethernet.

Qualcuno mi sa indicare come buttare un array di byte, nello specifico l'indirizzo IP, in una stringa per passarla poi sul socket tramite il metodo write

Qualcuno mi sa indicare come fare a creare una struttura contenente le 4 porte (classe server) in modo da poterci ciclare semplicemente con un ciclo for?

quindi avrei in remoto la possibilia di gestire 4 ingressi e quattro uscite con il programma in html sopra scritto

Jacoluca, potresti spiegare meglio cosa devi fare esattamente?

Arduino ha un Tot di porte che possono essere usate in ingresso ed in uscita sia in modo analogico che digitale(2 livelli diversi di tensione).
Tieni presente che sono abbastanza neofita ed autodidatta sull'argomento.

Cmq arduino può fare quello che devi fare ma NON con il mio listato che gestisce solo l'invio di messaggi su socket ethernet alla banale pressione di un tasto collegato per esempio tra il pin1 e il pin gnd.

Qualcuno mi da una mano nel formattare le stringhe???

up

Ho modificato il programma manipolando le stringhe in uscita con la funzione substring della classe string
Aggiungo codice modificato sotto
[ String format ]

| Message | Input | IOLAN MAC | Current |Current Status | Ip |
| Type | Number | Address |Alarm State | of Input | |
| (1 Byte) | (1 Byte) | (6 Bytes) | (1 Byte) | (1 Byte) |(15 Bytes)|

-Message type: (1 Byte)
0 = Digital input status (Fix Value)

-Input number: (1 Byte)
Digital input will be 1, 2, 3, or 4 to represent the channel number

-MAC Address of the IOLAN sending the input information. (6 Bytes)

-Current Alarm State: (1 Byte)
0 = Not in alarm
1 = In Alarm

-Current Status of Input: (1 Byte)
0 = Inactive for digital input.
1 = Active for digital input.

-Arduino shield Ip Address. (15 Bytes)

/*
  Four Digital dry push botton ethernet server
 
 A simple socket server for retry button status changing using digital input pins.
 Arduino Wiznet Ethernet shield platform is required. 
  
[ Circuit: ]
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Digital attached to pins 0 through 3
 
[ Protocol ]
 For each port use a socket. To 5001 through 5004
 When b
 
[ String format ]
 ---------------------------------------------------------------------------
 | Message  |    Input | IOLAN MAC |    Current |Current Status |      Ip  |
 |    Type  |   Number |  Address  |Alarm State |      of Input |          |
 | (1 Byte) | (1 Byte) | (6 Bytes) |  (1 Byte)  |      (1 Byte) |(15 Bytes)|
 ---------------------------------------------------------------------------
 -Message type: (1 Byte)
   0 = Digital input status (Fix Value)


 -Input number: (1 Byte)
   Digital input will be 1, 2, 3, or 4 to represent the channel number

 -MAC Address of the IOLAN sending the input information. (6 Bytes)

 -Current Alarm State: (1 Byte)
   0 = Not in alarm
   1 = In Alarm

 -Current Status of Input: (1 Byte)
   0 = Inactive for digital input.
   1 = Active for digital input.

 -Arduino shield Ip Address. (15 Bytes) 

[ Programmer ] 
 Created 24 Nov 2010
 by Marco BRUNO, Ivrea, Italy
 Rev 2010.02 25 Nov 2010 Marco BRUNO, Ivrea, Italy: Adding comments

 
 */
#include <SPI.h>
#include <String.h>
#include <Ethernet.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/wdt.h>
#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}  // Cane da guardia, se il timer si inchioda riavvia arduino
// Per resettare alla bisogna via softwqware usare
//  Reset_AVR();

//#include <Udp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
String sMac;
String sIP;
String sMsg="                         ";
int iPort;
int iLenMsg = 25;
    char cMsg[25];

byte gateway[] = {192, 168, 1, 1};	
byte subnet[] = {255, 255, 255, 0};


// Initialize the Ethernet server library
// with the IP address and port you want to use 
Server port1(5001);
Server port2(5002);
Server port3(5003);
Server port4(5004);

int Button1State = 0;  // Variable for reading the pushbuttons status
int Button2State = 0;  // Variable for reading the pushbuttons status 
int Button3State = 0;  // Variable for reading the pushbuttons status 
int Button4State = 0;  // Variable for reading the pushbuttons status   
int Button1StateOld = 0;            // 
int Button2StateOld = 0;            // 
int Button3StateOld = 0;            // 
int Button4StateOld = 0;            // 

int sStato=0;


String sIpSep=".";
//itoa(int(ip[0]),sIP,10);
//+"."+string(ip[0])+"."+String(ip[0])+"."+String(ip[0]);

  


  
void setup()

{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
    
 // start listening for clients
   Serial.begin(9600);
  port1.begin();
  port2.begin();
  port3.begin();
  port4.begin();
  
  // initialize the pushbutton pin as an input:
  pinMode(0, INPUT); 
  pinMode(1, INPUT); 
  pinMode(2, INPUT); 
  pinMode(3, INPUT); 


  digitalWrite(0, HIGH);   // sets the LED on
  digitalWrite(1, HIGH);   // sets the LED on
  digitalWrite(2, HIGH);   // sets the LED on
  digitalWrite(3, HIGH);   // sets the LED on

  // Ip address
  sIP=int(ip[0]);
  sIP+='.';
  sIP+=int(ip[1]);
  sIP+='.';
  sIP+=int(ip[2]);
  sIP+='.';
  sIP+=int(ip[3]);
  
    // Mac address
  sMac=mac[0];
  sMac+='.';
  sMac+=mac[1];
  sMac+='.';
  sMac+=mac[2];
  sMac+='.';
  sMac+=mac[3];
  sMac+='.';
  sMac+=mac[4];
  sMac+='.';
  sMac+=mac[5];
  



}


void loop()
{

// Controllo su porta1 --------------------------------------
  iPort=1;
  Button1State = digitalRead(0);
  if (Button1State != Button1StateOld)
       {     
        if (Button1State == HIGH)
           {
           sStato=0;
           cplmsg();
           port1.write(cMsg);
           } 
           else 
           {
           sStato=1;
           cplmsg();
           port1.write(cMsg);             
           }
       } 
       
       Button1StateOld=Button1State;
       
// Controllo su porta2 --------------------------------------
  iPort=1;
  Button2State = digitalRead(1);
  if (Button2State != Button2StateOld)
       {
        
        if (Button2State == HIGH)
           {     
           port2.write("Open");
           } 
           else 
           {
           port2.write("Close");
           }
           
       } 
       Button2StateOld=Button2State;
       
// Controllo su porta3 --------------------------------------
  iPort=1;
  Button3State = digitalRead(2);
  if (Button3State != Button3StateOld)
       {     
        if (Button3State == HIGH)
           {     
           port3.write("Open");
           } 
           else 
           {
           port3.write("Close");
           }
       } 
       Button3StateOld=Button3State;
       
// Controllo su porta4 --------------------------------------
  iPort=1;
  Button4State = digitalRead(3);
  if (Button4State != Button4StateOld)
       {     
        if (Button4State == HIGH)
           {     
           port4.write("Open");
           } 
           else 
           {
           port4.write("Close");
           }
       } 
       Button4StateOld=Button4State;
       
      delay(10);
}

void cplmsg()
{
//  sMsg.substring(1,25)="                          ";
//  sMsg.substring(1,1)="0";
//  sMsg.substring(2,1)=int(iPort);
//  sMsg.substring(3,6)=sMac;
//  sMsg.substring(9,1)="0";
//  sMsg.substring(10,1)=sStato;
//  sMsg.substring(11,15)=sIP;

sMsg="";
sMsg+="0";
sMsg+=int(iPort);
sMsg+=sMac;
sMsg+="0";
sMsg+=sStato;
sMsg+=sIP;

  for (int a=0;a<25;a++)
        {
            cMsg[a]=sMsg[a];
        }

}