Splitta seriell ASCII data och konvertera till dec

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
swapper
Inlägg: 1075
Blev medlem: 14 augusti 2012, 23:18:15
Ort: Helsingborg

Splitta seriell ASCII data och konvertera till dec

Inlägg av swapper »

Hej!
Har försökt hitta några exempel på följande problem men inte hittat något som tar mig tillräckligt långt med mina begränsade kod kunskaper.

Problemet är att konvertera inkommande seriell data till en arduino (ESP8266 IDE) som kommer till den i formatet "0A14001F0000015D" det är hex skickat som ASCII.
Den intressanta datan i den är de sista 4 byten (om jag benämner det rätt)

Sen behöver den datan konverteras till dec och delas med 10 (flytta kommat)
015D = 349 = 34,9V

Målet är att kunna läsa av diverse värden så som spänning/strömstyrka m.m. och visa på lämpligt ställe beroende på applikation.

Detta är lite av en fortsättning på meckande jag gjort med servomotorer tidigare:
http://elektronikforumet.com/forum/view ... lit=+servo

Bifogat är manualen för RS485 protokollet, dock stämmer det inte 100% med mina servon men alla register stämmer.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Splitta seriell ASCII data och konvertera till dec

Inlägg av sodjan »

> Den intressanta datan i den är de sista 4 byten (om jag benämner det rätt)

Jag skulle kalla det för de sista 4 tecknen, eftersom det är en textsträng.
De fyra sista tecknen representerar ju de *2* sista byten, om man ska vara korrekt.

> Sen behöver den datan konverteras till dec och delas med 10 (flytta kommat)
> 015D = 349 = 34,9V

Först så är ju alla värden alltid samtidigt i hex, dec, binärt eller vad du vill,
det handlar enbart om hur värdet representeras i skrift när vi läser det. Det
är inte olika värden! Din Arduino räknar dessutom alltid binärt.

Men du har alltså t.ex textsträngen "015D". Först så vill du sannolikt göra det
till ett numeriskt värde. Det blir alltså:

0*4096 + 1*256 + 5*16 + 13*1 = 256+80+14 = 349. ("D" är ju = 13 decimalt)
Allt detta är enkel matematik för processorn (eftersom det är jämna potenser av två, det blir
bara enkla skift operationer o.s.v.) och det kanske finns färdiga Arduino funktioner för det...

Nästa steg är att konvertera värdet till en ASCII representation. Det finns säkert färdiga funktioner
för det också, men i princip så handlar det om att plocka ut antalet hundratal, antalet tiotal och
antal ental, och sedan konvertera dessa antal till ASCII och bilda strängen "349". En vanlig metod
(om man inte har färdiga rutiner) är att räkna hur många gånger 100 kan dras bort innan det blir
mindre än 0, det är hundratals siffran. Sedan samma sak men tiotal. Det som då blir kvar är entalen.

Någon division med 10 behöver du självklart inte göra! Det är bara att stoppa in ett decimalkomma
i strängen och få "34,9". Det handlar enbart om *presentation" av värdet i alla fall, inte om värdet i sig.
Användarvisningsbild
Icecap
Inlägg: 26148
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Splitta seriell ASCII data och konvertera till dec

Inlägg av Icecap »

Generellt är det enkelt att omvandla inkommande data från tecken till värde.

Vanligt är att omvandla hexadecimala tal där man kan göra följande:
1: Deklarera en variabel som är stor nog att hålla slutresultatet. Kallar den "Result" här.
2: Nollställ Result.
3: Pek på första tecken som ska omvandlas.
4: Result *= 16;
5: Om tecknet är '0'-'9': Result += Tecken - '0'; Om tecken är 'A'-'F': Result += Tecken - 'A' + 10;
6: Gå till 4 om fler tecken ska omvandlas.

Alltså ska strängen tas emot och sparas i en buffer (eller likgiltiga tecken räknas bort) varefter man kör resten genom den rutin.

Jag brukar göra en rutin för att omvandla där jag anger antal tecken som ska omvandlas och pekar på buffern de finns i.
Användarvisningsbild
swapper
Inlägg: 1075
Blev medlem: 14 augusti 2012, 23:18:15
Ort: Helsingborg

Re: Splitta seriell ASCII data och konvertera till dec

Inlägg av swapper »

Efter lite testande och hjälp ifrån jobbarkompis som inte gav upp så fick vi fram fungerande kod.
Totalt ooptimal säkert men det fungerar :)

Kod: Markera allt

  String hexvalue;
  String hexvaluevolts;
  char hexvaluevolts2;
  char hexchararray[5];
  float voltage;
  

delay (2000);
     rs485.print("0214001F00000000"); //Request voltage in servopowerstage
     rs485.print('\r');//Send CR
     hexvalue = rs485.readString();
     hexvaluevolts = hexvalue.substring(12); 
     hexvaluevolts.toCharArray(hexchararray,5);
     voltage = strtol(hexchararray, NULL, 16); 
     Serial.print("Voltage: ");
     Serial.print(voltage/10);
     Serial.println("V"); 

Förslag på förenklingar/förbättringar mottages tacksamt.
Användarvisningsbild
jesse
Inlägg: 9235
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Splitta seriell ASCII data och konvertera till dec

Inlägg av jesse »

Det där var väl utmärkt.

>Förslag på förenklingar/förbättringar mottages tacksamt.
Förbättra hur? Det fungerar ju.

Sodjan har ju redan nämnt en förbättring, om man vill slippa använda float (som ofta tar mycket processortid, minne och program-minne att hantera):
Sodjan skrev:Någon division med 10 behöver du självklart inte göra! Det är bara att stoppa in ett decimalkomma
i strängen och få "34,9".
Men det fungarar sannolikt inte så bra med Arduinos Serial.print()...
Användarvisningsbild
Icecap
Inlägg: 26148
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Splitta seriell ASCII data och konvertera till dec

Inlägg av Icecap »

sprintf(Buffer, "bla bla %u,%u", Value / 10, Value % 10);
Ger "bla bla 34,9" printat i Buffer om Value är 349.

Serial.print(Buffer); // skickar sedan ut det på den seriella porten.
Skriv svar