Go Down

Topic: trasmettere comandi tra due arduino uno in udp (Read 4152 times) previous topic - next topic

ziopi88

ciao a tutti.
sono nuovo del forum e sono un neofita sia di programmazione che di arduino.
ho un problema che non riesco a risolvere e dopo alcuni giorni che sbatto la testa ovunque non arrivo da nessuna parte.
ho due arduino uno collegati ad uno swich di rete con due ethernet sheld wiznet, voglio remotizzare dei comandi a dei servo ovvero voglio utilizzare un arduino per pilotare i servo e l'altro per acquisire i dati di un potenziometro e inviarli via udp.
quindi modificando l'esempio base UDPsendreceiverstrig sono riuscito a farli comunicare,uno invia e l'altro riceve.
sino a quando si tratta di messaggi es; Udp.write("ciao") tutto ok. ma non so assolutamente  come mandare dei valori in modo separato o codificarli e riconoscerli separatamente dall'altra parte ovvero inviare per esempio val1=111  val2=90
e dall'altra parte ritrovarmi i due valori e scriverli su un uscita.
magari per qualcuno è una stupidata ma per me è una montagna dove non trovo neanche il sentiero per partire.
grazie in anticipo a chiunque risponda

nid69ita

In C/C++ (Arduino) devi imparare ad usare le stringhe, vettore di caratteri terminato da null '\0'.   NON la classe String che su queste MCU con poca SRAM possono dare problemi.

Quello che vuoi costruirti è un tuo protocollo. Per semplificare ti conviene stabilire delle parole a lunghezza fissa, esempio (non per il tuo caso specifico) vuoi accendere/spegnere dei rele numerati da 1 a 12 , io manderei delle frasi del tipo   R04 => accendi rele numero 4.          r04=> spegni il rele numero 4.   Nota che mando sempre 2 cifre e la 'R' oppure 'r' mi dice se accendo o spengo.
Nello sketch a questo punto non è difficile "analizzare" la frase ricevuta per stabilire i "comandi" che Arduino deve svolgere.
Una parte della frase è un valore che dovrai convertire da testo a numero vero e proprio. Puoi usare atoi().
Nel tuo caso se devi mandare valori diversi per usi diversi invece di val1=111  val2=90   io spedirei     A111  e B090, come vedi la prima lettera indica il primo o secondo valore, mentre dal secondo carattere hai sempre il valore (al max. 3 cifre).
Tu ora come ricevevi quella frase "ciao" ? Hai il codice ?

Invece da dove spedisci ? Da un PC o da un altro Arduino?

my name is IGOR, not AIGOR

ziopi88

Ciao karma.
Allora, io invio da un Arduino e ricevo su di un altro Arduino e per verificare utilizzo il monitor seriale!
Ora mando lo sketch di invio
Code: [Select]
[code]#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>         


byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 176);
IPAddress remote (192,168,1,177);
unsigned int localPort = 8889;   




EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}

void loop() {

    Udp.beginPacket(remote,8888);
    Udp.write("hello");
    Udp.endPacket();
 
  delay(10);
}
[/code][/b]

E questo è quello per ricevere
Code: [Select]


#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.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[] = {
  0xAE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i = 0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}



gpb01

@ ziopi88 :  Si parla d'altro, ma prova a guardare le mie spiegazioni in QUESTO thread ... magari possono aiutarti ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

nid69ita

#4
Jul 03, 2014, 11:50 am Last Edit: Jul 03, 2014, 11:52 am by nid69ita Reason: 1
@ziopi, quello che spedisci lo ricevi e te lo ritrovi dentro a stringa "packetBuffer".
Quello che non sò è se spedendo 2 volte "hello" dentro a quella stringa avrai prima un "hello" e poi un'altro "hello" oppure ti ritrovi 2 hello in un unica ricezione. Il tuo che spedisce lo fa di continuo, cosa ricevi?  Un "hello" alla volta?
Se si, invece di "hello" puoi spedire dei comandi come detto prima.

Code: [Select]
char buf[20];
....
comando='A';   // singolo carattere
valore=67;
snprint(buf,20,"%c%03d",comando,valore);     // scrive dentro a buf   "A067" vedi printf del C
Udp.write(buf);

%c stampa un carattere, %d un numero, con 03 lo riempie di 0 per 3 posizioni
http://www.cplusplus.com/reference/cstdio/snprintf/?kw=snprintf
http://www.cplusplus.com/reference/cstdio/printf/
my name is IGOR, not AIGOR

ziopi88

Allora, gpb01 ho letto quel articolo simile e secondo mè puo darsi che abbia lo stesso problema... devo avere un Po di tempo ed iniziare a fare esperimenti.
Invece per nido 69ita: allora, se scrivo
Code: [Select]

Udp.write("hello")
Udp.write("hello")

Dall'altra parte sulla seriale mi trovo hellohello
Ma se invio esempio
Code: [Select]

int val=123
Udp.write(val)

Dall'altra parte mi ritrovo es y

