HC-12 433Mhz receiver aiuto

ciao a tutti,
sono abbastanza inesperto di elettronica, progettazione e quant'altro, ma da quando ho conosciuto arduino e la sua piattaforma mi sto sempre più entusiasmando.
Sto cercando di realizzare un variometro da installare su i miei modelli rc, per poter "sentire" quando l'aereo entra in una termica. Il progetto prevede un sensore di pressione comandato da arduino (nano o digispark attiny85) che invia a terra i valori di pressione rilevati mediante il modulo HC-12.
A terra invece un altro modulo HC-12 riceve i segnali e con un semplice calcolo riesce a restituire indicazioni se l'aereo sale o scende, e la velocità con cui lo fa.
Il modulo trasmittente non ha grosse difficoltà nemmeno per me.......sul modulo ricevente invece ho qualche problemino sulla programmazione....mi spiego meglio:
riesco a ricevere i segnali inviati dalla trasmittente, ma tra un segnale e l'altro la ricevente continua a mandare lo stesso valore, come se rimanesse qualcosa in memoria.....
vi posto il codice che ho scritto per la ricevente (non è la versione finale ovviamente ma è solo per testare il tutto stando comodamente in casa):

//definition of pins

#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float received;

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


void loop() {

if(hc12.available())
{                     
received=hc12.read();              
}
Serial.println(received,3);  //3 for 3 digits after comma
}

devo usare la funzione flush per caso? avete suggerimenti?
grazie mille

grazie mille per la risposta......come immaginavo devo svuotare il buffer.
Ho notato che flush non funziona più...una cosa del genere potrebbe funzionare per svuotare il buffer?

while(Serial.available()){Serial.read();}

mandando un float del tipo 1234,56, la println mi stampa soltanto 1234....pensavo fosse un problema del formato del println, tipo Serial.println(val, format), non di read

per ricevere un float come risolvo?

non so se possa aiutare, ma ecco il codice della trasmittente che manda il valore di un led collegato al pin analogico.

#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
int led = 0;
int mean=30;
float valled;

void setup() {
  
 Serial.begin(9600);
 hc12.begin(9600);
 delay(200);
}


void loop() {
 for (int x=0; x<mean; x++)
{ 
valled += analogRead(led);
delay(5);
}
valled/=mean;


Serial.println(valled);
hc12.write(valled);

}

e se risolvo moltiplicando il mio float per 100 o 1000 a seconda di quanti decimali voglio dopo la virgola e poi ricostruisco il float sulla ricevente dividendo il valore ricevuto per 100 o 1000 potrebbe funzionare?

Grazie mille....stasera provo per vedere se risolvo.

ultimo dubbio.....con questo codice riesco a svuotare il buffer?

while(Serial.available()){Serial.read();}

e nel caso, non si introduce un "ritardo" tra il dato mandato e ricevuto? in altre parole, se quel codice funziona, quanto ci mette a svuotare il buffer?

Secondo me stai facendo un po' di confusione...........

ad esempio nel tuo codice

  if (hc12.available())
  {
    received = hc12.read();
  }
  Serial.println(received, 3); //3 for 3 digits after comma
}

mi pare normale che continui a stampare sempre lo stesso dato ( se non ne arrivano altri ) , visto che la variabile received rimane con quel valore. Prova a spostare il Serial.print dentro alla if e vedrai che stampa solo quello che riceve

Grazie brunello, effettivamente mettendo Serial.print all'interno della if lui stampa solo quello che riceve.....fino a qui risolto.
Ora però ho questo problema.....non riesco a ricevere un numero intero......
mi spiego...per mandare il float con due cifre decimali io lo moltiplico per 100 e mando questo intero...dall'altra parte prendo il numero ricevuto e lo divido per cento per avere il float originale.
Il problema è che sia usando print che write nella parte del sender, poi nel receiver non ottengo mai il medesimo valore.
Ecco il codice del trasmettitore

//definition of pins
//HC-12 messenger send/receive
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
int led = 0;
int mean=100;
float valled;
int valore;

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


