Temperatur darstellen auf 4digit 7-Segment-Anzeige

Hallo
Ich will die Temperatur, welche von einem DS18S20 gelesen wird, über den Arduino und einen MAX7219 auf einer 7-Segment-Anzeige darstellen. Ich stehe etwas an mit dem Programmieren.
Ich habe den Sensor getestet. Er funktioniert. Allerdings weiss ich nicht, wie ich (mit LedControl) programmieren soll, dass die Temperatur korrekt auf dem Display dargestellt wird.
Kann mir jemand helfen?
Vielen Dank
Dies ist der Code mit dem ich den Sensor getestet habe:

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

/*
 * The setup function. We only start the sensors here
 */
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // Start up the library
  sensors.begin();
}

/*
 * Main function, get and show the temperature
 */
void loop(void)
{ 
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));  
}

Ich möchte diesen gerne weiterverwenden, da ich diesen gut verstehe.
Freundliche Grüsse
techniclover

Hallo, kennst Du das Beispiel LCDemo7Segment.ino der Bibliothek LedControl? Damit würde ich das Display testen. Danach kannst Du die Anzeige in Deinen bestehenden Sketch integrieren.

Ja, dieses Beispiel habe ich mehrmals durchgesehen. Das Display funktioniert.
Da es aber bei den Temperaturen Zehner-, Einer- und Zehntelsziffern gibt weiss ich nicht, wie ich das programmieren muss. Ich habe es mit folgendem Code versucht.

/ Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
//7-Segment
#include <LedControl.h>
LedControl seg = LedControl (11, 13, 7, 1);

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

/*
   The setup function. We only start the sensors here
*/
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
  seg.shutdown(0, false);
  /* Set the brightness to a medium values */
  seg.setIntensity(0, 8);
  /* and clear the display */
  seg.clearDisplay(0);
  // Start up the library
  sensors.begin();
}

/*
   Main function, get and show the temperature
*/
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  sensors.requestTemperatures(); // Send the command to get temperatures
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));
  byte tempOnes = getTempCByIndex(0);
  byte temoTens = 0;
  while (tempOnes > 99 {
  tempOnes = tempOnes - 10;
  tempTens = tempTens + 1;
}
seg.setDigit (0, 3, tempTens, false);
seg.setDigit (0, 2, tempOnes, false);

}

Bei folgender Zeile markiert mir das Programm einen ERROR:

 byte tempOnes = getTempCByIndex(0);

Da ich nicht sehr viel Erfahrung damit habe, wäre ich froh um Hilfe.
LG

Natürlich. Du musst die Methode schon auf dein sensors Objekt anwenden. So wie du hier begin gemacht hast:

sensors.begin();

Oder hier:

 sensors.requestTemperatures();

Oder auch nur eine Zeile darüber

  Serial.println(sensors.getTempCByIndex(0));

Danke viel mals. Dies habe ich nun korrigiert. Damit hat das Programm nun kein Problem mehr.

Allerdings funktioniert es immernoch nicht. Mir wird nun eine Fehlermeldung gegeben, dass tempTens nicht definiert wurde (bei setDigit()):

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
//7-Segment
#include <LedControl.h>
LedControl seg = LedControl (11, 13, 7, 1);

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

/*
   The setup function. We only start the sensors here
*/
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
  seg.shutdown(0, false);
  /* Set the brightness to a medium values */
  seg.setIntensity(0, 8);
  /* and clear the display */
  seg.clearDisplay(0);
  // Start up the library
  sensors.begin();
}

/*
   Main function, get and show the temperature
*/
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  sensors.requestTemperatures(); // Send the command to get temperatures
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));
  byte tempOnes = sensors.getTempCByIndex(0);
  byte temoTens = 0;
  while (tempOnes > 9) {
  tempOnes = tempOnes - 10;
  tempTens = tempTens + 1;
}
seg.setDigit (0, 3, tempTens, false);
seg.setDigit (0, 2, tempOnes, false);

}

Ich verstehe das nicht. Zwei Zeilen vorher habe ich doch definiert, was tempTens ist?
Vielen Dank für eure Hilfe