nid69ita

#6
Jul 03, 2014, 01:51 pm Last Edit: Jul 03, 2014, 01:53 pm by nid69ita Reason: 1
Logico, se usi write() con un numero lui invia sempre il valore di quel numero (singolo byte) e non 3 cifre.
http://arduino.cc/en/Reference/EthernetUDPWrite

Devi convertire quella val in testo. Vedi il mio post precedente con esempio. Lo converto e lo rendo anche a dimensione fissa.
my name is IGOR, not AIGOR

ziopi88

ciao di nuovo non so perché non riuscivo a connettermi al forum dal mio portatile.... appena facevo il log in si incartava il sito.
cmq dopo varie letture ed esperimenti non arrivo da nessuna parte..... =( =( =(
codice tx
Code: [Select]
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.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
};
IPAddress ip(192, 168, 1, 176);
IPAddress remoto(192,168,1,177);
unsigned int localPort = 8889;

int val1=234;
int val2=90;
int val3=34;
char stringa[UDP_TX_PACKET_MAX_SIZE] = {val1,val2,val3}; //buffer to hold incoming packet,



EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}

void loop() {

   
    Udp.beginPacket(remoto,8888);
    Udp.write(stringa,UDP_TX_PACKET_MAX_SIZE);
    Udp.endPacket();
 
  delay(10);
}


codice rx
Code: [Select]
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.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, 0xED, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i = 0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}

risultato sulla seriale: Received packet of size 24
From 192.168.1.176, port 8889
Contents:
êZ"

nid69ita  ho cercato il tuo ultimo post ma non so quale sia.
mi date una dritta su dove posso andare a studiarmi questo argomento senza stressarvi l'anima =( =(

nid69ita

#8
Jul 08, 2014, 11:28 am Last Edit: Jul 08, 2014, 11:39 am by nid69ita Reason: 1
Mi riferivo a questo:
http://forum.arduino.cc/index.php?topic=252874.msg1790912#msg1790912
uso il comando snprint() oppure itoa()


Tu qui spedisci numeri come numeri e non come testo:
Code: [Select]
int val1=234;
int val2=90;
int val3=34;
char stringa[UDP_TX_PACKET_MAX_SIZE] = {val1,val2,val3};

Questi valori se li stampi a video sono 234=ê   90=Z    e 34="
Quindi hai ricevuto i valori giusti. Devi però stamparli come numeri:
Code: [Select]
Serial.println( int(remote[i]), DEC);
Essendo array remote di char, la print tende a stamparti i valori come caratteri
my name is IGOR, not AIGOR

ziopi88

ok sono scemo era sotto il naso....
arrivano tx
Code: [Select]
int val1=234;
int val2=90;
int val3=34;
char stringa[UDP_TX_PACKET_MAX_SIZE] = {val1,val2,val3}; //buffer to hold incoming packet,

rx


Code: [Select]
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
     for (int i = 0; i < 4; i++)
    {
      Serial.print(packetBuffer[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }

risposta
From 192.168.1.176, port 8889
Contents:
-22.90.34.0Received packet of size 24

ho provato a leggere 3 volte http://www.cplusplus.com/reference/cstdio/snprintf/?kw=snprintf ma non riesco davvero a capire nulla  =(
cmq con questa strada sto avendo risultati quindi l'unica è continuare di qua...e soprattutto forse capisco cosa sto facendo oppure ci arrivo a scopio ritardato.
cmq avrei ancora alcune domandine
perchè comprende male i valori superiori a 100??
poi perchè anche se io modifico lo skech e mando un solo val dall'altra parte mi trovo , un valore giusto e poi altri  3 valori diversi divisi da tre puntini???
grazie per la pazienza.

nid69ita

#10
Jul 09, 2014, 03:50 pm Last Edit: Jul 09, 2014, 03:55 pm by nid69ita Reason: 1
1) Indipendentemente da quante cifre spedisci nel codice c'e' quel for() che è un ciclo per stampare sempre 4 valori. La cosa migliore sarebbe mandare come primo valore il numero di elementi spediti. Quel for() ora è fisso e si aspetta sempre 4 cifre.

2) Quell'  if (i < 3)   stampa sempre 3 puntini tra le cifre. Levalo.

3) Poi tu stampi (te lo ripeto, l'ho scritto sopra) le cifre che ricevi prendendole da buffer che è un array/vettore di char, perciò stai stampando i valori come caratteri. I char poi sono con il segno.
Un char accetta un byte (8 bit) quindi valori da 0-255 se unsigned (senza segno) oppure -128+127 se con segno.
Un char è con segno. Il valore contenuto è sempre uguale. 10 con o senza segno è sempre lo stesso. Valori superiori a 127 sono interpretati nei char come negativi. Se stampi però usando la conversione a unsigned sei a posto (si chiama cast in linguaggio C ).
Code: [Select]
Serial.println( (unsigned int)remote[i], DEC);     // converte char in unsigned int, cast
my name is IGOR, not AIGOR

Go Up