void loop() {
  for (int x=0; x<mean; x++)
{ 
valled += analogRead(led);
delay(5);
}
valled/=mean;
valore=valled*100;

Serial.println(valore);
hc12.print(valore);

}

ed ecco quello della ricevente

//definition of pins
//HC-12 messenger send/receive
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float received;
float valore;

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


void loop() {

if(hc12.available())
{                     
received=hc12.read();
valore=received/100;              
Serial.println(valore);
}

}

alla fine quindi il problema è mandare un intero e riceverlo come tale.
Da quanto leggo write manda i dati in bytes, mentre anche se provo con print(valore,DEC) non ottengo comunque ciò che voglio.....

docsavage:
te lo avevo scritto prima.....

la .read() restituisce solo un carattere

tu devi leggere tutti i caratteri che ti arrivano, e convertirli da carattere a intero

inoltre se non metti un separatore di fine riga non sai quando finisce una lettura e ne comincia un'altra.......

settimana scorsa u'altro utente ha avuto lo stesso problema tuo, prova a cercare nei post

casomai ne parliamo dopocena......

Trovato io:
https://forum.arduino.cc/index.php?topic=480118.msg3281906#msg3281906

ma infatti ho provato sia la .read() che la .print(), come mi avevi suggerito.....ma in entrambi i casi il problemi permane.
Mi leggerò il post che mi hai linkato...intanto ti ringrazio per il prezioso aiuto.

eccomi a rompere di nuovo......
ho modificato la trasmittente con il codice per indicare quando inizia e finisce il valore.

#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float val=1234.56;
int ival=0;

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


void loop() {
ival=val*100;  

Serial.println(val);
Serial.println(ival);
hc12.print('#');
hc12.print(val);
hc12.print('*');
delay(10000);

}

qui la prima stranezza, almeno per me. Il .println(val) mi restituisce 1234.56 mentre println mi restituisce 32767.....come è possibile????? :o

dal lato ricevente invece, con questo semplice codice

//definition of pins
//HC-12 messenger send/receive
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float valore;

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


void loop() {
while(hc12.available()){
 valore=hc12.read();
 Serial.println(valore);
 }
}

ottengo questi valori
35.00
49.00
50.00
51.00
52.00
46.00
53.00
54.00
42.00
che a quanto vedo non sono altro che i valori che ho mandato in codice decimale.

ho modificato così il codice della ricevente seguendo un pò ciò che mi hai mandato, e con questo codice

//definition of pins
//HC-12 messenger send/receive
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float valore;
char rx;

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


void loop() {
while(hc12.available()){
    rx = hc12.read();
    if (rx == '#') {
      // trovato inizio
      rx =  hc12.read();
      // OK letta il byte in ingresso
      //test di uscita
        if (rx == '*') {            //questo sarebbe il test di uscita ma siccome siamo nella loop devo impiantare il programma
            Serial.print("trovato termine trasmissione");
            }
           }
        Serial.println(rx);
  }
}

ottengo i singoli caratteri

1
2
3
4
.
5
6
*

ma nessun float....

ho capito la questione del 32mila e passa.....semplicemente mi restituisce il valore più alto che possa stare dentro la variabile int (da -32,768 a 32,767).

scusa la domanda banale.....ma devo sommare il valore decimale o il carattere?

nel codice sul link che mi hai mandato c'è questa riga

valore = valore * 10 + rx - '0';

che non capisco bene.

scusa tanto per la rottura......

quindi se mando un long del tipo 123456
e alla somma decimale di 1,2,3,4,5,6 sottraggo lo 0 riottengo il numero 123456?
quindi con valore=valore+rx-'0' dovrei ottenere il mio long iniziale se ho capito bene
Saresti così gentile da darmi un indizio?

la gestione del punto in un numero 1234.56 la vedo un pò ostica per le mie conoscenze a quest'ora :sob:

