Arduino Forum

International => Deutsch => Topic started by: -Micky on Jun 13, 2013, 11:28 am

Title: Temperaturanzeige mit + Zeichen
Post by: -Micky on Jun 13, 2013, 11:28 am
Wie kann ich mit der Funktion:

temperatur = sensors.getTempCByIndex(0);

das Plus Zeichen mit ausgeben?

Die Ausgabe erfolgt mit:

lcd.print( dtostrf( temperatur, 5, 2, stringbuffer ) );


Micky
Title: Re: Temperaturanzeige mit + Zeichen
Post by: sth77 on Jun 13, 2013, 11:32 am
Vielleicht einfach so:
Code: [Select]
if (temperatur>=0) lcd.print("+");
lcd.print( dtostrf( temperatur, 5, 2, stringbuffer ) );
Title: Re: Temperaturanzeige mit + Zeichen
Post by: jurs on Jun 13, 2013, 12:39 pm

Wie kann ich mit der Funktion:

temperatur = sensors.getTempCByIndex(0);

das Plus Zeichen mit ausgeben?

Die Ausgabe erfolgt mit:

lcd.print( dtostrf( temperatur, 5, 2, stringbuffer ) );


Erstmal mußt Du mit dtostrf breit genug formatieren, 5 Zeichen reichen bei 2 Nachkommastellen ja nur für einstellige Temperaturen  mit Vorzeichen. Für zweistellige Temperaturen mit Vorzeichen wäre die Mindestbreite 6 Zeichen.

Und dann kannst Du die gewünschte Funktion realisieren, indem Du Dir nach der Formatierung das Zeichen vor der ersten Ziffer anschaust: Ist es ein Minuszeichen, dann ist das Vorzeichen vorhanden und Du machst weiter nichts, ist es aber ein Leerzeichen, setzt Du stattdessen ein Pluszeichen ein.

Code: [Select]

  dtostrf( temperatur, 6, 2, stringbuffer );
  int i=0;
  while (!isdigit(stringbuffer[i])) i++;
  if (i>0 && stringbuffer[i-1]!='-') stringbuffer[i-1]='+';
  Serial.println(stringbuffer);

Title: Re: Temperaturanzeige mit + Zeichen
Post by: -Micky on Jun 14, 2013, 11:22 am
Danke, funktioniert.

Bißchen merkwürdig ist, wenn ich bei allen:

dtostrf( temperatur, 9, 2, stringbuffer );

9 reinschreibe, mir bei 2 Displays die Erste Stelle nicht mehr angezeigt wird. Ich habe vier Displays dran. Mit zwei mal 8 und zwei mal 9 funktioniert das aber.


Micky
Title: Re: Temperaturanzeige mit + Zeichen
Post by: michael_x on Jun 14, 2013, 04:00 pm
Nein!
Merkwürdig ist, dass noch nicht mal jurs schreibt, was 'stringbuffer' ist.

Wenn man über definierte Variablenbereiche hinausschreibt, funktioniert das manchmal trotzdem.

Quote
dtostrf( temperatur, 9, 2, stringbuffer );

Mit dieser einen geposteten Zeile hat dein Problem höchstens indirekt zu tun.

Title: Re: Temperaturanzeige mit + Zeichen
Post by: jurs on Jun 14, 2013, 04:28 pm

Merkwürdig ist, dass noch nicht mal jurs schreibt, was 'stringbuffer' ist.


Es reicht doch, wenn es in der Referenz zur Funktion steht: http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

Außer, dass 'stringbuffer' in der Referenz 's' heißt, ist alles gleich:
value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s.

'stringbuffer' muss also immer lang genug sein, um den String mit voller Länge plus das abschließende Nullzeichen aufzunehmen. D.h. bei:
dtostrf( temperatur, 9, 2, stringbuffer );
muss 'stringbuffer' deklariert sein als char Array mit 10 Zeichen:
char stringbuffer[10];

9 Zeichen Stringlänge plus abschließendes Nullzeichen = 10 Zeichen Gesamtlänge.

Ich muß ja nicht in jedem Posting einen Roman schreiben.
;)
Title: Re: Temperaturanzeige mit + Zeichen
Post by: michael_x on Jun 14, 2013, 10:21 pm
Quote
Ich muß ja nicht in jedem Posting einen Roman schreiben.
smiley-wink

