Ik mis opeens mijn komma (punt)

Arduino specifieke Software
Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Ik mis opeens mijn komma (punt)

Berichtdoor Gompy » 29 Okt 2019, 00:28

Sorry, maar dit forum kent geen #topicregel, maar ik denk dat het hier staat viewtopic.php?f=20&t=3152&start=70#p26352

Wat betreft de nano, dat staat bovenin de sketch, eerste regel :shock:

Soms gaan jullie zo hard dat ik het amper nog kan volgen.
Een beetje van, je hebt de 6e klas lagere school doorlopen dus kan rekenen en dus snap je trigonometrie en geometrie ook wel.....niet echt dus.
C++ is nooit mijn vak geweest, ik programmeerde vroeger hoofdzakelijk S7 en !Logo Siemens PLC's met de bijbehorende (visuele) programma's, dit is duidelijk een differend cookie voor mij.
Op Google kan ik inderdaad een hoop vinden, maar snappen is wat anders en daar is dit forum toch voor, voor de uitleg en begeleiding ?
Geeft me aub iets meer informatie en tijd om eea te snappen......rennen leer je pas als je kan lopen ;)

Ik heb dit vanuit je voorbeeld en uitleg in de sketch geschreven en zo te zien gaat het voorlopig goed.
Het minnetje komt netjes voor de 00.00 te staan, maar nu loop ik tegen de beperkte regellengte aan.....even zien hoe we dat gaan oplossen.

Code: Alles selecteren
// PRINT LOAD CURRENT LCD ROW 3
  lcd.setCursor(0,2);
  lcd.print(F("LOAD CURRENT:"));
  char temp1[5]; // Enough spaces for 5 numbers
  dtostrf(currentValue, 5 ,2, temp1);
  lcd.print(temp1);
  lcd.setCursor(19,2);
  lcd.print(F("A"));


Persoonlijk vind ik dat ik mijn beperkte kennis al een aardig eind ben gekomen in zeer korte tijd.
Het mag dan nog niet perfect zijn en hele stukken kennis ontbreken me nog, maar dat is nu net waar ik aan wil werken en niet onbelangrijk wil snappen.

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Ik mis opeens mijn komma (punt)

Berichtdoor Koepel » 29 Okt 2019, 01:14

Nu voel het alsof ik klem zit tussen de liftdeuren :o Het is zo benauwend en je houdt geen rekening met de zero-terminator aan het einde van een tekst.

Minimaal 5 tekens plus ruimte voor een zero-terminator = 20 of 40 of zo iets.

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Ik mis opeens mijn komma (punt)

Berichtdoor Gompy » 29 Okt 2019, 11:39

OK, ik heb char temp1[40] gemaakt, want ik vermoed dat je dat bedoelt (?)
Bij de vorige sketch met snprintf kreeg ik ik dan -00.0E, 00.00. of nog vreemdere dingen vandaar dat ik even voorzichtig was.
Het is geen onwil, maar een stukje wat ik nog niet begrijp.....sorry.

Ik vraag me nu nog steeds af waarom het 20 of 40 moet zijn ?
Kan je me dat eens uitleggen of heb je misschien een verwijzing waar ik het kan vinden ?

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Ik mis opeens mijn komma (punt)

Berichtdoor Koepel » 29 Okt 2019, 16:12

Natuurlijk bedoel ik dat.
Ik had nog veel meer voorbeelden in gedachten. Bijvoorbeeld: "Als je wollen sokken koopt, dan ga je ze thuis zeker meteen op 90°C wassen, en vervolgens kan je ze niet gebruiken omdat ze te klein zijn".

In de taal 'C' staat aan het eind van een tekst een zero-terminator. Dat is gewoon een nul. Een nul als letter kan ook weergegeven worden als \0
Dus "Ok" neemt drie tekens in beslag: een 'O', een 'k' en een '\0'.

Wanneer je dit hebt:
Code: Alles selecteren
char buffer1[2];
char buffer2[100];

En je zou 'buffer1' vullen met "Ok", dan overschrijft de '\0' een geheugenplaats buiten het array. Misschien wordt 'buffer2' overschreven, misschien wordt iets anders overschreven.

Wanneer je dingen converteert met snprintf() of strlcpy() of strncpy(), dan hangt het maar net van die functie af of er nog een '\0' achter gezet wordt. Als dat wordt weggelaten omdat er geen ruimte voor is, dan heeft de tekst een open einde.

Zoals ik al schreef: "Minimaal 5 tekens plus ruimte voor een zero-terminator = 20 of 40 of zo iets".
Het maakt niet uit, zolang het maar niet te weinig is, want dan crasht de sketch of gaan er dingen raar doen.
Voor een unsigned long kwam ik op 11 voor de maximale tekstgrootte, een float als tekst kan meer in beslag nemen. Dus 20 is misschien net groot genoeg. Daarom is 40 prima. Als jij liever 33⅓ of 45 of 78 hebt, dan is dat ook prima (geintje natuurlijk, een ⅓ byte rekent zo lastig :lol: ).

