"RISOLTO" trasferire un unsigned int via seriale

salve a tutti.

Come faccio a trasferire il valore di un unsigned int tra due arduini via seriale?

ho un hc-sr04 collegato ad un arduino uno che mi tira fuori un tempo in millisecondi che viene messo in una unsigned int, e vorrei trasferire (per ora a cavo, poi con xbee) questo valore ad un altro arduino micro dove collegherò un display.

googolando mi sembra di aver capito di dovere mettere il dato in una striga, codificarla da una parte e decodificarla dall’altra ma non capisco come fare dato che il contenuto della variabile è un numero che può essere da una fino a sette cifre.

ho provato a fare cosi… senza successo!

TX

#include <SoftwareSerial.h>
#include <NewPing.h>
 
#define trigger_Port 9
#define echo_Port 8

SoftwareSerial Seriale(4,7); //RX,TX

unsigned int durata;
NewPing sonar(trigger_Port, echo_Port); 

void setup() 
{
  Serial.begin(9600);
  Seriale.begin(9600);
}

void loop() {
  
   delay(100);
  
 durata = sonar.ping_median(5);
  //Seriale.print(durata);
  //Seriale.print(",");
 Seriale.write(durata);      // invia byte basso
 Seriale.write(durata>>8);   // invia byte alto 
  
  Serial.println(durata);
  delay (1000);
}

RX

#include <SoftwareSerial.h>
SoftwareSerial Seriale(8,9); //RX,TX

int input;
void setup() 
{
  Serial.begin(9600);
  Seriale.begin(9600);
}

void loop() 
{
  if(Seriale.available())
  {
    //input=Seriale.read();
input = Seriale.read();          // riceve byte basso
input+= (int)Seriale.read()<<8;  // riceve byte alto
      Serial.println(input);

  }
}

ho usato Software Serial per debug e perchè una volta che riesco a vedere il valore della variabile nel monitor seriale del micro, vorrei invece collegare un serial 7seg display.

cosa sbaglio?

è giusto cominciare da qui se poi voglio arrivare alla trasmissione con gli xbee?

grazie

Mauro

Io modificherei le due write() così…

Seriale.write(lowByte(durata));  // trasmette il byte meno significativo
Seriale.write(highByte(durata)); // trasmette il byte più significativo

… le due funzioni lowByte ed highByte le trovi nel reference nella parte Bits and Bytes.

Ah … un altra cosa, quando vai a leggere in ricezione, chi ti assicura che siano arrivati DUE bytes ? Magari fare:

if (Seriale.available() > 1) { … }

… ti assicura che almeno DUE byte ci sono, altrimente rischi, data la velocità della MCU, che tu vai a leggere un qualche cosa che NON è ancora arrivato. :wink:

Guglielmo

Della libreria Serial, ci sono diverse funzioni, non solo Serial.read(). Si può leggere anche valori stringa, float e byte.

Si potrebbe quindi usare la funzione readBytes() o readBytesUntil(). Nel secondo caso, si dovrebbe mettere un ulteriore byte per la terminazione della trasmissione oppure quanti bytes aspettare.

giusto così per farlo

void sex_write(void* s, size_t sz)
{
    uint8_t* b = (uint8_t*)s;
    while( sz-->0 ) Serial.write(*b++);
}

int sex_read(void* d, size_t sz)
{
    if (Serial.available() < sz ) return 0;
    uint8_t* b = (uint8_t*)d;
    while( sz-->0 ) *d++=Serial.read();
    return 1;
}

se funziona la userei per inviare così

...
int dato = 1234;
sex_write(&dato, sizeof dato);

e per ricevere

int recv;
if ( sex_read(&recv, sizeof recv) )
{
    ....
}

se si vuole ricevere in maniera bloccante

int recv;
while (!sex_read(&recv,sizeof recv));
...

Questa funzione è meglio. Dato che si può implementare anche con una SoftSerial. Solo che è hardcodato il tipo di seriale.

