Temparatursensor bremmst den Arduino aus

Hallo zusammen.

Ich habe einen Knoten im Kopf und wollte euch um Hilfe bitten.

Ich habe mir ein Uhr für mein Motorrad gebaut, welche mir die Uhrzeit :slight_smile: , die Heizstufe meine Griffheizung und die Außentemp anzeigen soll.

Das ganze wird über ein 32*128 OLED Display angezeigt.

Wenn ich alle Funktionen am Display angezeigt bekomme, reagiert mein Taster nicht mehr sauber.

Ich verwende ein Arduino Uno, DS18B20 Temparatursensor, SSD1306 OLED Display.

Wenn der Sensor nicht abgefragt wird, klappt alles ganz wie gewünscht.

Jetzt mein Problem:

Ich denke die Abtastrate vom DS18B20 blockiert die Taster Erkennung.
Jetzt meine frage. Wo ist mein Denkfehler?

Ich habe schon versucht kleine Programmabschnitte für jede Funktion zu erstellen.
Auch das hat nicht funktioniert.

PS Ich bin neu und nicht so Erfahren beim Programmieren. :slight_smile:

Jetzt das Spannende :wink: :smiley: :smiley:
Der Sketch:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>

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

float Celsius = 0;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(4);

#include "Sodaq_DS3231.h"
/* * Tastendrücke zählen */
int switchPin = 2;                     // Schalter ist mit Pin 2 verbunden
int val;                                // Variable für den Pin Zustand
int buttonState;                        // Variable für den letzten Schalterzustand
int buttonPresses = 0;                  // Wie oft ist der Schalter gedrückt

const int buz = 6;

void setup() {
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //display.clearDisplay();
  display.display();
  rtc.begin();                            // initialisiere RTC
  sensors.begin();                        // initialisiere Temp sens
  
}

void zeit(){
    display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(3);
  display.setCursor(20, 0);                    //Start at Oled 20 in Zeile 1
  
  
 DateTime now = rtc.now();               //get the current date-time

  if (now.hour() < 10)                    //führende 0 bei der Stunde
  {
    display.print("0");
  }
  
  display.print(now.hour(), DEC);              //Anzeige Stunde
  display.print(':');
  if (now.minute() < 10)                    //wie oben: führende 0 bei der Minute 
  {
    display.print("0");
  }
  
 
  display.print(now.minute(), DEC);            //Anzeige der Minute

}

   void temp(){
        sensors.requestTemperatures();
    Celsius = sensors.getTempCByIndex(0);
    display.setTextColor(WHITE);
    display.setTextSize(1);
    display.setCursor(85,25);
    display.print(Celsius);    //read registers and display the temperature
    display.print(" C");
   }



void taster() {  

    val = digitalRead(switchPin);           // Eingabewert lesen und in val speichern
  delay(10);
  if (val != buttonState)
  {                                       // Der Zustand des Schalters hat sich verändert
    if (val == LOW)
    {                                     // Ist der Schalter gedrückt?
      buttonPresses++;                    // Inkrementieren der Variablen buttonPresses

    }
  }
  buttonPresses = buttonPresses % 7;       // Der Zähler für den Neustart
  buttonState = val;                        // Den Zustand merken

  if (buttonPresses == 0)                   // 0 Heizstufe
  {
    analogWrite (buz, 0);
 
  }
  
  if (buttonPresses == 1)                   // 1 Heizstufe
  { 
    analogWrite (buz, 30);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 25);                    //Start bei Stelle 1 in Zeile 25
    display.print("1");
  }
  if (buttonPresses == 2)                   // 2 Heizstufe
  { 
    analogWrite (buz, 80);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(12, 25);                    //Start bei Stelle 12 in Zeile 25
    display.print("2");
  }
  if (buttonPresses == 3)                   // 3 Heizstufe
  {
    analogWrite (buz, 120);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(24, 25);                    //Start bei Stelle 24 in Zeile 25
    display.print("3");
  }

  if (buttonPresses == 4)                   // 4 Heizstufe
  { 
    analogWrite (buz, 160);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(36, 25);                    //Start bei Stelle 36 in Zeile 25
    display.print("4");
  }

  if (buttonPresses == 5)                   // 5 Heizstufe
  { 
    analogWrite (buz, 200);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(48, 25);                    //Start bei Stelle 48 in Zeile 25
    display.print("5");
  }

  if (buttonPresses == 6)                   // 6 Heizstufe
  { 
    analogWrite (buz, 250);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(60, 25);                    //Start bei Stelle 60 in Zeile 25
    display.print("6");
  }
  
  if (buttonPresses == 7)                  // Ausschalten
  { 
    analogWrite (buz,0);
  }
 display.display();

  }