Mijn opvatting is om een buffer groot genoeg maken zodat het nooit te klein is. Dus als er op een andere plek in de sketch een foutje staat, dan mag de buffer toch niet overlopen. Aangezien de snprintf() en dtostrf() werken met een minimale breedte, is het gaan uittellen van het aantal tekens altijd verkeerd.

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Ik mis opeens mijn komma (punt)

Berichtdoor Gompy » 29 Okt 2019, 17:47

Nu begin ik het te snappen, wat je in de buffer zet MOET altijd minimaal +1 zijn (?) van het berekende getal.
Je stopt iets in die 2kB van de chip, sluit dat stukje af met een nul en dan kan het volgende stukje achter die nul gezet worden enz tot de buffer vol is......correct ?

Ik heb de sketch aangepast, maar zit met de laatste regels snprintf(temp3,6....enz
Als ik die ook omzet zoals de rest geeft de compiler dus dat de ((interval - (currentMillis-previousMillis))/1000)); te lang is voor dtostrf.
Op zich werkt het nu goed, dus echt erg is het niet, maar het bevreemd me dat ik die "foutmelding" krijg.
In een dtostrf kan je dus geen berekening maken, die zal je ergens elders in de sketch moeten maken en dan ophalen onder "naam".

Code: Alles selecteren
//-------------------------------------------------------
// PRINT VALUES ON LCD - ROW 1 AND 2 FROM PROGRAM
//-------------------------------------------------------
// PRINT LOAD CURRENT LCD ROW 3
  lcd.setCursor(0,2);
  lcd.print(F("LOAD/UNLOAD:"));
  char temp1[40]; // Enough spaces for the numbers -00.00 and 00.00
  dtostrf(currentValue, 6 ,2, temp1);
  lcd.print(temp1);
  lcd.setCursor(19,2);
  lcd.print(F("A"));

  lcd.setCursor(0,3);
  lcd.print(F("TOL:"));
  char temp2[40]; // Enough spaces for the numbers 0 to 50
  dtostrf(tolerance, 2 ,0, temp2);
  lcd.print(temp2);

// PRINT LOOP TIME LCD ROW 4 
  lcd.setCursor(7,3);
  lcd.print(F("LOOP: "));
  char temp3[40]; // Enough spaces for the numbers
  snprintf(temp3,6, "%5d", ((interval - (currentMillis-previousMillis))/1000)); /<<<<<<<<<<<<<<
  lcd.print(temp3);
  lcd.setCursor(19,3);
  lcd.print(F("S"));

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Ik mis opeens mijn komma (punt)

Berichtdoor Koepel » 29 Okt 2019, 20:01

Niet helemaal.
Stel je hebt een array char temp[100], en daar staat "Ok" in. Dan gebruikt je de eerste drie bytes, en de overige 97 bytes worden niet gebruikt.
Stel je hebt drie arrays 100 byte, en in alledrie staat "0.01", dan gebruik je alleen de eerste 5 bytes van elk. Dus totaal 475 bytes worden niet gebruikt.

Dat is de reden dat ik één char buffer[40] zou gebruiken.

Over de sprintf() en snprintf() schreef ik:

"De printf()-functies kijken niet naar het type van de extra parameters. Je moet dan zelf bijhouden welke dingen verwacht worden met %d, %u, %ld en zo, en dan heel secuur precies die dingen op de stack zetten. Zit er ergens een byte fout, dan gaat alles daarna fout. Het is dus geen eenvoudige functie om zomaar even te gebruiken."

en:

"Voor een precies formaat zijn de printf(), snprintf(), etc. functies heel handig. Maar dan moet je wel weten wat je doet".

Je kunt die functies dus niet zomaar gebruiken en hopen dat het goed gaat.

Jij bepaalt wat er op de stack wordt gezet en jij bepaalt het formaat dat gegevens van de stack gebruikt en jij zorgt ervoor dat het allemaal klopt.
Het is misschien eenvoudiger om een unsigned integer (van 16 bit) op de stack te zetten. Daar hoort een "%u" bij.
Dan is het gemakkelijker om dat eerst in een variabele te stoppen.

Code: Alles selecteren
char buffer[40]; // Enough space for the numbers
...
// De 'interval' en 'currentMillis' en 'previousMillis' zijn unsigned long.
// De berekening wordt met unsigned long gedaan.
// Dat wordt geconverteerd naar een unsigned int
unsigned int nog_te_gaan = (unsigned int) ((interval - (currentMillis-previousMillis)) / 1000);
snprintf( buffer, 40, "%5u", nog_te_gaan);

Vorige

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: Google [Bot] en 12 gasten