Go Down

Topic: eigenaardig gedrag met "float" (ESP32) (Read 223 times) previous topic - next topic

YvesD

Jan 14, 2020, 03:54 pm Last Edit: Jan 14, 2020, 05:33 pm by YvesD
Hallo,

ik heb wat problemen met oudere code (2018 - Arduino 1.8.5) in mijn huidige setup (2020 - Arduino 1.8.10)

in mijn code gebruik ik een "struct" om gegevens in op te slaan en uit te lezen. Daar zitten o.a. long & double in.
vroeger kon ik na het verwerken van de gehele getallen, een tijdspanne uitrekenen en dan in een double plaatsen, waarna ik die kom uitschrijven, via Serial.print() en ook opslaan met drie cijfers na het decimaalteken in deze struct{} in de velden met een double ...

Code: [Select]
struct DogTimeSTRUCT {
  bool Fault = OFF;
  String jumpHeight = "cm";
  String TeamName = "Flying Dragons";
  String DogName = "Blank";
  String PassString ="";
  byte rrPos = 0; /* if dog has to rerun, the position it has to come in again */
  byte Position = 0; /* place of the dog on the grid */
  long startTime;
  long raceTime;
  long inTimeIn = 0; /*to store the clock value from the ingoing sensorbreak S1*/
  long inTimeOut = 0; /*to store the clock value from the ingoing sensorbreak S1*/
  long inTime = 0; /*to store the clock value from the ingoing sensorbreak S1*/
  long outTimeIn = 0; /*to store the clock value from the outgoing sensorbreak S1*/
  long outTimeOut = 0; /*to store the clock value from the outgoing sensorbreak S1*/
  long outTime = 0; /*to store the clock value from the outgoing sensorbreak S1*/
  long heatTime = 0; /* to store the trainins value on sensor S3 */
  long passTime = 0;
  long teamNetto = 0;
  long teamPass = 0;
  long teamTime = 0;
  float Pass = 0.000; /*to store the float value of the passing*/
  float Heat = 0.000; /*to store the float value of the heat per dog*/
  float TeamTime = 0.000; /* add each dog's time up since start */
  float TeamNetto = 0.000; /* add each dog's time up since start */
  double TeamPass = 0.000; /* add each dog's time up since start */
}; DogTimeSTRUCT DogTimes[MAX_BUFFER]; /* MAX_BUFFER = [19]


verder in de code verkrijg ik dan een tijd in microseconden uit een interrupt gestuurde sensor (S1), en er is een referentietijd (het moment waarop op start gedrukt word +3000000 microseconden)
Ik kan correct de beide tijden van elkaar aftrekken, en het resultaat is een getal (+ of -)
Daarmee voer ik dan een deling door 1000000.0 uit en geef op dat ik drie cijfers na het decimaalteken wens
Code: [Select]
DogTimes[DogNumber].passTime = DogTimes[DogNumber].inTime - RaceTimeRed;    /* bv -111281 = -0.111 - RaceTimeRed is the startreference +3000000                                                             */
DogTimes[DogNumber].Pass=(float)(DogTimes[DogNumber].inTime - RaceTimeRed)/1000000.0,3; /*     calculate the float value                                                                       */
Serial.println("DogTimes[DogNumber].passTime  : "+String(DogTimes[DogNumber].passTime));
Serial.print("DogTimes[DogNumber].Pass : "); /* the float value of (passTime - RaceTimeRed) */
Serial.println(DogTimes[DogNumber].Pass);


nu blijkt dat deze code compileert, maar slechts 2 cijfers na het decimaalteken geeft, of zelfs een overflow van de float (4.294.... waarde) genereert.
Ik dus even de pedalen kwijt ...
Want zelfs als ik omzet om af te drukken via Serial.print((float)Dogtimes[DogNumber].Pass/1000000.0,3); verkrijg ik niet het gewenste resultaat, waar m'n vroegere omgeving dit wel deed.
Is er iets veranderd met de nieuwste versie van de IDE (compiler?) 1.8.10 t.o.v. 1.8.5 of zie ik nu iets banaal over het hoofd, het kan toch niet zijn dat er zoveel veranderd is dat de code niet meer de juiste uitdraai geeft?
Mijn idee is altijd geweest dat ik de integer kon verwerken tot natuurlijke getallen en opslaan in een double (float) als je de juiste argumenten meegaf
Code: [Select]
long tijd1 = 123456;
double decimaalgetal = 0;
decimaalgetal = (float)(tijd1 - 200000)/1000000.0,3; /* 123456-200000 = -76544 ... /100000.0,3 =>> -0.765

in elk geval ben ik het noorden even kwijt.
Ik heb al aardig wat opgezocht, en ook die opmerkingen doorgenomen met %f0.4 en dergelijke maar daar heb ik het moeilijker mee omdat ik dat niet zo goed begrijp of dat ook werkt om op te slaan in een "struct" of als dat enkel werkt voor uitvoer op het scherm via Serial.x() functies

MVG,
Yves


shooter

eerst maar eens alle declaraties uitbreiden met de type zoals uint8 etc.
paul deelen
shooter@home.nl
making controls with codesys PLC and arduino

YvesD

hey Shooter,

had ik intussen al min of meer gedaan :

Code: [Select]
struct DogTimeSTRUCT {
....
  uint32_t startTime;
  uint32_t raceTime;
  int32_t heatTime = 0;
  int32_t passTime = 0;
  int32_t teamNetto = 0;
  int32_t teamPass = 0;
  int32_t teamTime = 0;
  float Pass = 0;
  float Heat = 0;
  float TeamTime = 0;
  float TeamNetto = 0;
  float TeamPass = 0;
  ....
}; DogTimeSTRUCT DogTimes[MAX_BUFFER]; /* MAX_BUFFER = 19 */


en dan verder zo opgelost :

Code: [Select]
...
DogNumber=1;
DogTimes[DogNumber].passTime = DogTimes[DogNumber].inTime - DogTimes[DogNumber].raceTime;
DogTimes[DogNumber].Pass = DogTimes[DogNumber].passTime/1000000.0;
...
Serial.print("Eerste hond ::: ");
Serial.println(String((float)(DogTimes[DogNumber].Pass)/1.0,3));


en daarmee lijkt het voor nu even opgelost, al betwijfel ik of dit (met mijn beperkte kennis) de properste invulling van het probleem is... :)
het lijkt mij een beetje omslachtig, temeer omdat alle gegevens nog naar een Nextion HMI gezonden worden als tekst...
op het einde van het verhaal ga ik nog berekeningen moeten doen met alle "DogTimes.Pass om zo tot een totaalbeeld te komen, maar ik denk dat ik daar dan wel mee weg geraak met eenvoudige wiskundige oplossingen.

Grtz, en bedankt,
Yves

shooter

het komt door het standaard anders gebruiken van variabelen, zoals 8 bit 16 bit 32 bit etc.
dat zul je dus voor elke berekening moeten kijken of het goed gaat, en dan heb ik het nog niet over afronden etc.

paul deelen
shooter@home.nl
making controls with codesys PLC and arduino

Koepel

Je geeft stukjes code en dat is verwarrend.
https://snippets-r-us.com/

Dit gaat niet:
Code: [Select]
double x = (float) (a - b) / y , 3;
Dat kun je apart proberen.

De ",3" werkt wel als je String() gebruik of als je Serial.println() gebruikt.
https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/

Als je die regel alleen maar gebruikt tijdens het omzetten naar een String, dan kun je beter "String()" gebruiken om duidelijk de conversie aan te geven.

De teksten van de String objecten zitten niet in de struct. Dus als je de struct zou opslaan of doorsturen, dan ontbreken de teksten.

Arduino IDE is gewijzigd naar 1.8.10, maar het is vooral de ESP32 omgeving die flink is aangepakt de afgelopen tijd. Het is onder andere meer compatible met Arduino. Dus als je ergens geheugen overschrijft, of onduidelijke code hebt, dan is het goed mogelijk dat het anders werkt.

Go Up