void sex_fwrite(Stream* f, void* s, size_t sz)
{
    uint8_t* b = (uint8_t*)s;
    while( sz-->0 ) f->write(*b++);
}

int sex_fread(Stream* f, void* d, size_t sz)
{
    if (f->available() < sz ) return 0;
    uint8_t* b = (uint8_t*)d;
    while( sz-->0 ) *d++=f->read();
    return 1;
}
...
int dato = 1234;
sex_write(&Serial, &dato, sizeof dato);
int recv;
if ( sex_read(&Serial, &recv, sizeof recv) )
{
    ....
}

dovrebbe andare

[edit]corretto[/edit]
[edit]tornato a correggere[/edit]

è comunque possibile non reinventare la ruota.

int dato=1234;
Serial.write((uint8_t*)&dato, sizeof dato);
int recv;
if ( Serial.available() >= sizeof recv)
{
    Serial.readBytes((uint8_t*)&recv, sizeof recv);
}

Bravo, con la Serial c'è. Ho notato che, invece, la SoftwareSerial non ha le stesse funzioni della Serial, mio malgrado.

tutte le funzioni che ho usato fanno parte della classe Stream, di cui fanno parte sia Serial che la softwareSerial.

A volte mi viene da chiedervi … MA CHE RAZZA DI RISPOSTE DATE ? ? ? :o :o :o

Ma l’avete letta la presentazione di chi ha posto la domanda ? ? ? :o

cepics:
… mi piace smanettare per hobbie con elettronica e programmazione. le mie conoscenze sono praticamente pari allo zero ma realizzo semplici progetti seguendo tutorial, mescolando sketch e bruciando componenti.

e vi paiono i vostri post adatti alla preparazione di questa persona ? ? ?

Guglielmo

grazie a tutti e soprattutto a Guglielmo!!!! :slight_smile: :slight_smile: :slight_smile:

sono riuscito a farli parlare la stessa lingua via cavo!!!

ora mi scontro con la trasmissione xbee, tra una settimana se non avrò fatto progressi mi troverò costretto ad importunarvi di nuovo.

una domandina così al volo gia che ci sono ce l'avrei, dato che sulla rete trovo pareri discordanti:

devo ridurre con delle resistenze il tx di arduino prima di entrare in din di xbee (no shield) e viceversa?

grazie ancora.

Se ben ricordo gli Xbee lavorano a 3.3V ...
... devi controllare sulla documentazione del prodotto che hai acquistato, ma se è così, SI, devi assolutamente mettere un partitore resistivo sul collegamento TX di Arduino ---> RX del Xbee in modo che al Xbee NON arrivino più di 3.3V.

Oppure puoi utilizzare dei "convertitori di livello" già belli che fatti che trovi sotto forma di piccole schedine.

Guglielmo

RISOLTO!!! funziona anche con xbee

TX

#include <SoftwareSerial.h>
#include <NewPing.h>
 
#define trigger_Port 9
#define echo_Port 8

SoftwareSerial Seriale(4,7); //RX,TX

unsigned int durata;
NewPing sonar(trigger_Port, echo_Port); 

void setup() 
{
  Serial.begin(9600);
  Seriale.begin(9600);
}

void loop() {
  
   delay(100);
  
 durata = sonar.ping_median(5);
Seriale.write(lowByte(durata));  // trasmette il byte meno significativo
Seriale.write(highByte(durata)); // trasmette il byte più significativo
  
  Serial.println(durata);

}

RX

#include <SoftwareSerial.h>
SoftwareSerial Seriale(8,9); //RX,TX

int input;
void setup() 
{
  Serial.begin(9600);
  Seriale.begin(9600);
}

void loop() 
{
if (Seriale.available() > 1)
  {
input = Seriale.read();          // riceve byte basso
input+= (int)Seriale.read()<<8;  // riceve byte alto
      //Serial.println(input);

  }
  delay(100);
}

tutto ciò è bellissimo!!!

Bene, adesso, dopo averlo fatto così,
puoi anche dare un'occhiata qui: parseint

