[RISOLTO] Problema comunicazione Seriale

Salve a tutti,

in un mio precedente topic avevo affrontato un problema con I2C ed essendo impossibilitato ad usare esso, mi sono ritrovato a provare la comunicazione seriale tra due schede Arduino (un mini e un mega).

Ho la necessità di mandare valori letti dal mini al mega e quindi mi sono messo a fare qualche prova. Sono riuscito a mandare un qualsiasi numero da 0 a 255 dichiarato in una variabile globale, il cui valore non cambia nel void loop.

Il problema arriva però quando la variabile cambia nel corso del void loop. Infatti se prima il valore lo leggevo tranquillamente con il mega, se provo a trasmettere un valore di una variabile che non rimane uguale mi da nel mega un output a caso.

In caso qualcuno avesse piacere di aiutarmi lascio il codice del trasmettitore e quello del ricevitore.

Trasmettitore:

int analogPin_DX1 = 0;           //-------* ESTREMO
int analogPin_DX2 = 1;           //------*- ACCENTRATO
int analogPin_MD1 = 4;           //-----*-- DIETRO
int analogPin_MD2 = 6;           //----*--- DAVANTI
int analogPin_MD3 = 7;           //---*---- DAVANTI
int analogPin_MD4 = 5;           //--*----- DIETRO
int analogPin_SX2 = 3;           //-*------ ACCENTRATO
int analogPin_SX1 = 2;           //*------- ESTREMO

int val_DX1 = 0;
int val_DX2 = 0;
int val_MD1 = 0;
int val_MD2 = 0;
int val_MD3 = 0;
int val_MD4 = 0;
int val_SX2 = 0;
int val_SX1 = 0;

int val = 0;


void setup()
{
  Serial.begin(115200);                   //DEBUG
}

