Bitte um CODE Review - Temperatur wird nicht auf OLED ausgegeben

Hallo

Ich bin relativ neu im Arduinogeschehen. Nun habe ich mir einen Code für eine Druckmessung und Temperaturmessung zusammen gestellt. Das ganze wird auf ein SSD1306 ausgegeben.

Mir wird aber irgendwie die Temperatur nicht angezeigt (NTC Tempsensor)
Im seriellen Print funzt er einwandfrei.

Vielen Dank für eure Hilfe !


#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Thermistor.h>
#include <NTC_Thermistor.h>
int Sensor_Pin = A0;
#define Referenzwiderstand   47000 // Widerstandswert des Widerstandes der mit dem NTC in Reihe geschaltet wurde.
#define Nominalwiderstand     38000 // Widerstand des NTC bei Normaltemperatur
#define Nominaltemperatur    30 // Temperatur, bei der der NTC den angegebenen Wiederstand hat
#define BWert                3800 // Beta Koeffizient(zu finden im Datenblatt des NTC)
Thermistor* thermistor;



#define SCREEN_WIDTH 128 // display width, in pixels
#define SCREEN_HEIGHT 64 // display height, in pixels
#define OLED_RESET     4
#define SCREEN_ADDRESS 0x3C // OLED

const int sensorPin = A1;
const float alpha = 0.95; // Low Pass Filter alpha (0 - 1 )
const float aRef = 4.6; // analog reference
float filteredVal = 512.0; // midway starting point
float sensorVal;
float voltage;
float psiVal;
float celsius;

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup()   {
  Serial.begin(9600);
  while (!Serial);
  thermistor = new NTC_Thermistor(Sensor_Pin, Referenzwiderstand, Nominalwiderstand, Nominaltemperatur, BWert);

  //analogReference(EXTERNAL);
  //analogReference(INTERNAL);

  //SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
    Serial.println(F("SSD1306 allocation failed"));
    while (1); // Don't proceed, wait forever
  }
  display.clearDisplay();
  display.display();
}

void loop() {

  const double celsius = thermistor->readCelsius(); //Temperatur auslesen
  Serial.print("Temperatur: "); // Ausgabe der Temperatur am Seriellen Monitor - hier nur der Text "Temperatur; "
  Serial.print(celsius, 0); // An dieser Stelle wird der Temperaturwert an den Seriellen Monitor gesendet.
  Serial.println(" °C"); // Hinter dem Temperaturwert wird am Seriellen Monitor nun noch die Einheit "C" angezeigt.
  
  sensorVal = (float)analogRead(sensorPin); // Read pressure sensor val (A1)
  filteredVal = (alpha * filteredVal) + ((1 - alpha) * sensorVal);// Low Pass Filter
  voltage = (filteredVal / 1024.0) * aRef; // calculate voltage
  psiVal = (voltage - 0.4784) / 14.504; // x=(y-b)/m

  Serial.print ("raw_adc "); Serial.print (sensorVal, 0);
  Serial.print(", filtered_adc "); Serial.println (filteredVal, 0);
  //Serial.print(", voltage ");
  //Serial.println(voltage, 2);

  updateOLED ();

  delay(200);
}

void updateOLED () {

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);

  display.setCursor(5, 2);
  display.print("BENZINDRUCK ");

  display.setCursor(5, 40);
  display.print("OILTEMP");

  display.setCursor(80, 2);
  display.print(voltage, 2);
  display.print(" V");

  display.setTextSize(3);
  display.setCursor(30, 15);
  display.print(psiVal, 0);
  display.print("BAR");
 
  display.setTextSize(3);
  display.setCursor(50, 40);
  display.print(celsius, 0);
  display.print("C");

display.display();


}

Das hat Dir der Compiler nicht um die Ohren gehauen? Was bedeutet const?

Gruß Tommy

Globale und lokale Variable verhaken sich.

Schmeiß mal const double raus, dann wird die globale Variable verwendet.

1 Like

Vielen Dank !

Das war tatsächlich die Lösung :smiley:

der compiler hat das so geschluckt

Danke für Deine Rückmeldung :slightly_smiling_face:

1 Like

Combie hätte evtl. geschrieben
const double celsius {thermistor->readCelsius()};
damit eher zu sehen ist, dass es die Definition einer Konstanten ist.
Lokale Konstanten werden erst beim jeweiligen Funktionsaufruf definiert, und können auch durch einen erst zur Laufzeit bestimmbaren Wert initialisiert werden.

constexpr statt const geht natürlich nicht

1 Like

Danke für die Korrektur, da habe ich nicht richtig hin geschaut.

Gruß Tommy