paulus1969:
Bene, adesso, dopo averlo fatto così,
puoi anche dare un'occhiata qui: parseint

La parseInt si aspetta una stringa numerica, in questo caso viene inviato il numero "reale" senza la coversione a stringa.

Certo, dovrebbe regolarsi di conseguenza anche nell'invio.

paulus1969:
Bene, adesso, dopo averlo fatto così,
puoi anche dare un’occhiata qui: parseint

interessante la parseint… (provvederò)

cmq oggi non vuole funzionare …
sembra ci sia un problema di trasmissione/ricezione
funzionava tutto bene prima di instalare i driver per cinoduino (CH340).

gli xbee chattano ancora bene in xctu

il monitor seriale del rx non da nulla e quando lo apro il display si illumina per un attimo

os x lion

tx

hc-sr04
arduino micro
xbee s1 end device (no shield)

#include <SoftwareSerial.h>
#include <NewPing.h>

#define trigger_Port 9
#define echo_Port 8

SoftwareSerial Seriale(4,7); //RX,TX

unsigned int durata;
NewPing sonar(trigger_Port, echo_Port); 

void setup() 
{
  Serial.begin(9600);
  Seriale.begin(9600);
}

void loop() {

  delay(100);

  durata = sonar.ping_median(5);
  Seriale.write(lowByte(durata));  // trasmette il byte meno significativo
  Seriale.write(highByte(durata)); // trasmette il byte più significativo

  Serial.println(durata);

}

rx

xbee s1 coordinator (no shield)
arduino uno (il guaio è cominciato quando l’ho voluto sostituire con il cino)
serial four digit 7 seg display (sparkfun)
potenziometro

#include <SoftwareSerial.h>
SoftwareSerial Serial7Segment(8,9); //RX pin, TX pin

long cm;
int input;

int sensorPin = A0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor
byte x;


void setup() 
{
  Serial.begin(9600);


  Serial7Segment.begin(9600); //Talk to the Serial7Segment at 9600 bps
  Serial7Segment.write('v'); //Reset the display - this forces the cursor to return to the beginning of the display
  Serial7Segment.print("DAJE");
  delay(5000);
  Serial7Segment.write('v'); //Reset the display - this forces the cursor to return to the beginning of the display

}

void loop() 
{
  if (Serial.available() > 1)
  {

    sensorValue = analogRead(sensorPin);
    x = sensorValue / 4;

    input = Serial.read();          // riceve byte basso
    input+= (int)Serial.read()<<8;  // riceve byte alto
    Serial.println(input);

    cm = ((input/2) / 29.1);

    Serial7Segment.write(0x7A);  // Brightness control command
    Serial7Segment.write((byte) x);  // 0 is dimmest, 255 is brightest

    Serial7Segment.write(0x79);  // Decimal, colon, apostrophe control command
    Serial7Segment.write(0x01);
    Serial7Segment.print(cm);

  }
  delay(100);
}

il display si inizializza (mi dice “DAJE”), poi si spegne e fa un lampo quando lancio il serial monitor

idee?

ciao

Mmmm ... ma hai installato i driver per "macOS Sierra" su "OS X Lion" ? O ... dove hai preso quelli per Lion ?

Guglielmo

gpb01:
Mmmm ... ma hai installato i driver per "macOS Sierra" su "OS X Lion" ? O ... dove hai preso quelli per Lion ?

Guglielmo

dal tuo link

dice: "We released our new Mac drivers package, which includes the drivers for the FTDI chip for Yosemite. No more searching, downloading and installing is needed, and furthermore they work with all OSX for Mac. ....... We talked to WCH, the manufacturer of CH340G chip which is a great new alternative to FTDI, and we created a new driver that supports the CH340G chip on Yosemite (a world first!) and all OSX for Mac."

Aha ... ok ... quindi dovrebbe andare.

Se apri l'IDE di Arduino, vedi tra le porte la porta del CH340 ? Se SI ... allora non è un problema di driver ... ::slight_smile:

Guglielmo