byte tem*o*Tens = 0;

Vielen Dank. Ich denke ich habe dieses Programm heute schon zu oft durchgesehen, dass mir solche Fehler nichtmehr auffallen.

Nun habe ich noch ein Problem mit der Darstellung der Zehntel. Kann mir da jemand helfen?
Ich habe es folgendermassen probier, allerdings funktioniert dies nicht. Vielen Dank

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
//7-Segment
#include <LedControl.h>
LedControl seg = LedControl (11, 13, 7, 1);

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

/*
   The setup function. We only start the sensors here
*/
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
  seg.shutdown(0, false);
  /* Set the brightness to a medium values */
  seg.setIntensity(0, 8);
  /* and clear the display */
  seg.clearDisplay(0);
  // Start up the library
  sensors.begin();
}

/*
   Main function, get and show the temperature
*/
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  sensors.requestTemperatures(); // Send the command to get temperatures
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));
  byte tempOnes = sensors.getTempCByIndex(0);
  byte tempTens = 0;
  byte tempTenths = sensors.getTempCByIndex(0);
  while (tempOnes > 9) {
    tempOnes = tempOnes - 10;
    tempTens = tempTens + 1;
    tempTenths = tempTenths - tempTens * 10 - tempOnes;
  }
  seg.setDigit (0, 3, tempTens, false);
  seg.setDigit (0, 2, tempOnes, false);
  seg.setDigit (0, 1, tempTenths, false);
}

getTempCByIndex() liefert eine Gleitkommazahl. Du weist das einfach einem Integer zu. Dabei werden die Nachkommastellen abgeschnitten. Du musst das erst mal mit 10 Multiplizieren.

Also z.B. 25,3 * 10 = 253

Und auch beachten dass es einen Unterschied macht ob die vor dem Komma 1 oder 2 Ziffern hast

Oh dankeschön, das habe ich nicht gewusst.

So geht es übrigens einfacher:

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

  getDigits(1.0);
  getDigits(6.7);
  getDigits(10.0);
  getDigits(78.2);
}

void loop()
{ 

}

void getDigits(float temp)
{
  int tempInt = temp * 10;
  
  byte tempFrac = tempInt % 10;
  tempInt /= 10;
  byte tempOne = tempInt % 10;
  tempInt /= 10;
  byte tempTen = tempInt % 10;

  Serial.println(tempTen);
  Serial.println(tempOne);
  Serial.println('.');
  Serial.println(tempFrac);
  Serial.println("--");
}

Einzelne Ziffern holt man am besten sich durch Division und Modulo-Division (Rest einer Division). Dann geht es auch mit allen (positiven) Zahlen. Modulo 10 liefert dir immer die Einer-Stelle. Diese wird dann mit einer normalen Division durch 10 abgeschnitten. Sowas in einer Schleife bis die Division 0 ist funktioniert wunderbar wenn man Zahlen unbekannter Länge hat

Aber Achtung hier:

int tempInt = temp * 10;

Das sollte int sein. Nicht byte wie bei dir! Wenn du * 10 machst und byte hast geht es nur bis 25,5 da du dann schon bei 255 bist.

Ich verstehe was du meinst. Allerdings verstehe ich nicht, was der Befehl getDigit() bedeuten soll.

void getDigits(float temp) ist eine Funktion, um die Temperatur anzuzeigen.

Ja, aber was bedeuten die getDigit() Befehle im Setup? Was bedeuten die Zahlen?

techniclover: Ja, aber was bedeuten die getDigit() Befehle im Setup? Was bedeuten die Zahlen?

Serenifly macht Dir ein Beispiel, welches nur einmal durchlaufen werden soll. Daher schreibt er das in setuo().

Bei Dir gehört das in loop() und dann nicht getDigits(78.2); mit einer festen Temperatur, sondern getDigits(temperatur); mit einer Variablen.

Das ist kein Befehl sondern eine Funktion. Wie auch loop() oder setup()