porca miseria che gentile! io da solo non sarei mai riuscito a concepire un codice così....ora me lo studio per bene e oggi pomeriggio lo provo e ti faccio sapere se funziona....sono al lavoro e non ho UNO sotto mano
una domanda sola: quando calcoli la parte decimale, ovviamente il valore deve essere un decimo quella parte intera per la prima cifra decimale, ma deve essere un centesimo per la seconda cifra decimale. Se la parte intera la calcoli con
ricevuta = ricevuta * 10 + rx - '0';
per la prima cifra decimale non basterebbe fare
ricevuta = ricevuta + rx - '0';?
te invece hai messo ricevuta = ricevuta + (rx - '0') / 10;

ti ringrazio ancora per la tua gentilezza.....non sarei stato proprio in grado di capire come fare senza il tuo aiuto 8)

//HC-12 messenger send/receiver
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float valore;
float ricevuta = 0;
char rx;
int stato = 0; //0 non in ricezione
//1 in ricezione
//2 in ricezione dopo un punto
float divisore = 1;



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


void loop() {
  if (hc12.available()) {
    // un carattere
    rx = hc12.read();
    // carattere letto
    // se e' un cancelletto
    if (rx == '#') {
      // comincio la lettura
      stato = 1;
      ricevuta = 0; //ricevuta è la variabile di appoggio dove faccio i calcoli

    }
    if (rx == '*') {
      // fine trasmissione
      //aggiurno la variabile valore
      valore = ricevuta;
      stato=0;
      //la stampo
      Serial.println(ricevuta);

    }
    if (rx == '.') {
      // un punto
      //comincio a contare i decimali
      stato = 2;
      divisore = 1;

    }
    if (rx <= '9' && rx >= '0') {
      // una cifra
      if (stato == 1) {
        // parte intera
        ricevuta = ricevuta * 10 + rx - '0';
        // shiftare di una cifra e aggiungere l'ultima


      }
      if (stato == 2) {
        //parte decimale
        divisore = divisore * 10;
        //ogni cifra è un decimo della precedente
        ricevuta = ricevuta + (rx - '0') / divisore;
      }

    }

  }
  else {
    // la cosa non e' bloccante
    // se serve qui il programma puo' far qualcosa

  }
  // ma sopratutto qui, prosegue normalmente, la ricezione non è bloccante

}

con questo funzionaaaaaaaaaaaaaa!!!!!!!!!!!!!!!!mi ritorna 1234.56

SEI UN GRANDE!!!!!!!!!!!GRAZIE MILLEEEEEEE!!!!!

ho provato a generare un long moltiplicando il valore ricevuto per 100, e il tutto funziona solo se metto la moltiplicazione e il print dopo Serial.println(ricevuta); altrimenti se lo metto alla fine mi ritorna sempre 0.....ma il valore ricevuta non dovrebbe essere "costante"?

quindi "valore" è ciò che potrei usare successivamente nel codice mentre "ricevuta" si aggiorna di continuo da quanto ho capito.
Dove dici "// ma sopratutto qui, prosegue normalmente, la ricezione non è bloccante", potrei usare "valore" per fare tutti i calcoli del caso?

Ho provato a modificare il tuo codice per ricevere solo un long, quindi solo un intero, senza problemi di decimali.....secondo le mie poche conoscenze, io lo avrei modificato così

//HC-12 messenger send/receive
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float valore;
float ricevuta = 0;
char rx;
int stato = 0; //0 non in ricezione


long prova;


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


void loop() {
  if (hc12.available()) {
    // un carattere
    rx = hc12.read();
    
    if (rx == '#') {  // carattere letto....se e' un cancelletto
      ricevuta = 0;   //ricevuta è la variabile di appoggio dove faccio i calcoli
    }
    if (rx <= '9' && rx >= '0') {
        ricevuta = ricevuta * 10 + rx - '0';
        
     if (rx == '*') {      // fine trasmissione; aggiurno la variabile valore
      valore = ricevuta;
      //la stampo
      Serial.println(ricevuta);
      }
    }
  }
}

ma non stampa assolutamente nulla. :confused:

