Uhrzeit als String- geht es noch "einfacher"

Hallo,
diese “StringFunktionen” haben mich bald an den Rand des Wahnsinn getrieben.
Ich benutze RTC ohne Lib´s. Das ist das Ausgangsmaterial:

minutes = (((minutes & 0b11110000)>>4)*10 + (minutes & 0b00001111));
hours = (((hours & 0b00110000)>>4)*10 + (hours & 0b00001111));

Um nun eine einfache (1:7) Uhrzeit in eine normale (01:07) Uhrzeit zu
bekommen habe ich nachfolgendes programmiert:

String Zeit;
String Std(hours);
String Min(minutes);

if (hours >=0 && hours <10)
{Std=(String("0") + (hours));}

if (minutes >=0 && minutes <10)
{Min=(String("0") + (minutes));}
   
Zeit=(String(Std) + ":" + String(Min)); 

lcd.print(Zeit);

geht das noch einfacher, oder ist das die Grenze?
Gruß und Dank
Andreas

Wenn Du die Uhrzeit nur auf das LCD ausgeben willst, dann brauchst Du keine Strings. Einfach wenn die Null notwendig ist, diese auf das Display ausgeben und dann die Variable. Ich nehme mal an, daß die Werte für Minuten und Stunden keine negativen Werte annehmen.

if (hours <10)
{lcd.print("0");}
lcd.print(hours);
lcd.print(":");
if (minutes <10)
{lcd.print("0");}
lcd.print(minutes);

Grüße Uwe

Wenn minutes und hours noch die Original von der RTC gelesenen bytes sind:

static char time[6] = "##:##"; // Der Platz für den Anzeigetext
time[0] =  ((hours & 0b00110000)>>4) + '0';
time[1] = (hours & 0b00001111) + '0';
time[3] = ((minutes & 0b11110000)>>4)+ '0';
time[4]= (minutes & 0b00001111)+'0';
lcd.write(time);

SkobyMobil: diese "StringFunktionen" haben mich bald an den Rand des Wahnsinn getrieben.

Du verwendest ein "String-Objekt", das nur wenige Methoden zur Manipulation des String-Objekts bietet. String-Objekte sind voll Panne, denn sie sind zu den "richtigen" Stringfunktionen der AVR LIBC vollkommen inkompatibel.

Strings unter C sind nullterminierte Char-Arrays. Zusammen mit C-Strings stehen Dir zig String-Funktionen in der AVR LIBC zur Verfügung. Zum Beispiel Formatierung eines Strings mit sprintf oder snprintf.

Das Problem ist: Zum Umgang mit String-Objekten gibt es nur eine gute handvoll Methode für das String-Objekt, aber an String-Funktionen für echte C-Strings gibt es zig Funktionen in der AVR LIBC. Damit kannst Du Strings viel mächtiger manipulieren und formatieren als mit der handvoll Methoden von String-Objekten.

  int hours=1;
  int minutes=7;
  char zeit[6];
  snprintf(zeit,sizeof(zeit),"%02d:%02d",hours,minutes);
  Serial.begin(9600);
  Serial.println(zeit);

Bei der sprintf/snprintf Funktion formatierst Du in einen "Format-String mit Platzhaltern" die zu formatierenden Variablen hinein. Der Platzhalter im Format-String für "Dezimalzahl mit führenden Nullen und zwei Stellen" lautet "%02d". Und davon formatierst Du zwei Stück (hours, minutes) in den String hinein.

Beispielsweise. Aber es gibt im Endeffekt zig verschiedene Möglichkeiten. Z.B. nach Michaels Methode, wenn die aus der RTC ausgelesenen Werte schon in Stunden und Minuten umgewandelt wurden:

  char time[6]="##:##";
  time[0]='0'+hours/10;
  time[1]='0'+hours%10;
  time[3]='0'+minutes/10;
  time[4]='0'+minutes%10;
  Serial.println(time);

Diese letzte Art der Manipulation einzelner Zeichen funktioniert allerdings auch mit String-Objekten, falls Du trotz der Nachteile bei String-Objekten statt Strings bleiben möchtest:

  String time="##:##";
  time[0]='0'+hours/10;
  time[1]='0'+hours%10;
  time[3]='0'+minutes/10;
  time[4]='0'+minutes%10;
  Serial.println(time);

