• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
esp32 ramka modbus rtu hex to float convert
#1
Witam, mam problem z zamianą liczby hex na float, poniżej zamieszczam kod. Oprócz tego wszystko działa. Czy ktoś wie gdzie tkwi błąd?
Kod:
int byte ByteArray[250];
int ByteData[30];

const char msg_reguest[] = {0x01, 0x04, 0x00, 0x08, 0x00, 0x02, 0xf0, 0x09};

void setup() {

  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);

}

void loop() {

delay(200);
int i;
int len=8;

Serial.println("WYSŁANA RAMKA");
for(i = 0 ; i < len ; i++){
      Serial2.write(msg_reguest[i]);
      Serial.print("[");
      Serial.print(i);
      Serial.print("]");
      Serial.print("=");
      Serial.print("Ox");
      Serial.print(String(msg_reguest[i], HEX));     
      Serial.print(" ");
}
len = 0;
Serial.println();
Serial.println();

int a = 0;
while(Serial2.available())
{
ByteArray[a] = Serial2.read();
a++;
}

int b = 0;
String registros;
    Serial.println("ODEBRANA RAMKA");
    for(b = 3 ; b < a-2 ; b++){     
      Serial.print("[");
      Serial.print(b);
      Serial.print("]");
      Serial.print("=");   
      Serial.print("Ox");
      registros =String(ByteArray[b], HEX);  
      Serial.print(registros);
      Serial.print(" ");
      }
       Serial.println();
       Serial.println();

Serial.println(ByteArray[3],DEC);
Serial.println(ByteArray[4],DEC);
Serial.println(ByteArray[5],DEC);
Serial.println(ByteArray[6],DEC);

Serial.println();
Serial.println();

byte hexArray[] = "registros";
  float value;
  memcpy(&value, hexArray, sizeof(hexArray));
  Serial.println(value);

delay(3000);

}
 
Odpowiedź
#2
Nie mam dużego doświadczenia, właściwie to gadam tylko z jednym licznikiem, ale jest to raczej ogólna zasada, że urządzenia nie używają floatów, bo w uC należy tego unikać, bo dane nie były by jednoznaczne, w szczególności jakieś działania na wartościach gdzieś tam chen daleko po przecinku. Np. w moim liczniku na LCD pokazuje przykładową wartość 234.341kWh, ale w pamięci jest to zapisane jako liczba 64bity 234341 Wh i tylko na potrzebę wyświetlania udaje floata. Tak samo inne"floaty" w liczniku to liczby typu 1 , 2 lub 4 czy 8 bajtów, ale całkowite i tylko ich prezentacja jest zależna od kontekstu.
Więc może wystarczy float x = y/1000, a y to będzie jakaś liczba całkowita z tej tablicy. Choć oczywiście lepiej jest robić tak samo, w programie dalej mieć to jako jednoznaczną wartość int32 i tylko prezentować odpowiednio.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
(15-12-2021, 00:25)kaczakat napisał(a): Nie mam dużego doświadczenia, właściwie to gadam tylko z jednym licznikiem, ale jest to raczej ogólna zasada, że urządzenia nie używają floatów, bo w uC należy tego unikać, bo dane nie były by jednoznaczne, w szczególności jakieś działania na wartościach gdzieś tam chen daleko po przecinku. Np. w moim liczniku na LCD pokazuje przykładową wartość 234.341kWh, ale w pamięci jest to zapisane jako liczba 64bity 234341 Wh i tylko na potrzebę wyświetlania udaje floata. Tak samo inne"floaty" w liczniku to liczby typu 1 , 2 lub 4 czy 8 bajtów, ale całkowite i tylko ich prezentacja jest zależna od kontekstu.
Więc może wystarczy float x = y/1000, a y to będzie jakaś liczba całkowita z  tej tablicy. Choć oczywiście lepiej jest robić tak samo, w programie dalej mieć to jako jednoznaczną wartość int32 i tylko prezentować odpowiednio.
 Dzięki kolego za odpowiedź, masz 100% racji że float to nie jest szczęśliwa liczba w C. Można to zrobić (już to wygooglałem) np. tak:
```
float total;
const char modbus_data[] = "47f972f6";
    union {
        uint32_t i;
        float f;
    } data;
    data.i = strtoul(modbus_data, NULL, 16);
    total=data.f;
Serial.println(total, 2);

```
problem tylko w tym, że powyżej jest w tablicy jest String a jak podstawię "Licznik" to dostaję 0, nie działa
 
Odpowiedź
#4
Nie zrozumiałeś przekaz "kaczakat"..
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#5
Float jest niepotrzebny. Zawsze możesz go wyrazić w postaci dwóch intów połączonych kropką.
I myślę, że nad tym się powinieneś zastanowić i to Ci koledzy chcą zasugerować.

Wysłane z mojego POCOPHONE F1 przy użyciu Tapatalka
 
Odpowiedź
#6
Oddalasz się od celu, jak zapiszesz string "47" w tablicy to nie będzie tam siedział bajt 0x47, tylko dwa bajty, jeden dla 4 i drugi dla 7 wg tablicy ASCII, analogicznie 47f972f6 to bajt dla każdego znaku, czyli 64bity a nie spodziewana wartość 4 bajtowa (32bity) dla int32 lub float.
Możesz użyć zwykłego kalkulatora z WIN w trybie programisty, przepisać te bajty (jeśli odbierasz to jako literki i zapisujesz do tablicy char to drukujesz 4 hexy z tablicy jako hexy) i zamienić na postać dziesiętną by przekonać się oczętami, czy jest to zapis zmiennej całkowitej czy float. Float ma inną konstrukcję, część bitów odpowiada za mantysę, reszta za exponent, można tak wyrażać olbrzymie liczby, ale tylko w przybliżeniu. Int32 przedstawia dokładną i jednoznaczną wartość.
Jak w twoich działaniach napotykasz na błędy, traktując zapis 4 bajtów jak float to pewnie nie jest to float.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości