Sari la conținut
ELFORUM - Forumul electronistilor

Comunicatie seriala, variabila floating point


alibiduda

Postări Recomandate

Va salut. Sunt incepator in domeniul progarmarii arduino si intampin o problema in legatura cu comunicatia seriala intre 2 arduino.

La prima vedere ce vreau eu sa fac e simplu: un adruino nano masoara temperatura printr-un senzor DS18B20 si o trimite via convertoare RS485 pe o distanta de 15m catre al 2-lea arduino nano care afisaza temperatura pe un ecran LCD 16x2.

Din cata informatie am gasit reiese ca nu se poate trimite o valoare floating point direct prin serial atunci intrebarea mea este care ar fi cea mai buna metoda sa prelucrez valoarea temperaturii pentru a o putea trimite.

 

Multumesc.

Link spre comentariu
  • Răspunsuri 22
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Poti trimite un string pe care cel de al doilea uC doar sa-l afiseze.
Depinde si de protocolul soft pentru comunicatia seriala.
Posteaza cum te-ai gandit sa comunici intre cele doua arduino.

Link spre comentariu

Il "spargi" in 4 octeti si il trimiti:

 

void sendFloat(float f)
{   
  byte * b = (byte *) &f;   
  Serial.write(b[0]);   
  Serial.write(b[1]);   
  Serial.write(b[2]);   
  Serial.write(b[3]);   
  // sau vezi daca nu merge Serial.write (b, 4);
  Serial.flush();   
  return; }

 

Link spre comentariu

Din documentatia de la arduino.cc

 

Citat

Serial.print()

Description

Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit. Floats are similarly printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character. Characters and strings are sent as is. For example-

  • Serial.print(78) gives "78"

  • Serial.print(1.23456) gives "1.23"

 

Da-mi place si ideea lu' merck.

Editat de Liviu M
Link spre comentariu

Va multumesc pentru raspunsuri.

In prima incercare am copiat un sketch in care inmultea valoarea temperaturii cu 100 apoi despartea rezultatul in 2 byte prin impartire cu rest la 255. Primul byte continea valoarea divizata si al 2-lea byte restul. La celalat capat se se asamba matematic inpoi si se afisa rezultatul. Metoda functiona pt o perioada de timp (1- 2 minute) dupa care afia valori negative de genul -130 grade. Nu stiu de ce dar comunnicatia devine instabila. Pentru a testa comunicatia am incercat sa trimit direct valoarea inmutita cu 100. Functioneaza ok dar dupa scurt timp pe LCD se afiseaza valori total aiurea desi informatia receptionata e corecta (testata prin serial cu calculatorul). Pentru conexiunea cu modulele RS485 folosesc SoftwareSerial iar pentru debugging portul serial nativ.

O sa incerc imediat sugestiile de mai sus dar inca nu am inteles pe deplin limbajul arduino si probabil o sa dureze putin pana revin cu rezultatele.

 

@Liviu.Mihaiu si @Liviu M am incercat direct cu Serial.print() temperatura trimisa 24,06  se receptioneaza valori aletaorii intre 46 si 52.

@merck m-am gantit la metoda asta dar nu stiam cum sa o transpun in progam. Mulumesc o sa incerc.

@mihaicozac o chestie foarte eleganta, nu stiam ca exista asa ceva. Mulumesc o sa incerc.

Link spre comentariu

Data viitoare cand ceri ajutorul da toate informatiile pe care le poti da, in special ce ai incercat deja si n-a mers (si ce n-a mers). Scutim cu totii timp si tocit aiurea la tastaturi.

Dupa parerea mea, nu e o problema cu "codificarea", e o problema de timing/sincronizare intre cele doua module, mai ales ca folosesti porturile soft.

Prima incercare ar fi sa bagi un delay intre transmisia caracterelor (sugerez prima varianta pe care ai incercat-o, cea cu 2 octeti). Eventual implemetezi si un "protocol", adica trimiti un octet de start (sa zicem caracterul 'A'), numarul, un octet de stop (sa zicem 'Z') si la receptie consideri date valide doar ce se potriveste "protocolului". Cand astepti date noi, arunci tot ce nu e start, dupa ce primesti start salvezi (si numeri) tot ce urmaza pana la stop, cand vine stop verifici ca numarul de octeti primiti e ce trebuie (daca nu arunci si o iei de la capat) si faci ce trebuie mai departe cu datele.

Daca nici asa nu merge, las pe altcineva, eu nu mai am alte idei. :)

Link spre comentariu

Ar trebui verificată şi valoarea de la Serial.timeout(), care implicit este de 1000ms. Dacă ai rata de transmitere a datelor mai mică de valoarea asta pot apărea erori de interpretare a datelor. Dacă sunt de trimis 4 bytes mulţi folosesc metoda asta:

if (Serial.available() > 3) {// ceva cu pointeri sau arii pt. refacerea variabilei}
// sau mai rau  if (Serial.available() == 4) {ca mai sus}

Dacă apare o eroare la recepţie din cauză de întreruperi sau alt motiv bufferul rămâne cu 3 sau mai puţini bytes valizi şi apoi vine următoarea rafală de 4 bytes din care se iau în considerare doar primii până la completarea unei serii de 4 cu octeţii din buffer după care se face citirea şi prelucrarea, iar de aici se dă peste cap tot.

Deci dacă trimiţi rafalele la interval de 500ms valoarea lui Serial.timeout() trebuie să fie mai mică, undeva între 100-200ms. Dacă rata de transmitere este mai mare de 1 secundă atunci ce am scris eu nu mai este valabil.

Link spre comentariu

Eu nu am știut de librăria de care a scris mihaicozac, și îi mulțumesc cu această ocazie, e interesantă. Eu am făcut astfel:

Valorile float la care mă interesa o singură zecimală le-am înmulțit cu 10 ca să am variabile int și nu float.

Le-am trimis pe serială cu Serial.print. Dar la ultimul int trimis am folosit Serial.println.

La recepție băgam datele întro matrice până recepționam acel '\n'

Trimit astfel fără erori 3 temperaturi, o tensiune de baterie a unui UPS și o valoare de presiune de la un arduino nano programat ca termostat la centrala pe lemne, către un esp-01 programat ca web server ca să pot vedea datele online.

Link spre comentariu

Eu tot nu pricep, de ce trebuie sa ma scarpin cu mana stanga la urechea dreapta! Tot ce ati insirat aici poate fi executat in modulul de receptie, nu transmis de modulul de transmisie (asta ca tot incerc sa evit repetitia!). Ai 12-16 biti brut, ii transmiti pe seriala cu evidentierea inceputului si sfarsitului de date si la receptie se face prelucrarea in orice chip isi doreste utilizatorul final!

Link spre comentariu

Daca se posteaza codul cu problema, ar putea fi identificat mai usor cauza valorilor afisate eronat. Cauze ar putea de la citirea ADC prea rapida si incetinita de comunicatie de trimis, pana la primirea prea repede de date seriala si procesare lenta, sau anumite accese de memorie partiale, precum suprascriere date de trimis din intrerupere, in timp ce se transmit, byte cu byte, in bucla principala.

Legat de transmisia unui float, cel mai elegant e cu un tip union format de un float si 4 byte array. Conversia se face automat, atat la trimis cat si la receptie, folosind acelasi tip de date. Optim cred ca e mai usor de trimis doar doi octeti de ADC, cum au recomandat si alti colegi.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări