Gleicher Code mit unterschiedlichem Output

Servus zusammen im Forum. Hab einiges mit Arduinos und ESP´s gemacht bin aber weit weg von routiniert. Bis jetzt konnte ich Fragenstellungen und Probleme die aufgetreten sind mittels Suche in Netz lösen. Hier komme ich aber nicht weiter. Verwende einen Arduino UNO R4 Wifi. Habe den Code auch auf einem Lilygo A7670 G (arbeitet mit einem ESP32) getestet mit ähnlichem Ergebnis. Arudino IDE 2.3.4.
Ziel des Code soll es sein ein Integer in eine formatierte Zeichenfolge zu bringen und diese in einem char array abzulegen. Konkret wird in der Variablen NWhour der Stundenwert (zb 6) als Integer gespeichert und soll als 06 im array gespeichert werden. Jener Teil der die Stunden behandelt funktoniert wie erwartet, wenn Teil 2 auskommentiert ist. Der zweite Teil gibt einen anderen Output. Code und Beispieloutput anbei. Was mache ich falsch bzw habe ich etwas übersehen ?

// Variablen um die Zeit zu speichern
  int   NWyear    = 0;         
  int   NWmonth   = 0;
  int   NWday     = 0;
  int   NWhour    = 0;
  int   NWmin     = 0;
  int   NWsec     = 0;
  float NWtimezone = 0;
//array in dem Stunden bzw Minuten formatiert abgelegt werden
  char GSMhour[2];
  char GSMminuten[2];

void setup() {
  Serial.begin(115200);
}

void loop() {
  NWmin=random(0,59);       // zu testzwecken wird ein Int ausgewählt
  int checkmin = NWmin;     // speichert den Zufalls wert

  NWhour=random(0,23);
  int checkhour = NWhour;

// Formating hours: Teil 1
  if (NWhour<10){               //Erste Bedingung trifft zu wenn die Stunden kleiner als 10
    GSMhour[0]= '0';            //zb NWhour == 7  =>  im array soll 07 abgelegt werden
    GSMhour[1]= NWhour+'0';     // +'0' um einen 0 terminated char zu erzeugen
  }
  else if (NWhour>9) {            //zb NWhour ==12 => im array als 12 abeglegt
    GSMhour[0]= (NWhour/10)+'0';
    GSMhour[1]= (NWhour%10)+'0';
  }
  else {
    GSMhour[0]= '0';            //Wenn NWhour == 0 im array 00 ablegen
    GSMhour[1]= '0';            
  }
//*********Zum testen hier auskommentieren
// Formating min: Teil 2            //Dieser Teil gibt einen anderen Output obwohl kopiert
  if (NWmin<10){
    GSMminuten[0]= '0';
    GSMminuten[1]= NWmin+'0';
  }
  else if (NWmin>9) {
    GSMminuten[0]= (NWmin/10)+'0';
    GSMminuten[1]= (NWmin%10)+'0';
  }
  else {
    GSMminuten[0]= '0';
    GSMminuten[1]= '0'; 
  }
//********auskommentieren

  Serial.println("**********************************");

  Serial.print(checkhour);Serial.print(":"); Serial.print(checkmin);
  Serial.print(" ==> ");
  Serial.print(GSMhour);Serial.print(":"); Serial.println(GSMminuten);

  delay(5000);
}

Beispiel Ausgabe ok

00:33:43.582 -> 2:48 ==> 02:
00:33:48.809 -> **********************************
00:33:48.809 -> 10:33 ==> 10:
00:33:54.005 -> **********************************
00:33:54.005 -> 1:54 ==> 01:

Beispiel Ausgabe nicht ok

00:36:23.096 -> **********************************
00:36:23.096 -> 10:36 ==> 1036
00:36:23.096 -> :36
00:36:23.096 -> 
00:36:28.277 -> **********************************
00:36:28.277 -> 13:6 ==> 1306
:06

00:36:33.493 -> **********************************
00:36:33.493 -> 19:44 ==> 1944:44

Ein Char Array braucht immer ein Feld extra für das Endzeichen.

Wenn du ein Char Array brauchst, was zwei Felder benötigt, wie bei dir, dann musst du ein Char Array mit 3 Feldern bauen.

int kann 16 oder 32 Bit sein. Besser (u)int16(32)_t benutzen. Bei dir besser noch uint8_t

Das Ganze lässt sich auch etwas verkürzen.

// Variablen um die Zeit zu speichern
  int   NWyear    = 0;        
  int   NWmonth   = 0;
  int   NWday     = 0;
  int   NWhour    = 0;
  int   NWmin     = 0;
  int   NWsec     = 0;
  float NWtimezone = 0;
//array in dem Stunden bzw Minuten formatiert abgelegt werden
  char GSMhour[3];
  char GSMmin[3];
 
void setup() {
  Serial.begin(115200);
}
 
void loop() {
  NWmin=random(0,60); 
  NWhour=random(0,24);
  snprintf(GSMhour,sizeof(GSMhour),"%02d", NWhour);
  snprintf(GSMmin,sizeof(GSMmin),"%02d", NWmin);
 
  Serial.println("**********************************");
  Serial.print(NWhour);Serial.print(":"); Serial.print(NWmin);
  Serial.print(" ==> ");
  Serial.print(GSMhour);Serial.print(":"); Serial.println(GSMmin);
  delay(5000);
}

Ja.
Grundlagen :slight_smile:

Das:

wird nix.
Du willst in ein Byte zwei Zeichen legen.
Und zusätzlich kommt dazu, dass '0' das Zeichen '0' und nicht die Zahl 0 und erst recht nicht der Wert NULL ist.
Das was Du suchst ist '\0'
Passt aber trotzdem nicht. Du braucht ein Byte für die Ziffer und eines für die Terminierung.