Ich will etwas mehrmals tun. Anstatt also den Code mehrmals hinzuschreiben oder eine Schleife zu machen, schreibe ich eine Funktion der man die Zahl als Parameter übergibt. Dann kann man sie beliebig oft verwenden. Bei viel Code wird es außerdem übersichtlicher wenn man zusammengehöre Zeilen in Funktionen auslagert. Dann sieht man beim Aufruf was gemacht wird, aber muss sich nicht direkt die Implementierung ansehen.

getTempCByIndex() ist auch nicht viel anderes, nur dass es zu einer Klasse gehört und daher "Methode" heißt (es gibt einen Unterschied aber das ignorieren wir hier mal).

Das macht Sinn. Ich habe das ausprobiert, aber es gibt eine Fehlermeldung.
Bei meinem getDigits() Befehl wird gesagt, dass er nicht definiert wurde. Wo muss ich den definieren?
Dies ist der Sketch:

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
//7-Segment
#include <LedControl.h>
LedControl seg = LedControl (11, 13, 7, 1);

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

/*
   The setup function. We only start the sensors here
*/
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
  seg.shutdown(0, false);
  /* Set the brightness to a medium values */
  seg.setIntensity(0, 8);
  /* and clear the display */
  seg.clearDisplay(0);
  // Start up the library
  sensors.begin();
}

/*
   Main function, get and show the temperature
*/
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  sensors.requestTemperatures(); // Send the command to get temperatures
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));
 getDigits (sensors.getTempCByIndex(0));
 void getDigits(float temp)
{
  int tempInt = temp * 10;
 
  byte tempFrac = tempInt % 10;
  tempInt /= 10;
  byte tempOne = tempInt % 10;
  tempInt /= 10;
  byte tempTen = tempInt % 10;
  }
  }
  seg.setDigit (0, 3, tempTens, false);
  seg.setDigit (0, 2, tempOnes, false);
  seg.setDigit (0, 1, tempFrac, false);
}

Vielen Dank

Du musst unbedingt Programmier-Grundlagen lernen sonst wird das nichts. Es kein Befehl, sondern eine Funktion. Google wie man Funktionen in C schreibt und verwendet. Das ist ganz wichtig.

Die Funktion muss natürlich außerhalb einer anderen Funktion definiert werden.

Ich schreibe dir mal einen Test-Sketch mit Einbindung eines Sensors...

Spiel vielleicht mal damit herum bevor du es auf deine Anzeige überträgst:

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup()
{
  Serial.begin(9600);
  sensors.begin();
  sensors.setResolution(9);   //1 Nachkommastelle. Das ist aber schon Standard
}

void loop()
{
  sensors.requestTemperaturesByIndex(0);
  getDigits(sensors.getTempCByIndex(0));

  delay(400);   //nur damit Serial nicht zugemüllt wird. Kann bei einer reinen LED/LCD Anzeige weglassen!
}


void getDigits(float temp)
{
  //abs(solute) entfernt evtl. negative Temperaturen. 
  //Ein Vorzeichen kann man zur Anzeige gesondert behandeln wenn man abfragt ob temp < 0 ist
  int tempInt = abs(temp * 10);

  byte tempFrac = tempInt % 10;
  tempInt /= 10;
  byte tempOne = tempInt % 10;
  tempInt /= 10;
  byte tempTen = tempInt % 10;

  //print(float) formatiert standardmäßig auf 2 Nachkommastellen. Das ist nur eine Darstellungssache!
  //, 1 heißt 1 Nachkommastelle. Hat mit dem eigentlich Wert in der Variable nichts zu tun
  Serial.print(temp, 1);
  Serial.print(" -- ");
  Serial.print(tempTen);
  Serial.print(' ');
  Serial.print(tempOne);
  Serial.print(". ");
  Serial.print(tempFrac);
  Serial.println();
}

Und wie in dem anderen Thread gesagt. Bei 9 Bit Auflösung hast du nie etwas anderes als 0,5° Schritte. Deshalb kann man einfach * 10 machen

Du sagst es gibt nur 0.5 Schritte, aber es zeigt mir im Serial Monitor immernoch auch 25.3 25.6 und so weiter an.