void loop()
{

  val_DX1 = analogRead(analogPin_DX1);
  val_DX2 = analogRead(analogPin_DX2);
  val_MD1 = analogRead(analogPin_MD1);
  val_MD2 = analogRead(analogPin_MD2);
  val_MD3 = analogRead(analogPin_MD3);
  val_MD4 = analogRead(analogPin_MD4);
  val_SX2 = analogRead(analogPin_SX2);
  val_SX1 = analogRead(analogPin_SX1);

  //------------------------------------- DX1
  if (val_DX1 >= 400) {
    val = val + 1;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- DX2
  if (val_DX2 >= 100) {
    val = val + 2;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- MD1
  if (val_MD1 >= 500) {
    val = val + 4;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- MD2
  if (val_MD2 >= 500) {
    val = val + 8;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- MD3
  if (val_MD3 >= 200) {
    val = val + 16;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- MD4
  if (val_MD4 >= 500) {
    val = val + 32;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- SX2
  if (val_SX2 >= 600) {
    val = val + 64;
  }
  else {
    val = val + 0;
  }
  //------------------------------------- SX1
  if (val_SX1 >= 600) {
    val = val + 128;
  }
  else {
    val = val + 0;
  }
  Serial.write(val);
  val = 0;
}

Ricevitore:

void setup() {

  Serial.begin(115200);
  Serial2.begin(115200);

}

void loop() {

 if (Serial2.available()) {
   unsigned char val = Serial2.read();
   
    Serial.println(val, DEC); 
  }
}

Grazie in anticipo :smiley:

Credo che il problema sia che trasmetti un int e ricevi un char...

fratt: Credo che il problema sia che trasmetti un int e ricevi un char...

Lo credo anch'io

Spiegazione per @Podret Tu in pratica trasmetti un int e fai ricevere all'arduino un char (che è uguale a mezzo int). Quindi l'arduino per ricevere tutto sovrascrive il char e ti dà una lettura errata

Primo consiglio, in fase di sviluppo preferisco i classici 9600 a valori superiori.

Secondo consiglio, sempre in fase di sviluppo, nel tuo caso sullo sketch di trasmissione inserirei un delay(200) giusto per rallentare il loop e apprezzare visivamente cosa succede.

Da quello che ho capito usi i bit della variabile (1,2,4,8,...) per verificare il superamento di un valore in ingresso.

//------------------------------------- SX1
  if (val_SX1 >= 600) {
    val = val + 128;
  }
  else {
    val = val + 0;
  }

Puoi eliminare tutti gli "else" e assegnare "val = 0;" una sola volta all'inizio del loop. Consiglio di settare i bit con l'istruzione "bitSet(x, n)" pronta allo scopo.

Nel trasmettitore sostituirei "Serial.println(val, DEC);" con "Serial.println(val, BIN);" in modo da apprezzare il settaggio dei vari bit. Attenzione che la funzione "BIN" non stampa gli "0" significativi iniziali e pertanto siprodurrà un certo scorrimento del valore.

lelebum: Primo consiglio, in fase di sviluppo preferisco i classici 9600 a valori superiori.

Secondo consiglio, sempre in fase di sviluppo, nel tuo caso sullo sketch di trasmissione inserirei un delay(200) giusto per rallentare il loop e apprezzare visivamente cosa succede.

Da quello che ho capito usi i bit della variabile (1,2,4,8,...) per verificare il superamento di un valore in ingresso.

//------------------------------------- SX1
  if (val_SX1 >= 600) {
    val = val + 128;
  }
  else {
    val = val + 0;
  }

Puoi eliminare tutti gli "else" e assegnare "val = 0;" una sola volta all'inizio del loop. Consiglio di settare i bit con l'istruzione "bitSet(x, n)" pronta allo scopo.

Nel trasmettitore sostituirei "Serial.println(val, DEC);" con "Serial.println(val, BIN);" in modo da apprezzare il settaggio dei vari bit. Attenzione che la funzione "BIN" non stampa gli "0" significativi iniziali e pertanto siprodurrà un certo scorrimento del valore.

Ora provo a fare i dovuti cambiamenti al codice, grazie mille

fratt: Credo che il problema sia che trasmetti un int e ricevi un char...

0xIOSTREAM: Lo credo anch'io

Spiegazione per @Podret Tu in pratica trasmetti un int e fai ricevere all'arduino un char (che è uguale a mezzo int). Quindi l'arduino per ricevere tutto sovrascrive il char e ti dà una lettura errata

Ok, ora provo a correggere il codice, grazie

Seguendo le indicazioni di Podret, sul trasmettitore devi definire "byte val;" o "unsigned char val;"

lelebum: Seguendo le indicazioni di Podret, sul trasmettitore devi definire "byte val;" o "unsigned char val;"

Alla fine ho provato, ma è sempre lo stesso. Ho provato anche a fare una prova, creando un altro .ino per trasmettere una variabile il cui valore cresceva fino a 100 e poi si resettava e il valore lo trasmetteva e riceveva in maniera perfetta (ho provato sia byte che int che unsigned char).

Il problema me lo da proprio quando devo analizzare quello che arriva ai pin analogici, dato che riesco a trasmettere qualsiasi cosa che non abbia a che fare con essi. Mi sa proprio che collegherò i due sensori che occupano i pin del I2C a quelli PWM e farò comunicare le due schede appunto con I2C

Podret: Il problema me lo da proprio quando devo analizzare quello che arriva ai pin analogici, dato che riesco a trasmettere qualsiasi cosa che non abbia a che fare con essi

Il valore ottenuto dai pin analogici (0..1023) è contenuto in una variabile a 16 bit, quindi vanno inviati singolarmente due byte da ricomporre in ricezione nell'ordine giusto per riottenere il valore 16 bit. Su i2c è la stessa cosa.

Per curiosità potresti inviare gli ultimi sketch tx e rx

fratt: Credo che il problema sia che trasmetti un int e ricevi un char...

0xIOSTREAM: Lo credo anch'io

Spiegazione per @Podret Tu in pratica trasmetti un int e fai ricevere all'arduino un char (che è uguale a mezzo int). Quindi l'arduino per ricevere tutto sovrascrive il char e ti dà una lettura errata

lelebum: Per curiosità potresti inviare gli ultimi sketch tx e rx

Claudio_FF: Il valore ottenuto dai pin analogici (0..1023) è contenuto in una variabile a 16 bit, quindi vanno inviati singolarmente due byte da ricomporre in ricezione nell'ordine giusto per riottenere il valore 16 bit. Su i2c è la stessa cosa.

Ok allora, finalmente ho risolto. Questo pomeriggio ho veramente provato di tutto e ho provato pure la I2C e non andava nemmeno quella.

Allora mi son detto: "qua c'è qualcosa che non torna a livello hardware perché il programma è buono e non è quello il problema". A farmelo sospettare è stata una cosa che avevo notato già ieri, ossia che se lasciavo i due arduini attaccati allo stesso pc, riuscivo a ricevere pure i dati derivanti dai sensori IR (anche se entrambe le schede avevano già GND in comune prima di attaccarle al PC).

Tornando a noi: ho provato a togliere la shield dei motori dal mega e già iniziava a darmi qualcosa di diverso in output. Ho infine provato a sostituire il mega con un arduino UNO e riuscivo a ricevere alla perfezione.

Il problema è quindi il seguente: io andavo ad alimentare il mini con l'uscita 5V del mega che in qualche maniera influenzava nella ricezione di quel particolare dato e ho risolto alimentando il mini da una batteria esterna.

Ringrazio tutti quelli che hanno dedicato il loro tempo al mio problema :D

P.S.

Morale della favola per chi, leggendo questo topic si troverà nella mia stessa situazione: se dovete far comunicare due schede arduino NON dovete alimentare una delle due con l'uscita 5V dell'altra. Io come un tonto (essendo ancora un neofita) pensando che due sensori e un mini fossero un carico leggero per l'uscita 5V del mega, ma non è così.

Se metti [Risolto] nel titolo aiuti altri neofiti col tuo stesso problema.

Ciao, P.