Alles, was Du da versuchst zu rechnen gibt es Fertig.
Das Zauberwort heisst sprintf() bzw. snprintf()
Letztere berücksichtigt die Angabe der Größe des Ziels.

  snprintf(GSMhour, sizeof(GSMhour),  "%02d", NWhour);
  snprintf(GSMminuten, sizeof(GSMminuten), "%02d", NWmin);
2 Likes

Da stellt sich doch die Frage: Warum?
Warum willst du das überhaupt machen.
Wenn du eine Information als Integer vorliegen hast und diese lediglich "anders" darstellen willst, dann gibt es bestimmt bessere Möglichkeiten als diese Information - mit mehr Speicherbedarf - redundant abzuspeichern.
Wenn du beschreibst, was du eigentlich machen willst, kann man dir sicher besser helfen.

Herzlichen Danke für eure konstruktiven Hinweise. Hab wieder viel dazu gelernt. Klar warum einfach wenn es auch kompliziert geht :slight_smile: . Ich verstehe arrays nun besser und kann ein wenig mit snprintf umgehen. Danke nochmals.
Warum das Ganze. Der formatierte Stirng wird einer Funktion übergeben die eine SMS sendet.
links die mir geholfen haben mein wissen zu erweitern.
escape from % Formatted output ASCII Code Das Array
So siehts das schnipsel jetzt aus: :wink:

// Variablen um die Zeit zu speichern
  uint16_t  NWyear    = 0;         
  uint8_t   NWmonth   = 0;
  uint8_t   NWday     = 0;
  uint8_t   NWhour    = 0;
  uint8_t   NWmin     = 0;
  uint8_t   NWsec     = 0;
  float NWtimezone = 0;
//array in dem Stunden bzw Minuten formatiert abgelegt werden
  char GSMhour[3];
  char GSMminuten[3];
  uint8_t percent=86;

void setup() {
  Serial.begin(115200);

delay(2000);
int z = 9 ;
char testchar=z;
Serial.println(testchar);
}

void loop() {
  NWmin=random(0,59);       // zu testzwecken wird ein Int ausgewählt
  uint8_t checkmin = NWmin;     // speichert den Zufalls wert

  NWhour=random(0,23);
  uint8_t checkhour = NWhour;

// Formating hours: Teil 1
  if (NWhour<10){               //Erste Bedingung trifft zu wenn die Stunden kleiner als 10
    GSMhour[0]= '0';            //das Zeichen 0 wird an erste Stelle abgelegt
    GSMhour[1]=NWhour+48;       //Die Stunde wird als Zeichen abgelegt. +48 ist notwendig um auf den richtigen Zeichenwert der ASCII Tablle zu kommen
    GSMhour[2]= '\0';           // 0 Terminator
  }
  else if (NWhour>9) {            
    GSMhour[0]= (NWhour/10)+48;
    GSMhour[1]= (NWhour%10)+48;
    GSMhour[2]= '\0';
  }
  else {
    GSMhour[0]= '0';            
    GSMhour[1]= '0'; 
    GSMhour[2]= '\0';           
  }

  if (NWmin<10){
    GSMminuten[0]= '0';
    GSMminuten[1]= NWmin+48;
    GSMminuten[2]= '\0';
  }
  else if (NWmin>9) {
    GSMminuten[0]= (NWmin/10)+48;
    GSMminuten[1]= (NWmin%10)+48;
    GSMminuten[2]= '\0';
  }
  else {
    GSMminuten[0]= '0';
    GSMminuten[1]= '0'; 
    GSMminuten[2]= '\0';
  }

  Serial.println("**********************************");

  Serial.print(checkhour);Serial.print(":"); Serial.print(checkmin);
  Serial.print(" ==> ");
  Serial.print(GSMhour);Serial.print(":"); Serial.println(GSMminuten);

  // oder einfacher
  char mySMStext[150];
  snprintf_P(mySMStext, sizeof(mySMStext), ("Es wurde eine Aktion zum Zeitpunkt %02d:%02d ausgelöst! Die Batterie ist zu %03d%% geladen"), NWhour, NWmin,percent);
  Serial.println(mySMStext);

  delay(5000);
}

Schön, dass Du etwas mitgenommen hast. Warum du dieses If else „Gebimsel“ aber immer noch machst, ist mir etwas schleierhaft.

Irgendwie sehe ich keinen Sinn in deiner Array-Geschichte.
s(n)printf bringt doch alles für eine formatierte Ausgabe mit.

Die von mir gebaute Zeile(n) berücksichtigen:
a) Dass Du zwei Stellen in der Variablen möchtest
b) wenn nur eine Stelle im Wert ist, eine 0 davor geschrieben wird. (01, 02, 03....)

zwei Sachen:

NWmin=random(0,59); 

du wirst nie eine Minute 59 bekommen. Siehe random() | Arduino Documentation

(gilt analog auch für die Stunden)

char mySMStext[150];

wenn du davon ausgehst, dass das SMS Längenlimit 150 ist, dann sollst du die Buffergröße auf 150+1 setzen.

Hmm, in Posting #4 wurde die Geschichte mit Random korrigiert und die snprintf Geschichte gezeigt. Aber anscheinend wurde sich damit nicht wirklich beschäftigt. Sonst hätte ja zumindest eine Frage aufkommen müssen.

Da If else „Gebimsel wird nicht verwendet und auch beim random war es nicht so wichtig was raus kommt. War für mich rein um das array besser zu begreifen und die zusammenhänge. Im Projekt verwende ich natürlich snprintf.

Nun du hast es gepostet. In dem Code wird es verwendet. Da hat sich die Frage halt aufgedrängt.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.