Nein, aber ich gehe davon aus, du weisst auch, dass Code ohne Variablendefinition nur Mist ist.
smiley-wink zurück ;)

Title: Re: Temperaturanzeige mit + Zeichen
Post by: -Micky on Jun 14, 2013, 10:34 pm
Hier ist der Code, kann ja was falsch sein:

Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Für I2C LCD Display

#define ONE_WIRE_BUS 3

LiquidCrystal_I2C lcd(0x20,16,2);  // I2C LCD Adresse auf 0x20 gesetzt, 16 Zeichen / 2 Zeilen LCD
LiquidCrystal_I2C lcd2(0x21,16,2);  // I2C LCD Adresse auf 0x21 gesetzt, 16 Zeichen / 2 Zeilen LCD
LiquidCrystal_I2C lcd3(0x22,16,2);  // I2C LCD Adresse auf 0x22 gesetzt, 16 Zeichen / 2 Zeilen LCD
LiquidCrystal_I2C lcd4(0x24,16,2); // I2C LCD Adresse auf 0x24 gesetzt, 16 Zeichen / 2 Zeilen LCD

char buffer[17] = "";                                     
OneWire oneWire(ONE_WIRE_BUS);                           
DallasTemperature sensors(&oneWire);

void setup(void) {
 
  lcd.init();
  lcd.backlight();
 
  lcd2.init();
  lcd2.backlight();
 
  lcd3.init();
  lcd3.backlight();
 
  lcd4.init();
  lcd4.backlight();
 
  byte addr[8]; 
   
  sensors.begin();

  sensors.setResolution( 12 );
                               
}


void loop(void) {

  float temperatur = 0;
  char stringbuffer[10];

  sensors.requestTemperatures();                                         
   
  int i=0;
 
  lcd.setCursor(0, 0);
  lcd.print( "Tiefkuehltruhe 1" );
  lcd.setCursor(10, 1);
  lcd.print((char)223);
  lcd.print("C ");
  lcd.setCursor(3, 1);
  temperatur = sensors.getTempCByIndex(0);
  dtostrf( temperatur, 8, 2, stringbuffer );
  while (!isdigit(stringbuffer[i])) i++;
  if (i>0 && stringbuffer[i-1]!='-') stringbuffer[i-1]='+';
  lcd.setCursor(1, 1);
  lcd.print(stringbuffer);
   
  lcd2.setCursor(0, 0);
  lcd2.print( " Kuehlschrank 1" );
  lcd2.setCursor(10, 1);
  lcd2.print((char)223);
  lcd2.print("C ");
  lcd2.setCursor(3, 1); 
  temperatur = sensors.getTempCByIndex(1);
  dtostrf( temperatur, 8, 2, stringbuffer );
  while (!isdigit(stringbuffer[i])) i++;
  if (i>0 && stringbuffer[i-1]!='-') stringbuffer[i-1]='+';
  lcd2.setCursor(0, 1);
  lcd2.print(stringbuffer);
 
  lcd3.setCursor(0, 0);
  lcd3.print( "Innentemperatur" );
  lcd3.setCursor(10, 1);
  lcd3.print((char)223);
  lcd3.print("C ");
  lcd3.setCursor(3, 1); 
  temperatur = sensors.getTempCByIndex(2);
  dtostrf( temperatur, 9, 2, stringbuffer );
  while (!isdigit(stringbuffer[i])) i++;
  if (i>0 && stringbuffer[i-1]!='-') stringbuffer[i-1]='+';
  lcd3.setCursor(0, 1);
  lcd3.print(stringbuffer);
   
  lcd4.setCursor(0, 0);
  lcd4.print( "Aussentemperatur" );
  lcd4.setCursor(10, 1);
  lcd4.print((char)223);
  lcd4.print("C ");
  lcd4.setCursor(3, 1);
  temperatur = sensors.getTempCByIndex(3);
  dtostrf( temperatur, 9, 2, stringbuffer );
  while (!isdigit(stringbuffer[i])) i++;
  if (i>0 && stringbuffer[i-1]!='-') stringbuffer[i-1]='+';
  lcd4.setCursor(0, 1);
  lcd4.print(stringbuffer);
}