void loop() {
  zeit();
  taster();
//temp();
}

Setze deine Sketch bitte in Code-Tags und verwende dazu die Schaltfläche </> oben links im Editorfenster.
Dann kann jeder den Sketch auch richtig lesen.

Ich sehe nicht, wo in deinem Sketch der Sensor gelesen wird.

Ah....ok. Doch gefunden.
Schlecht lesbar das Teil.

Du verwendest offenbar ein falsches Beispiel, die blockiert.

Es gibt in der Lib zum Sensor auch eine nicht blockierende Version.

Hi

Code bitte in Code-Tags.
Du fragst die Sensoren BLOCKIEREND ab - da musst Du Dich nicht wundern, daß die Abfrage ... blockiert.
Du KANNST die Generierung der Temperatur auch anstoßen und dann (je nach Auflösung bis zu 750ms) später die aktuelle Temperatur auslesen.
Während der Generierung bekommst Du die zuletzt generierte Temperatur zurück gegeben.
Wenn Du 'immer' eine neue Temperatur anforderst, wird die bereits Vorhandene bestenfalls eine Sekunde alt sein - sollte hier keinerlei Rolle spielen (bei 12 Bit ist die Temperatur eh bereits 750ms alt ... ).

Baue Deinen Sketch so um, daß alle Sekunde die Temperatur ausgelesen wird und DANN die neue Temperatur-Generierung angestoßen wird.

MfG

Du musst im Setup dem Sensor sagen, dass er nicht warten soll: sensors.setWaitForConversion(false);
Dann musst Du selbst dafür sorgen, dass zwischen requestTemperatures(); und getTempCByIndex(0);
mindestens 750 ms Zeit ist.
Das musst Du nicht blockierend mit millis erledigen.

Gruß Tommy

Edit: Die Variante vom postmaster-ino ist auch machbar und evtl. einfacher unzusetzen.

Vielen Dank für eure schnelle Hilfe.

Ich werde die Tips mal ausprobieren und berichten.

Besten Dank. :slight_smile:

Den Button für den Code habe ich jetzt auch gefunden. :smiley:

Arduino_Frischling:
Den Button für den Code habe ich jetzt auch gefunden. :smiley:

Und warum benutzt Du ihn nicht? Das kannst Du auch nachträglich noch ändern.

Gruß Tommy

Arduino_Frischling:
Den Button für den Code habe ich jetzt auch gefunden. :smiley:

Und du kannst du auch noch nachträglich im ersten Post machen.

Und die Temperatur musst du auch nicht in jedem loop abfragen.

Hi

Aber in jedem loop() kann man abfragen, ob bereits 1000ms vergangen sind.
Dann liest man die zuletzt angefragte Temperatur aus und lässt direkt 'eine Neue' generieren.
Außerdem merkt man sich die aktuelle zeit, für den nächsten Zugriff, Der ja erst in 1000ms erfolgen soll.
Da Das nur alle 1000ms greift, passiert dem Rest des Sketch dabei auch nichts.

MfG

Wichtig ist, dass man den Sensor nicht pausenlos mit Requestanforderungen und Auslesen traktiert.

Ich hatte es etwas anders gemacht, es kommt aber auf den ähnlichen Ablauf raus.

  1. requestTemperatures wenn nicht isRequestet + Zeitpunkt merken + Flag isRequestet setzen
  2. nach 1 Sekunde und isRequestet: Temperatur lesen, isRequestet zurücksetzen

Man kann beide in jeweils eine Funktion setzen.

Gruß Tommy

Ist eventuell nicht relevant hier. Aber die Dallas-Sensoren werden selber warm wenn man sie zu
häufig ausliest. Also nicht alle paar Millisekunde auslesen sondern ruhig mal 30 Sekunden warten.
Das sollte für diese Aufgabe völlig reichen.

Ulli

Hi

Als Kühlmittel-Sensor sollte die Eigenerwärmung im Rauschen untergehen.
Oder Anders: Wenn die Eigenerwärmung zum Tragen kommt, ist der Motor definitiv nicht am Laufen.

Bei Messung der stehenden Luft: ok.
Aber auch hier beim Mopped sollten wir von (sogar recht schnell) bewegter Luft ausgehen können.

Wie gesagt: Ich stimme Dir zu, wenn's um die Messung einer Raum-Temperatur in/an einem Schalter geht, Der recht wenig Luft-Verwirbelung abbekommt.

MfG

Ja, eine Verbesserung kannst du einbauen, damit der Sketch hier besser lesbar ist.

Verwende Strg + T in der IDE um den Sketch zu formatieren.
Und die unnötigen Leerzeilen löschen, diese machen das Lesen schwer.
Danach den vorhandenen Sketch hier austauschen.

Hallo zusammen,

nach längerer Zeit bin ich nun dazu gekommen das Projekt zu bearbeiten.
Noch mals vielen Dank für eure Unterstützung.

Wenn ich ein paar Hilfen für mich habt, dann nur raus damit. :slight_smile:
Ich bin für jede Hilfe dankbar.

Nun der Sketch

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 3


OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);
float Celsius = 0;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(4);

#include "Sodaq_DS3231.h"
/* * Tastendrücke zählen */
int switchPin = 2;                     // Schalter ist mit Pin 2 verbunden
int val;                                // Variable für den Pin Zustand
int buttonState;                        // Variable für den letzten Schalterzustand
int buttonPresses = 0;                  // Wie oft ist der Schalter gedrückt
const int buz = 6;




void setup() {
   
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();
  rtc.begin();                            // initialisiere RTC
  sensors.begin();                        // initialisiere Temp sens


}

void loop() {  

  if (millis() % 30000 < 500){           //Timer für die Temparaturabfrage

 sensors.requestTemperatures();
 Celsius = sensors.getTempCByIndex(0);
}
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(3);
  display.setCursor(20, 0);                    //Start at Oled 20 in Zeile 1

  
 DateTime now = rtc.now();               //get the current date-time

  if (now.hour() < 10)                    //führende 0 bei der Stunde
  {
    display.print("0");
  }
  
  display.print(now.hour(), DEC);              //Anzeige Stunde
  display.print(':');
  if (now.minute() < 10)                    //wie oben: führende 0 bei der Minute 
  {
    display.print("0");
  }
  
 
  display.print(now.minute(), DEC);            //Anzeige der Minute
  //display.display();
 
    display.setTextColor(WHITE);
    display.setTextSize(1);
    display.setCursor(85,25);
    display.print(Celsius);    //read registers and display the temperature
    display.print(" C");


    val = digitalRead(switchPin);           // Eingabewert lesen und in val speichern
  delay(10);
  if (val != buttonState)
  {                                       // Der Zustand des Schalters hat sich verändert
    if (val == LOW)
    {                                     // Ist der Schalter gedrückt?
      buttonPresses++;                    // Inkrementieren der Variablen buttonPresses
      //Serial.print("Schalter wurde ");
      //Serial.print(buttonPresses);
      //Serial.println(" gedrueckt");
    }
  }
  buttonPresses = buttonPresses % 7;       // Der Zähler für den Neustart
  buttonState = val;                        // Den Zustand merken

  if (buttonPresses == 0)                   // 0 Heizstufe
  {
    analogWrite (buz, 0);
 
  }
  
  if (buttonPresses == 1)                   // 1 Heizstufe
  { 
    analogWrite (buz, 30);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 25);                    //Start bei Stelle 1 in Zeile 1
    display.print("1");
  }
  if (buttonPresses == 2)                   // 2 Heizstufe
  { 
    analogWrite (buz, 80);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(12, 25);                    //Start bei Stelle 1 in Zeile 1
    display.print("2");
  }
  if (buttonPresses == 3)                   // 3 Heizstufe
  {
    analogWrite (buz, 120);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(24, 25);                    //Start bei Stelle 1 in Zeile 1
    display.print("3");
  }

  if (buttonPresses == 4)                   // 4 Heizstufe
  { 
    analogWrite (buz, 160);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(36, 25);                    //Start bei Stelle 1 in Zeile 1
    display.print("4");
  }

  if (buttonPresses == 5)                   // 5 Heizstufe
  { 
    analogWrite (buz, 200);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(48, 25);                    //Start bei Stelle 1 in Zeile 1
    display.print("5");
  }

  if (buttonPresses == 6)                   // 6 Heizstufe
  { 
    analogWrite (buz, 250);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(60, 25);                    //Start bei Stelle 1 in Zeile 1
    display.print("6");
  }
  
  if (buttonPresses == 7)                  // Ausschalten
  { 
    analogWrite (buz,0);
  }
 display.display();

  }

...

Da Du kein Fragezeichen benutzt hast, wirst Du wohl keine Frage haben.
Da Du weder die Leerzeilen entfernt hast, noch STRG+T in der IDE drücktest, wohl auch nicht wollen, daß man sich Deinen Sketch anschaut.
(Es sind nicht viele Änderungen, Die STRG+T vornimmt, zugegeben)

Ich fasse zusammen:

  • kein Problem
  • kein Interesse, daß Das Jemand anschaut

Dann aber eine Frage: Was macht Das dann hier?

MfG

Und unsere Anmerkungen werden auch komplett ignoriert.

Dann weiterhin viel Spass mit deinem Teil.

Arduino_Frischling:
Wenn ich ein paar Hilfen für mich habt, dann nur raus damit. :slight_smile:

Er will sich ja auch selbst helfen. :wink:

Gruß Tommy

Tommy56:
Er will sich ja auch selbst helfen. :wink:

Gruß Tommy

Das machen wir doch alle irgendwie.
Nur das wir auch Tipps anderer annehmen.

Tommy56:
Du musst im Setup dem Sensor sagen, dass er nicht warten soll: sensors.setWaitForConversion(false);
Dann musst Du selbst dafür sorgen, dass zwischen requestTemperatures(); und getTempCByIndex(0);
mindestens 750 ms Zeit ist.

Habe ich mal ausprobiert, weil mir die Bremse auch erst durch dieses Thema aufgefallen ist. Funktioniert wunderbar. Ich mache eh nur alle 2 Sekunden eine Aulesung, und hatte da aber dann jedesmal noch so um die 740ms Zwangsstopp und 60ms Ausgabe aufs Display, obwohl der LOOP ansonsten mit weniger als einer Millisekunde durchläuft. So sind jetzt die längsten Loop durchläufe 60ms. Für zwei Messungen holen und aufs Display ausgeben. Das waren vorher 800ms. Die Display-Ausgabe ist jetzt das einzige was noch bremst.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h> // LCD Display

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int delayTimeM1 = 2000; // Alle 2 Sekunden Temperatur-Auswertung
unsigned long VorherMillesM1 = 0;

const unsigned long Baud_Rate = 9600;
const unsigned char One_Wire_Bus = 2; // Sensoren auf Pin
OneWire oneWire(One_Wire_Bus);
DallasTemperature sensoren (&oneWire);

int Anzahl_Sensoren = 0;
int is = 0; // Zähler für die Sensoren
int ia = 0; // Zähler für die Adressstellen 0-7
int Sensor = 0;

DeviceAddress tempDeviceAddress; // Für die Adressausgabe
int numberOfDevices; // Für die Adressausgabe
//---------------------------------------------------------------------------
void setup()
{
  sensoren.begin();
  Serial.begin(Baud_Rate);
  lcd.begin(20, 4);
  lcd.backlight();
  lcd.clear();

  // Anzahl der Sesoren ermitteln
  Anzahl_Sensoren = sensoren.getDeviceCount();

  // Ermitteln der Sensor-Adressen
  for (is = 0; is < Anzahl_Sensoren; is++)
  {
    if (sensoren.getAddress(tempDeviceAddress, is))
    {
      Serial.println ();
      printAddress(tempDeviceAddress);
    }
  }
  // Kein blockierendes Warten auf die Messung!!
  // Spart 740ms Loop Zeit bei der Messung
  sensoren.setWaitForConversion(false);
}
//---------------------------------------------------------------------------
// Ausgabe der Sensor-Adressen
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t ia = 0; ia < 8; ia++)
  {
    if (deviceAddress[ia] < 16)
    {
      Serial.print("0"); //ist die Hex Adresse kleiner 16 dann erste Stelle eine "0"
    }
    Serial.print(deviceAddress[ia], HEX);
  }
}
//---------------------------------------------------------------------------
void loop()
{
  if (millis() - VorherMillesM1 >= delayTimeM1)
  {
    VorherMillesM1 = millis();

    //Temperaturen Aulesen
    if (Sensor == 0) { //Bei jedem ersten Durchgang Temperaturen holen
      sensoren.requestTemperatures();
    }

    // Hier werden die Temperaturen aufs Display gebracht
    if (Sensor < Anzahl_Sensoren)
    { Sensor ++;
      float temperatur = sensoren.getTempCByIndex(Sensor - 1);
      lcd.setCursor (0, (Sensor - 1));
      lcd.print ("Temperatur");
      lcd.setCursor (11, (Sensor - 1));
      lcd.print (Sensor);
      lcd.setCursor (14, (Sensor - 1));
      lcd.print (temperatur);
      if (Sensor == Anzahl_Sensoren)
      {
        Sensor = 0;
      }
    }
  }
}