HC-12 Problemi di decodifica trasmissione

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):

//http://alessiobigini.it/2017/03/20/attiny85/
//AT84
//clock internal 8MhZ

#include <SoftwareSerial.h>
SoftwareSerial mySerial(1, 2); //TX, RX

int dato[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

void setup() {
  mySerial.begin(9600);
}

void loop() {
  for (int i = 0; i < 9 ; i++) {
    mySerial.println(dato[i]);
  }
  delay(100);
}

RX (Arduino Nano):

#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 .....

Grazie + saluti

Enrico

Tu hai bisogno di stabilire un "protocollo" di comunicazione

Ci sono innumerevoli esempi qui sul forum al riguardo

Non te ne cito uno perché fa bene guardare e "capire" più esempi e da lì capire come risolvere le proprie esigenze

Naturalmente prima fa bene averle ben descritte, le esigenze

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:

31 0D 0A 32 0D 0A 33 0D 0A 34 0D 0A 35 0D 0A 36 0D 0A 37 0D 0A 38 0D 0A 39 0D 0A

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)

In realtà queste cose sono già definite e descritte tsnte di quelle volte da fare quasi "senso"

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.

Senza questa fase fare ipotesi è semplicemente inutile

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-

Enrico

Invii le 9 cifre in fila e poi le ricomponi...

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")

Scusate ho inviato la versione sbagliata! (ho cos+ tante prove che ho difficoltà a raccapezzarmi!).
Questa è quella giusta

unsigned long dato;

void loop() { // run over and over
  if (mySerial.available()) {
    dato = mySerial.read();    
  }
  Serial.write(dato);
  delay(500);

e questo il risultato:

123456789
123456789
123456789
123456789

Enrico

Che ha gli stessi problemi della volta scorsa

E che non hai nemmeno provato a identificare

Fallo e progredirai...

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).

Magari é la volta che impari l'ordine...

Seriamente: fare tante prove da andare in confusione é stupido, in particolare se tu per primo te ne rendi conto

Inoltre tutti i consigli che ti sono stati dati stavolta li avevi già avuti negli anni passati, evidentemente hai un problema di organizzazione

Dai, noi siamo qui, ma comincia col dimostrare un po' di impegno

In 75 anni non ci sono riuscite prima mia madre e poi mia moglie .... il mio è un ordine "sparso"!!!

Enrico

1 Like

Non è nostra intenzione fare del lavoro in più e inutile perchè tu sei svogliato

O impari a fare quello che serve oppure ti limiti a fare quello che sai, che non include arduino

Pensavo il forum fosse composto da persone serie e ben disposte (come finora verificato). Ogni altro commento è superfluo.

Enrico

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!

Enrico