Micky
Title: Re: Temperaturanzeige mit + Zeichen
Post by: michael_x on Jun 14, 2013, 10:56 pm
Code: [Select]
while (!isdigit(stringbuffer[i])) i++;

kommt vier mal vor ( für jede lcd ) , i wird aber nur einmal ganz am Anfang auf 0 gesetzt

Ich weiss zwar nicht, ob das wirklich das Problem ist, das ist jedenfalls nicht der Sinn von jurs Idee, wie man den Anfang der Zahl findet um dort das '+' zu setzen .
Title: Re: Temperaturanzeige mit + Zeichen
Post by: -Micky on Jun 14, 2013, 11:03 pm
Das ist es! Danke.

Wäre nicht darauf gekommen das es daran liegt.


Micky
Title: Re: Temperaturanzeige mit + Zeichen
Post by: jurs on Jun 15, 2013, 12:06 am

Das ist es! Danke.

Wäre nicht darauf gekommen das es daran liegt.


Kleiner Exkurs zum Schreiben von übersichtlichem Code.

Wenn Du praktisch immer dieselben Codeabschnitte wieder und wieder ausführen mußt mit nur ganz geringen Änderungen, dann bietet es sich an, dafür geeignete Funktionen zu schreiben. Getestete Funktionen, die dann immer wieder aufgerufen werden können, ohne dass was vergessen wird, wenn Codeabschnitte mehrfach kopiert und eingefügt werden.

Wie wäre es z.B. mit so einer aufgeräumten loop-Funktion:
Code: [Select]

void loop(void) {
  sensors.requestTemperatures();     
  printOnLCD(lcd, "Tiefkuehltruhe 1",sensors.getTempCByIndex(0));
  printOnLCD(lcd2," Kuehlschrank 1",sensors.getTempCByIndex(1));
  printOnLCD(lcd3,"Innentemperatur",sensors.getTempCByIndex(2));
  printOnLCD(lcd4,"Aussentemperatur",sensors.getTempCByIndex(3));
}


Statt dass da haufenweise unübersichtlich (und womöglich fehlerhaft) zusammenkopierter Code drinsteht, steht da viel weniger, aber dafür aufgeräumter Code drin, nämlich hauptsächlich vier fast gleiche Funktionsaufrufe:
- gib auf "lcd" den Text "Tiefkuehltruhe 1" mit Temperaturindex 0 aus
- gib auf "lcd2" den Text " Kuehlschrank 1" mit Temperaturindex 1 aus
- gib auf "lcd3" den Text "Innentemperatur" mit Temperaturindex 2 aus
- gib auf "lcd4" den Text "Aussentemperatur" mit Temperaturindex 3 aus

Dann sieht die loop doch schon mal aufgeräumter aus als bei Dir, oder?

Und nun brauchst Du natürlich die Funktion "printOnLCD()", die einige Parameter übergeben bekommt, nämlich
- auf welchem lcd ausgegeben werden soll
- welcher Text ausgegeben werden soll
- welche Temperatur ausgegeben werden soll

Code: [Select]

void printOnLCD(LiquidCrystal_I2C einlcd, char* text, float temp)
// Funktion gibt auf einem LCD einen Text und eine Temperatur aus
{
  char stringbuffer[10];
  einlcd.setCursor(0, 0);
  einlcd.print( text );
  einlcd.setCursor(10, 1);
  einlcd.print((char)223);
  einlcd.print("C ");
  dtostrf( temp, 8, 2, stringbuffer );
  int i=0;
  while (!isdigit(stringbuffer[i])) i++;
  if (i>0 && stringbuffer[i-1]!='-') stringbuffer[i-1]='+';
  einlcd.setCursor(1, 1);
  einlcd.print(stringbuffer);
}


Stichwort: "Wiederverwertbarkeit von Code"

Du schreibst also nur einmal Code, wie Text und Temperatur auf einem LCD ausgegeben werden soll. Dieser Code wird gründlich getestet.

Aber Du kannst diesen kompletten Code dieser einen Funktion dann mit einem Einzeiler und einigen übergebenen Parametern beliebig oft ausführen lassen, ohne dass beim Kopieren von Codeabschnitten Fehler passieren können.

Ist nur ein Vorschlag, mehr Struktur und Übersicht zu bekommen.