Hallo, erst einmal schönen Dank für eure Mühe.

Ich wollte den "Zeit" String auch an anderer Stelle verwenden können, und dort auch unter Umständen zurückholen. Das von mir ausgedachte taugt aber nur um eine Anzeige auf dem Display zu realisieren, alles andere ist umständlich bis nicht machbar. Müll!

Das zweite was mich jetzt stört, ist- wenn ich mich richtig "schlau" gemacht habe, das "ArduinoString´s(Manupulationen)" sich dynamisch geheimnisvoll im Speicher verteilen. Um mit String´s sauber zu arbeiten, bleiben wohl nur C-Zeichenketten übrig. Das von "jurs" & "michael_x" angebotene ist schon perfekt. Wobei der von "jurs" gezeigte Code schon ziemlich mächtig ist. So werde ich das in Zukunft auch mit anderen Zahlen machen. Wenn man sich damit beschäftigt hat (hier habe ich ja mal eine Verständliche Erklärung dazu bekommen) dann ist es eigentlich keine Schwierigkeit mit Strings zu arbeiten. Das hat mich richtig weitergebracht und einige Probleme sind einfach vom Tisch gewischt. Also, schönen Dank. Gruß und Spaß Andreas

Ja, die String Objekte verwenden dynamischen Speicher. Damit kann es sein, dass du dir mit der Zeit den Heap fragmentierst.

Was einem am Anfang oft nicht klar ist, dass bei String Klassen i.d.R ein neues Objekt erzeugt wird wenn man irgendeine Operation durchführt. Das heißt, wenn man z.B. zwei Strings zusammenfügt wird ein neues Objekt erzeugt und die zwei anderen gelöscht. Es sieht nur so aus als ob sich der String vergrößert. Tatsächlich hat man es mit komplett neuem Speicher zu tun.

Es gibt eine Implementierung der C++ Standard Template Library für den Arduino, bei der sich Strings wie Vektoren verhalten. Dass hast es wird erst etwas mehr Speicher als nötig angelegt. Dadurch kann der String etwas wachsen und man muss nicht ständig das Array im Hintergrund umkopieren. Weiß nicht ob die Standard Arduino Version das auch so macht.

Ich habe mir länger überlegt dies zu fragen, aber es lässt mir keine Ruhe ;)

Die Beispiele von jurs und michael_x verstehe ich schon, bis auf eine Sache.

 char time[6]="##:##";
  time[0]='0'+hours/10;
  time[1]='0'+hours%10;
  time[3]='0'+minutes/10;
  time[4]='0'+minutes%10;

Time ist ein Char Array, und ein Element des Array ist ein Byte/Zeichen. Hier wird z.b auf time[0] also das erste Zeichen von time zugegriffen um den Zehnerwert der Stunde zuzuweisen. Also so: time[0]=hours/10; wäre für mich logisch.

Warum dann das: time[0]='0'+hours/10; Also die '0' ??

Schau dir mal die ASCII Tabelle an. Das Zeichen '0' hat den ASCII Wert 0x30 oder 48. Und char Literale sind nichts anderes als deren ASCII Integer Wert. Daher kann man dafür auch + '0' schreiben.

Wenn man das weg lässt ist man in den nicht druckbaren Steuerzeichen. Bei einfachen LCDs ist das meistens das custom character RAM. Bei TFT Displays zeigt er Unsinn an.

Ahh.. Danke jetzt kommt Licht ins Dunkle , das Display braucht ja den ASCII Wert. :blush: :blush: Wenn 0x30 oder 48 addiert worden wäre hätte ich es evtl. sogar gleich verstanden.

Wenn 0x30 oder 48 addiert worden wäre hätte ich es evtl. sogar gleich verstanden.

Sorry, ich hätte gedacht ‘0’ + i wäre klarer :wink:
‘0’ ist der Buchstabe, der angezeigt wird, da braucht man sich nicht zu merken, wie der intern gespeichert wird, nur dass die ‘1’ direkt danach kommt also ‘0’ +1