Devo trasmettere con HC-12 una serie di 9 numeri da un AT84 a un nano. Dovendo poi "manipolare" questi, ho pensato d'inviarli come un array. Ho provato diverse soluzioni, ma proprio no sono riuscito a raccapezzarmi e trovare una logica nei vari numeri che ricevo!
I programmi utilizzati sono i seguenti:
TX (AT84):
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 2); // TX, Rx
void setup() {
Serial.begin(9600);
while (!Serial) {
; // wait for serial port o connect. Needed for native USB port only
}
mySerial.begin(9600);
}
int dato[9];
void loop() { // run over and over
if (mySerial.available()) {
for (int i = 0; i < 9 ; i++) {
dato[i] = mySerial.read();
// Serial.println(dato[i] - 48);
}
}
Serial.println(dato[3]);
delay(1000);
}
Se qualcuno potesse indirizzarmi su come risolvere il problema .....
Con println non si trasmette il byte dato[i], ma i byte dei caratteri codificati in ASCII corrispondenti alla sua visualizzazione decimale, seguiti dai byte terminatori di linea di valore 13 e 10. Per trasmettere il singolo byte si deve usare Serial.write
Questo è il primo problema. Poi c'è quello della sincronizzazione, cioè far corrispondere il primo byte ricevuto al primo byte trasmesso, in sostanza in ricezione serve un modo per capire qual è il primo byte utile da salvare nell'array.
Poi eventualmente ci sono gli ulteriori problemi di controllo errori e timeout in ricezione.
A quanto già detto, aggiungo l'output in byte (rappresentati in esadecimale) che questo blocco di codice produce sulla software serial con i dati di esempio con cui hai inizializzato l'array è questo:
Come vedi è molto molto diverso da quello che invece ti aspetti, per ogni valore hai: <ASCII code del carattere> <carriage return> <new line> (perché stai usando il println())
Potresti, per esempio, trasmettere un byte di start, la sequenza di cifre e un byte di parità, combinazione dei precedenti. Il ricevitore verifica la parità ed eventualmente chiede la ritrasmissione.
Se il numero di cifre fosse variabile, servirebbe anche un byte di stop.
E rimane sempre il problema di distinguere i byte dei dati da quelli di controllo, per cui (a meno di NON dover mai trasmettere l'intero range 0..255, e poter usare i byte eccedenti come controllo) in un modo o nell'altro dobbiamo aggiungere informazione. Un sistema può essere quello delle sequenze di escape, in modo ad esempio da considerare le sequenze 27 1, 27 27 e 27 4, come: start, 27 e stop. In questo modo il payload può contenere qualsiasi valore (basta trasmettere ogni 27 due volte)
Deve trasmettere "numeri", ha scritto, mi sembra di capire di una cifra, quindi rimangono disponibili tuttti i valori da 10 in poi. Se sono di due cifre, da 100 in poi.
Chiarisco:
La trasmissione è di 9 cifre, così composte:
le prime tre si riferiscono alla temperatura da DHT22,
le seconde tre sono relative all'umidità e
le ultime alla percentuale di carica della batteria.
"Manipolandole" intendo scomporre i tre valori (tutti con due interi ed un decimale) e con un array pensavo di riuscirci semplicemente; la serie di numeri è facilmente ottenibile con questo:
unsigned long dato;
void loop() { // run over and over
while (mySerial.available()) {
dato = mySerial.read();
Serial.write(dato);
}
delay(500);
ma ovviamente non riesco a manipolare il dato e volevo evitare di utilizzare una Stringa.
Inizio a pensare che questa strada sia al di là delle mia capacità; = pausa di riflessione, poi, eventualmente, mi arrendo-
La prima*100 + la seconda*10 + la terza;
la quarta*100 + la quinta*10 + la sesta;
la settima*100 + l'ottava*10 + la nona;
la parità: sommi le 9 cifre e fai %100
un valore di stop maggiore di 99.
già il fatto che stai sparando tipi dato praticamente a caso indica che non è "facilmente"
i primi due errori che saltano alla vista sono che usi una println (che "sporca la trasmissione" con i ritorni a capo, e che non aspetti di aver ricevuto tutto il dato)
a seguire non fai un sincronismo tra trasmissione e ricezione e non hai nulla per separare tra di loro le singole variabili
ci sembrava di ricordare (Fabio è un "caino" in queste cose) che la cosa non fosse nuova, in effetti è un po' che ci stai lavorando intorno, forse vale la pena di fare un nuovo giro di "cerca e capisci" (versione studiata del "copia incolla")
All'inizio davo per scontato che si volessero trasmettere byte (valore da 0 a 255). Se si vogliono trasmettere solo valori da 0 a 9 è molto più semplice, ma la prima cosa da capire è la differenza tra trasmettere un byte o un carattere.
Serial.print(0) trasmette il carattere '0', byte 48
Serial.write(0) trasmette il byte 0
In ricezione si deve essere coerenti, se si trasmettono "caratteri", ai byte ricevuti va tolto 48, altrimenti no.
Indipendentemente da questa scelta, la sincronizzazione è in questo caso molto semplice: prima della sequenza dei nove valori/caratteri si trasmette un altro byte, ad esempio il carattere '#'. In ricezione si devono accumulare i valori in un array, e l'indice va messo a zero quando si riceve il '#' (ecco la sincronizzazione tra trasmettitore e ricevitore).
Corretto, ma allora avevo optato per l'uso di "String" non essendo riuscito a "costruire" un array, ora ho più tempo e spero (a furia di tentativi) di riuscirci!