Jetzt habe ich ein zweites Display verbaut. Was dort angezeigt werden soll ist noch nicht eingebunden. Habe erst mal das vom ersten Display kopiert.

I2C Scanner sagt das ein Display 03xC ist und eins 03xD vorhanden sind

Ich habe beide Displays initialisiert und derfiniert als displayL und displayR

Er bringt nach dem upload im serialscanner aber displayR allocation failed.

Tut mir leid das ich so viele Fragen haben :smiley: aber ich bin neu im Arduinobereich.
Irgendwo ist der wurm drin, wenn ich einen einfachen code nehme um die displays zu testen. Kann ich display 1 und 2 Ansteuern

#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 Display1(OLED_RESET);
Adafruit_SSD1306 Display2(OLED_RESET);

int i, j;

void setup()   {

  //Serial.begin(9600);

  Display1.begin(SSD1306_SWITCHCAPVCC, 0x3D);
  Display1.clearDisplay();
  Display1.display();

  Display2.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  Display2.clearDisplay();
  Display2.display();

}


void loop() {


  for (i = 0; i < 270; i+=10) {

    Display1.setTextSize(2);
    Display1.setTextColor(WHITE, BLACK);
    Display1.setCursor(0, 0 );
    Display1.println("Display 1");
    Display1.fillCircle(i, 30,  10, 1);
    Display1.display();
    Display1.clearDisplay();

    Display2.setTextSize(2);
    Display2.setTextColor(WHITE, BLACK);
    Display2.setCursor(0, 0);
    Display2.println("Display 2");
    Display1.fillCircle(i - 127, 30,  10, 1);
    Display2.display();
    Display2.clearDisplay();


  }

}

Mein Code



#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Thermistor.h>
#include <NTC_Thermistor.h>
int Sensor_Pin = A0;
#define Referenzwiderstand   47000 // Widerstandswert des Widerstandes der mit dem NTC in Reihe geschaltet wurde.
#define Nominalwiderstand     38000 // Widerstand des NTC bei Normaltemperatur
#define Nominaltemperatur    30 // Temperatur, bei der der NTC den angegebenen Wiederstand hat
#define BWert                3800 // Beta Koeffizient(zu finden im Datenblatt des NTC)
Thermistor* thermistor;



#define SCREEN_WIDTH 128 // display width, in pixels
#define SCREEN_HEIGHT 64 // display height, in pixels
#define OLED_RESET     4
#define SCREEN_ADDRESSL 0x3C // displayL
#define SCREEN_ADDRESSR 0x3D // displayR

const int sensorPin = A1;
const float alpha = 0.95; // Low Pass Filter alpha (0 - 1 )
const float aRef = 4.6; // analog reference
float filteredVal = 512.0; // midway starting point
float sensorVal;
float voltage;
float psiVal;
float celsius;

//displayL Init
Adafruit_SSD1306 displayL(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//displayR Init
Adafruit_SSD1306 displayR(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup()   {
  Serial.begin(9600);
  while (!Serial);
  thermistor = new NTC_Thermistor(Sensor_Pin, Referenzwiderstand, Nominalwiderstand, Nominaltemperatur, BWert);

  //analogReference(EXTERNAL);
  //analogReference(INTERNAL);

  //SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally Oled1
  if (!displayL.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESSL)) {
    Serial.println(F("displayL allocation failed"));
    while (1); // Don't proceed, wait forever
  }
  displayL.clearDisplay();
  displayL.display();

   //SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally Oled2
  if (!displayR.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESSR)) {
    Serial.println(F("displayR allocation failed"));
    while (1); // Don't proceed, wait forever
  }
  
  displayR.clearDisplay();
  displayR.display();
}

void loop() {

  celsius = thermistor->readCelsius(); //Temperatur auslesen
  Serial.print("Temperatur: "); // Ausgabe der Temperatur am Seriellen Monitor - hier nur der Text "Temperatur; "
  Serial.print(celsius, 0); // An dieser Stelle wird der Temperaturwert an den Seriellen Monitor gesendet.
  Serial.println(" °C"); // Hinter dem Temperaturwert wird am Seriellen Monitor nun noch die Einheit "C" angezeigt.
  
  sensorVal = (float)analogRead(sensorPin); // Read pressure sensor val (A1)
  filteredVal = (alpha * filteredVal) + ((1 - alpha) * sensorVal);// Low Pass Filter
  voltage = (filteredVal / 1024.0) * aRef; // calculate voltage
  psiVal = (voltage - 0.4784) / 14.504; // x=(y-b)/m

  Serial.print ("raw_adc "); Serial.print (sensorVal, 0);
  Serial.print(", filtered_adc "); Serial.println (filteredVal, 0);
  //Serial.print(", voltage ");
  //Serial.println(voltage, 2);

  updateOLED ();

  delay(200);
}