quello che dovrei fare mi sembra semplice in teoria.....pian piano sto facendo i singoli pezzi.
Sto cercando di fare un variometro per un aereomodello per accorgermi quando l'aereo è dentro una termica e quindi sale senza motore. La trasmittente all'interno del modello invia il dato della pressione atmosferica (che cambia con l'altezza). La trasmittente a terra invece riceve il valore della pressione, calcola il delta pressione, e se questa è negativa allora l'aereo scende, se è positiva invece l'aereo è dentro una termica ed emette un segnale sonoro (mediante un semplice buzzer) proporzionale al rateo di salita o discesa. Sono riuscito a far funzionare il sensore barometrico, il buzzer e a far variare il suo tono e la sua frequenza in base alla altitudine.....ma ovviamente questi pezzi andranno poi separati nei due componenti.
Quello che sto cercando di fare ora è il codice per la ricevente......per cui una volta ricevuto il valore (il sensore me lo da come float), ma potrei anche mandare un long moltiplicando il float per 100.
Mi servirebbe quindi poi usare questo valore per fare tutto il resto, che dovrei avere già pronto (uso il condizionale perchè ad ogni step incontro problemini...ma si sa che la curva di apprendimento è fatta così :o )

Alla fine ho risolto così :smiley: :smiley: :smiley: :smiley: :smiley:
un piccolo stratagemma senza rompere troppo

//HC-12 messenger receiveer
#include <SoftwareSerial.h>
SoftwareSerial hc12(2, 3); //RX, TX
float valore;
float ricevuta = 0;
char rx;
int stato = 0; //0 non in ricezione
//1 in ricezione
//2 in ricezione dopo un punto
float divisore = 1;
long intero;


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

void loop() {
  if (hc12.available()) {
    // un carattere
    rx = hc12.read();
    // carattere letto
    // se e' un cancelletto
    if (rx == '#') {  // comincio la lettura
      stato = 1;
      ricevuta = 0; //ricevuta è la variabile di appoggio dove faccio i calcoli

    }
    if (rx <= '9' && rx >= '0') { //parte intera
      // una cifra
      if (stato == 1) {
        // parte intera
        ricevuta = ricevuta * 10 + rx - '0';
        // shiftare di una cifra e aggiungere l'ultima
      }
      if (stato == 2) {
        //parte decimale
        divisore = divisore * 10;
        //ogni cifra è un decimo della precedente
        ricevuta = ricevuta + (rx - '0') / divisore;
      }
    }
    if (rx == '.') {  //comincio a contare i decimali
      // un punto
      stato = 2;
      divisore = 1;
    }
    if (rx == '*') {    // fine trasmissione
      //aggiurno la variabile valore
      valore = ricevuta;
      stato=0;
      //la stampo
      Serial.println(ricevuta);
      intero=ricevuta*100;
      Serial.println(intero);
    }
  }

  // ma sopratutto qui, prosegue normalmente, la ricezione non è bloccante

}

un ultima cosa che non sto capendo......per ricevere 3 decimali ho provato a mettere divisore=divisore * 100, ma così non funziona...... :confused:

docsavage:
ti sei incasinato con e chiusure delle if

la graffa che chiude la seconda if (quella che testa se sono cifre)

è messa dopo la terza if (qella dell'asterisco)

te ne accorgi facile

se guardi il programma nellIDE vedi che in corrispondenza di ogni graffa aperta c'è, a sinistra un piccolo -

se ci clicchi sopra ti nasconde tutto quel ramo di programma

se provi sulla seconda if ti accorgi che nasconde anche la terza

prova a metterlo a posto tu

per il resto dovrebbe andare

PS, metti a posto i tipi dati

se vuoi long dichiara long, non float

hai perfettamente ragione....così funziona.......hai un nick appropriato ("savage") :smiley: :smiley: :smiley: :smiley:

scusami...intendevo "savage" come salvatore degli inetti come sono io :smiley:
probabilmente sbaglio io, ma se mando un float 123455,678 (e per stamparlo tale devo dare Serial.print(val,3), dall'altra parte ricevo solo due decimali, arrotondati quindi 12345,68 :confused:

ancora una volta hai ragione!!!!

da qui mi rendo conto quanto abbia da imparare....