Info xbee

La faccio breve, sto costruendo una centralina con un arduino mega + display da 3.5 pollici e un'unità esterna, con adafruit protrinket + sensore dht11 e pir. Tra di loro comunicano grazie a 2 xbee pro serie 2, configurati come coordinator AT (centralina interna) e l'altro come router AT.

Dopo un paio di orette sono riuscito a farli comunicare... ora, sul serial monitor della centralina interna, vedo i dati che elaboro con il modulo esterno, ovvero la temperatura e l'umidità.

Ma tramite xbee c'è la possibilità di trasmettere un dato (tipo sotto forma di variabile come viene storicizzato nella sonda esterna) e non un semplice output seriale? Oppure l'unico modo è elaborare sulla ricevente il serial.print che ricevo dalla trasmittente?

Non so se sono riuscito a spiegarmi... =(

Cioè tu vorresti passargli il dato numerico senza farlo diventare una stringa per poi riconvertirlo ?

terrornoize: Non so se sono riuscito a spiegarmi... =(

Per niente :) In tutti i casi devi vedere gli Xbee come un sostituto di un cavo seriale pertanto sopra ci possono transitare le stesse informazioni. Puoi sia inviare i dati sotto forma di caratteri ascii che sotto forma di valori binari, poi dipende dalla parte che li riceve interpretarli nel corretto modo.

Ok, ho capito. Pensavo che in qualche modo fosse possibile passare direttamente il valore di una variabile senza doverlo scrivere come serial print e poi doverlo ri-elaborare dall'altra parte... thx!

terrornoize: Pensavo che in qualche modo fosse possibile passare direttamente il valore di una variabile senza doverlo scrivere come serial print e poi doverlo ri-elaborare dall'altra parte... thx!

Stai usando una comunicazione seriale, in tutti i casi sei obbligato ad inviare un byte per volta.

In effetti noto che è un aspetto molto dibattuto, una specie di FAQ. La soluzione è abbastanza semplice, si trovano centinaia di tutorial fra cui quello di Leo. Mi chiedo se qualcuno abbia mai realizzato una libreria per passare un INT via seriale, sia in rx che in tx.

Grazie ragazzi, io cerco di googlare il più possibile ma a volte l’inesperienza mi porta a pensare cazzate che neanche nell’internet sono mai state concepite! Fino a 20 giorni fa non sapevo manco cosa fosse arduino o un codice… XD

Questo è il codice del modulo esterno, che:
-invierà i dati della temperatura, umidità e attivazione del pir.
-riceverà il comando per spegnere/accendere la luce o la sirena (attaccati ai relè) tramite dei bottoni posti sulla centralina interna.

#include <dht11.h>

// SecurDuino Home
// Modulo Esterno Balcone

//Settaggio pin del sensore PIR
const int pin_pir=11; // Il pin dov'è attaccato il pir
const int pin_led=13; // Il led per indicare il movimento
boolean alert_pir = false;
boolean status_sirena = false;
boolean status_luce = false;

const int relay1 = 9;
const int relay2 = 10;

byte ric_ext; // per comandi seriali via xbee

char cmd_ext_sirena = 's'; //comando esterno seriale per switchare sirena
char cmd_ext_luce = 'l'; //comando esterno seriale per swithcare luce




//Librerie Sensore DHT11
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 12 // Dove c'è il Sensore DHT11

unsigned const long rit_rilev = 60; // Ritardo tra un rilevamento e l'altro, in secondi
unsigned const long durata_luce= 180; // Durata della luce da accendere tramite reley, in secondi
unsigned long previousMillis_dht = 0; // Store per tenere traccia dei millisecondi passati per calcolare tempo senza interrompere con un delay
unsigned long previousMillis_relay = 0; // Store per tenere traccia dei millisecondi passati per calcolare tempo senza interrompere con un delay


 
void setup(){
  Serial.begin(9600);
  pinMode(pin_pir, INPUT);
  pinMode(pin_led, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  
} // Parentesi fine Setup


 
void loop() {
  
  unsigned long currentMillis = millis(); // Tengo da parte i millis per usi futuri
  
  // Rilevazione Movimento
  if (digitalRead(pin_pir)==1) {
        digitalWrite(pin_led,HIGH);
        previousMillis_relay = currentMillis;
        Serial.println("Rilevato Movimento!");
        alert_pir = true;
        } else {
          digitalWrite(pin_led,LOW); 
        }
  
  // Rilevamento temperatura solo ogni tot secondi settati in rit_rilev
  if ((currentMillis - previousMillis_dht) >= (rit_rilev*1000)) { 
    DHT.read(DHT11_PIN); // per leggere valori sensore DHT11
    Serial.print("T");
    Serial.println(DHT.temperature,1); 
    Serial.print("U");
    Serial.println(DHT.humidity,1);
    previousMillis_dht = currentMillis;
      }
  
  // Attivazione Luce
  if (alert_pir == true) {
      if ((currentMillis - previousMillis_relay) <= (durata_luce*1000)) { 
        digitalWrite(relay1,HIGH);          
        } else {
          digitalWrite(relay1,LOW);
          alert_pir = false;
        }
      }
  
  // Ricezione comandi dall'esterno
  if (Serial.available()) { // Se ci sono dei seriali in arrivo
      ric_ext = Serial.read(); // nel ric_ext c'è il contenuto dei segnali

      // se ricevi il comando, switcha tra una modalità e l'altra
      if (ric_ext == cmd_ext_luce) status_luce =! status_luce; 
      if (ric_ext == cmd_ext_sirena) status_sirena =! status_sirena;
      } 
  
  // Attivazioni Relays da remoto grazie a comandi esterni
  if (status_luce == true) { // se lo status luce è acceso
      digitalWrite(relay1,HIGH); // accendi il relay
      } else { // altrimenti...
        if (alert_pir == false) { //...se non c'è un allame pir attivo...
        digitalWrite(relay1,LOW); //...spegni la luce
        }
      }
      
  if (status_sirena == true) { // se lo status sirena è acceso
      digitalWrite(relay2,HIGH); // accendi la sirena
      } else { // altrimenti...
        digitalWrite(relay2,LOW); //...spegni la sirena
      }
      
  
} // Parentesi Fine Loop

Secondo voi questo approccio che utilizzo per scambiare i dati tra un arduino e l’altro è corretto? o ci sono altri modi?
Chiedo per migliorare, visto che non ho mai nessuno con cui confrontarmi…

Comunque per vostra informazione, dalla centralina al sensore esterno ci saranno si e no 10 metri in linea d’aria, ma con 2 muri belli spessi… per fortuna ho preso la serie pro (boost attivo, serie 2), altrimenti non so se ce la facevo ad inviare i dati, visto che mi perde il 41% del segnale con questa distanza!

paulus1969:
Mi chiedo se qualcuno abbia mai realizzato una libreria per passare un INT via seriale, sia in rx che in tx.

Non esiste per il semplice motivo che si fa con due righe di codice :slight_smile:

TX

int a

Serial.write(a);      // invia byte basso
Serial.write(a>>8);   // invia byte alto

RX

int a

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

astrobeed:

paulus1969:
Mi chiedo se qualcuno abbia mai realizzato una libreria per passare un INT via seriale, sia in rx che in tx.

Non esiste per il semplice motivo che si fa con due righe di codice :slight_smile:

TX

int a

Serial.write(a);      // invia byte basso
Serial.write(a>>8);  // invia byte alto




**RX**


int a

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

Astro perché dovrei fare lo shift ? aaaaaaa ok ho capito giusto mi ero dimenticato che era su 16 bit l’int :wink:

cosa serve il “>>8” o “<<8”? :astonished:

Quindi così facendo potrei mandare direttamente all’arduino il valore della temperatura e dell’umidità senza accrocchi o interpretazioni varie, giusto? :fearful:

terrornoize:
cosa serve il “>>8” o “<<8”? :astonished:

Servono tutti e due, con >>8 sposti il byte alto in quello basso, con <<8 sposti il byte basso in quello alto.

Astro se metto in tx

temperatura = DHT.temperature;
    umidita = DHT.humidity;
    Serial.write(temperatura);
    Serial.write(temperatura>>8); 
    Serial.write(umidita);
    Serial.write(umidita>>8);

e in rx:

if (Serial.available()) {
      temperatura = Serial.read();
      temperatura+= (int)Serial.read()<<8;
      umidita = Serial.read();
      umidita+= (int)Serial.read()<<8;
      Serial.print("-Temperatura :");
      Serial.println(temperatura);
      Serial.print("-% Umidita' :");
      Serial.println(umidita);
      }

In outupt, sul monitor seriale della centralina RX mi viene fuori questo!

-Temperatura :-256
-% Umidita' :-257
-Temperatura :76
-% Umidita' :-257
-Temperatura :-233
-% Umidita' :-257
-Temperatura :-256
-% Umidita' :-257
-Temperatura :78
-% Umidita' :-257
-Temperatura :-233
-% Umidita' :-257
-Temperatura :-256
-% Umidita' :-257
-Temperatura :78
-% Umidita' :-257

:fearful:

Ok, per ora questo approccio è troppo complicato per me… sono andato di :

char cmd_ext_pir = 'P'; // comando input rilevazione pir da xbee
char cmd_ext_temp = 'T'; // comando input temperatura da xbee
char cmd_ext_umid = 'U'; // comando input umidità da xbee

...........

if (Serial.available()) {
      ric_ext = Serial.read();
        
        // Serial.println(ric_ext);
        if (ric_ext == cmd_ext_pir) {
          Serial.println("-- Pir Rilevato");
        }
        if (ric_ext == cmd_ext_temp) {
           Serial.println("-- Temperatura intercettata");
        }
        if (ric_ext == cmd_ext_umid) {
           Serial.println("-- Umidita' intercettata");
        }
          
      }

La centralina mi intercetta le lettere… adesso devo solo capire come inserire i caratteri successivi ricevuti dal modulo esterno in una variabile nella centralina interna. :stuck_out_tongue_closed_eyes:

Signori, è stato un piacere. E' tutto troppo complicato per me, ho perso tutto il pomeriggio inutilmente alla ricerca su come far interpretare ed immagazzinare i dati che ricevo dal modulo esterno.

Grazie a tutti alla prossima... =(

Zio bono dopo 12 ore di parto ci sono riuscito... :blush: Tutto per tirare fuori 2 cacchio di dati... :bua:

void loop() {
  
  while (Serial.available()) {
    delay(10);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }
  
  
  if (readString.length() >0){
      
      Serial.print("-Stringa Ricevuta: ");
      Serial.println(readString); //see what was received
      
      // expect a string like 07002100 containing the two servo positions      
      valore1 = readString.substring(0, 2); //get the first four characters
      valore2 = readString.substring(2, 4); //get the next four characters 
      
      Serial.print("-Valore 1: ");
      Serial.println(valore1);  //print ot serial monitor to see results
      Serial.print("-Valore 2: ");
      Serial.println(valore2);
      
      char carray1[6]; //magic needed to convert string to a number 
      valore1.toCharArray(carray1, sizeof(carray1));
      temperatura = atoi(carray1); 
      
      char carray2[6];
      valore2.toCharArray(carray2, sizeof(carray2));
      umidita = atoi(carray2); 
      
      Serial.print("*Temperatura: ");
      Serial.println(temperatura);
      Serial.print("*Umidita': ");
      Serial.println(umidita);
      
      readString="";
    
  }

Sto sclerando!
Ma perché non riesco a uploadare lo sketch all’arduino mega quando c’è l’xbee attaccato sulla porta rx e tx (pin 0 e 1)?
Non c’è un modo per evitare tutto sto sbattimento? =(

terrornoize: Ma perché non riesco a uploadare lo sketch all'arduino mega quando c'è l'xbee attaccato sulla porta rx e tx (pin 0 e 1)? Non c'è un modo per evitare tutto sto sbattimento? =(

Perché devi usare la serial1 per l'Xbee, il pin 0 e 1 vengono utilizzati per caricare lo sketch se ci colleghi l'Xbee questo ti blocca la comunicazione verso l'USB.

astrobeed:

terrornoize: Ma perché non riesco a uploadare lo sketch all'arduino mega quando c'è l'xbee attaccato sulla porta rx e tx (pin 0 e 1)? Non c'è un modo per evitare tutto sto sbattimento? =(

Perché devi usare la serial1 per l'Xbee, il pin 0 e 1 vengono utilizzati per caricare lo sketch se ci colleghi l'Xbee questo ti blocca la comunicazione verso l'USB.

Perché ho visto che se lo metto sulla 18 e 19, rx1 e tx1 e nello sketch cambio serial.read in serial1.read non legge nulla... cosa sbaglio?

Edit:... che non metto serial1.begin... :sweat_smile: Risolto.

Signori, mi aiutate a capire una cosa che mi sfugge?

Io mi faccio inviare una stringa con questi caratteri:

"HS123456.82;"

H (header) e S (tipo dato) non li considerate, come il punto e virgola finale che ho messo per troncare un dato in confronto all'altro... considerate solo la parte numerica, compresa della virgola, che estrapolo e metto in un'altra stringa (part3), quindi solo "123456.82"

Ora, io per far diventare un float quel pezzo di stringa(part3) che ricevo utilizzo questa codice:

char carray1[6]; 
part3.toCharArray(carray1, sizeof(carray1));
val_temp = atof(carray1); // storicizzo temperatura con la funzione atof per farlo diventare un float

[u]val_temp l'ho definito come float.[/u]

Perché diavolo se gli passo 123456.82 nel val_temp mi mette solo 5 cifre senza virgola...

Arduino riceve: HS123456.82;
Arduino meno punto e virgola: HS123456.82
-- part1 - header: H
-- part2 - tipo valore: S
-- part3: - valore: 123456.82
--val_temp valore numerico: 12345.00

...e se gli passo 234.82 mi tira fuori solo il primo decimale...

Arduino riceve: HS234.82;
Arduino meno punto e virgola: HS234.82
-- part1 - header: H
-- part2 - tipo valore: S
-- part3: - valore: 234.82
--val_temp valore numerico: 234.80

... e se invece gli passo 24.82, il val_temp invece lo interpreta e memorizza correttamente?

Arduino riceve: HS24.82;
Arduino meno punto e virgola: HS24.82
-- part1 - header: H
-- part2 - tipo valore: S
-- part3: - valore: 24.82
--val_temp valore numerico: 24.82

Cosa mi sfugge? :~ =(

terrornoize: Cosa mi sfugge? :~ =(

Che i float sono rappresentati sotto forma di un esponenziale e con solo 32 bit la reale risoluzione è di 6-7 cifre complessive tra parte intera e parte decimale, 123456.78 viene troncato a 123456.00 perché ha troppe cifre.