void updateOLED () {

  displayL.clearDisplay();
  displayL.setTextSize(1);
  displayL.setTextColor(WHITE);

  displayL.setCursor(5, 2);
  displayL.print("BENZINDRUCK ");

  displayL.setCursor(5, 40);
  displayL.print("OILTEMP");

  displayL.setCursor(80, 2);
  displayL.print(voltage, 2);
  displayL.print(" V");

  displayL.setTextSize(3);
  displayL.setCursor(30, 15);
  displayL.print(psiVal, 0);
  displayL.print("BAR");
 
  displayL.setTextSize(3);
  displayL.setCursor(65, 42);
  displayL.print(celsius, 0);
  displayL.print("C");

displayL.display();

  displayR.clearDisplay();
  displayR.setTextSize(1);
  displayR.setTextColor(WHITE);

  displayR.setCursor(5, 2);
  displayR.print("BENZINDRUCK ");

  displayR.setCursor(5, 40);
  displayR.print("OILTEMP");

  displayR.setCursor(80, 2);
  displayR.print(voltage, 2);
  displayR.print(" V");

  displayR.setTextSize(3);
  displayR.setCursor(30, 15);
  displayR.print(psiVal, 0);
  displayR.print("BAR");
 
  displayR.setTextSize(3);
  displayR.setCursor(65, 42);
  displayR.print(celsius, 0);
  displayR.print("C");

displayR.display();


}

Hallo michael_x, wie genau meinst Du das? :innocent:

guckstu constexpr

Wenn du denkst/willst , dass der Compiler den Ausdruck schon beim Compilieren ausrechnet, kannst du constexpr statt const schreiben.
constexpr ist sozusagen eine Verschärfung von const.

Ja constexpr ist typensicherer.

Du schriebst

Warum geht das in dem Falle nicht? :thinking:

Das verwirrt mich :innocent:

Wie soll der Compiler beim Übersetzen aus thermistor->readCelsius(); eine Konstante machen?

Typsicher ist beides, im Gegensatz zu #define

Lokale Variable, die erst bei der Definition (also in jedem loop Durchlauf neu mit eventuell unterschiedlichem Wert) initialisiert werden, sind durch const gegen irrtümliches Ändern in deinem Code geschützt. Das kann der Compiler natürlich erkennen und als Fehler markieren.

Und warum versuchst Du nicht die Ansteuerung wie im ersten Code?

Ich wurde U8g2 nehmen, ich habe mall gelesen das die Adresse 0xC will Adafruit für 128/32 Display haben.
Im anderen Thema wurde schon drüber geschrieben.

Könnte mit dieser Zeile in Adafruit_SSD1306.cpp zu tun haben:

// (0x3C for 32-pixel-tall displays, 0x3D for all others).
i2caddr = addr ? addr : ((HEIGHT == 32) ? 0x3C : 0x3D);

Könnte man durch i2caddr = addr; ersetzen (ungetestet).

Danke !!! Hatte doch gut in Erinnerung.

Die Definition von constexpr habe ich gelesen, aber nicht alles verstanden :roll_eyes:

Ich habe 2 konkrete Fragen zu diesem Fall, evtl. hat jemand Zeit und Lust zu versuchen, mir es zu erklären ? Danke euch :slight_smile:

  1. Wenn in jeder Loop „celsius“ ein neuer Wert zugewiesen wird, warum nehme ich dann const?
    Es ist doch dann eine Variable denke ich?

  2. Wenn man dort, warum auch immer, doch const nimmt, warum kann man nicht constexpr nehmen? Schließt es die Definition von expr aus?
    Das kommt ich nicht rauslesen bei der constexpr Definition.

Danke für etwas Hintergrundwissen :slight_smile:

Um dem Compiler zu sagen, dass du diesen Wert nach der Initialisierung nicht mehr ändern willst.
Darf danach nicht mehr links von einem Zuweisungsoperator ( = ) stehen.
Wenn doch, möchtest du das als Fehler gemeldet bekommen. Ob der Adressoperator erlaubt ist, könnte man mal ausprobieren. Weiß ich noch nicht .

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.

constexpr deklariert, dass es möglich ist, den Wert der Funktion oder Variable schon zur Kompilierzeit auszurechnen.
Die weiteren Erläuterungen erklären, in welchen Fällen das auch bei lokalen Variablen Konstanten geht, (evtl. auch erst ab C++17).

Das hatte ich soweit verstanden, ich meinte warum im loop ein const? Warum hier keine Variable?
const wird doch in jedem Durchlauf neu zugewiesen oder übersehe ich etwas?