Hallo zusammen,
ich heisse Christian und beschäftige mich seit einiger Zeit mit dem Arduino, bin aber weit entfernt vom Profi.
Die komplizierteren sketches kopiere ich mir zusammen und passe sie meinen Bedürfnissen an.
In einem relativ langem Sketch, habe ich das Problem, dass bei drehen des Drehgebers die Temperaturanzeige einen Fehler erzeugt.
Ich habe die wichtigen Teile für eine bessere Übersicht kopiert und auch hier kommt der Fehler vor.
Leider blicke ich bei dem Programmteil getTemp nicht ganz durch, daher weiß ich auch nicht warum der Fehler entsteht.
Wenn ich den Encoder drehe, dann gibt es zwischndrin den Wert 0 für die Temperatur aus.
Kann mir evtl. jemand sagen woran das liegen könnte?
int DrehRechts=2; //Drehencoder
int DrehLinks =3; //Drehencoder
int Taster=4; //Drehencoder
int T;
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <OneWire.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int DS18S20_Pin = 13;
OneWire ds(DS18S20_Pin);
volatile int number = 0;
volatile int number2 = 0;
volatile boolean halfleft = false; // Used in both interrupt routines
volatile boolean halfright = false; // Used in both interrupt routines
int drehen=0;
void setup() {
lcd.begin(20,4);
lcd.clear();
lcd.setCursor(9,2);
lcd.print("T:");
pinMode (10,OUTPUT);
digitalWrite(10,HIGH);
attachInterrupt(1, isr_2, FALLING); // Interrupt encoder
attachInterrupt(0, isr_3, FALLING);
sei();
Serial.begin(9600);
}
void loop() {
lcd.setCursor(11,2);
lcd.print(T);
T=getTemp();
if (T<=22){
digitalWrite(10,LOW);
}else{
digitalWrite(10,HIGH);
}
Serial.println(T);
}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
//return 80;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return 70;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return 60;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
void isr_2()
{ // Pin2 went LOW
delay(1); // Debounce time
if(digitalRead(DrehLinks) == LOW){
if(digitalRead(DrehRechts) == HIGH && halfright == false) //Wert Decoder ++
{
halfright = true;
}
if(digitalRead(DrehRechts) == LOW && halfleft == true)
{
halfleft = false;
{
number++;
}
}
}
}
void isr_3()
{
delay(1); // Debounce time
if(digitalRead(DrehRechts) == LOW)
{
if(digitalRead(DrehLinks) == HIGH && halfleft == false) // Wert Decoder --
{
halfleft = true;
}
if(digitalRead(DrehLinks) == LOW && halfright == true)
{
halfright = false;
{
number--;
}
}
}
}
Hallo,
also wenn dann den gesamten Code, notfalls als Anhang wenn zu groß. Und dann bitte nicht in quote einbetten sonder in in Code Tags, dass </> Zeichen links über den Smilies Sonst kommt wie du siehst Mist raus, Smilie statt 8 usw.
Hallo Doc,
danke für die schnelle Antwort.
Das ist der gesamte Code, zwar etwas gekürzt, aber der Fehler kommt auch hier vor.
Noch etwas: Mal zeigt er 0 an, ein anderes Mal 80, also aus folgendem Teil:
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return 80;
}
Danke
Christian
int DrehRechts=2; //Drehencoder
int DrehLinks =3; //Drehencoder
int Taster=4; //Drehencoder
int T;
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <OneWire.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int DS18S20_Pin = 13;
OneWire ds(DS18S20_Pin);
volatile int number = 0;
volatile int number2 = 0;
volatile boolean halfleft = false; // Used in both interrupt routines
volatile boolean halfright = false; // Used in both interrupt routines
int drehen=0;
void setup() {
lcd.begin(20,4);
lcd.clear();
lcd.setCursor(9,2);
lcd.print("T:");
pinMode (10,OUTPUT);
digitalWrite(10,HIGH);
attachInterrupt(1, isr_2, FALLING); // Interrupt encoder
attachInterrupt(0, isr_3, FALLING);
sei();
Serial.begin(9600);
}
void loop() {
lcd.setCursor(11,2);
lcd.print(T);
T=getTemp();
if (T<=22){
digitalWrite(10,LOW);
}else{
digitalWrite(10,HIGH);
}
lcd.setCursor(9,3);
lcd.print(number);
Serial.println(T);
}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return 80;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return 70;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return 60;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
void isr_2()
{ // Pin2 went LOW
delay(1); // Debounce time
if(digitalRead(DrehLinks) == LOW){
if(digitalRead(DrehRechts) == HIGH && halfright == false) //Wert Decoder ++
{
halfright = true;
}
if(digitalRead(DrehRechts) == LOW && halfleft == true)
{
halfleft = false;
{
number++;
}
}
}
}
void isr_3()
{
delay(1); // Debounce time
if(digitalRead(DrehRechts) == LOW)
{
if(digitalRead(DrehLinks) == HIGH && halfleft == false) // Wert Decoder --
{
halfleft = true;
}
if(digitalRead(DrehLinks) == LOW && halfright == true)
{
halfright = false;
{
number--;
}
}
}
}
Ja, so ist der Sketch besser lesbar.
Allerdings auch hier kann ich nicht erkennen, wo du die Temperatur auf das LCD schreibst.
Nur eine Vermutung:
Da dein Drehgeber per IRQ abgefragt wird, kann es passieren, dass der Sensor nicht sauber ausgelesen wird.
Der braucht rel. lange, um seine Temperatur komplett auszugeben.
Was möchtest du überhaupt mit dem Drehgeber erreichen ?
Hallo Dieter,
hier erneut der Sketch mit der Markierung der Temperaturausgabe.
In diesem Sketch macht der Drehgeber nichts, im original führt er durch ein Menü. Das Menü habe ich nur weggelassen, da es zu unübersichtlich ist und der Fehler hier auch aufkommt.
Christian
int DrehRechts=2; //Drehencoder
int DrehLinks =3; //Drehencoder
int Taster=4; //Drehencoder
int T;
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <OneWire.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int DS18S20_Pin = 13;
OneWire ds(DS18S20_Pin);
volatile int number = 0;
volatile int number2 = 0;
volatile boolean halfleft = false; // Used in both interrupt routines
volatile boolean halfright = false; // Used in both interrupt routines
int drehen=0;
void setup() {
lcd.begin(20,4);
lcd.clear();
lcd.setCursor(9,2);
lcd.print("T:");
pinMode (10,OUTPUT);
digitalWrite(10,HIGH);
attachInterrupt(1, isr_2, FALLING); // Interrupt encoder
attachInterrupt(0, isr_3, FALLING);
sei();
Serial.begin(9600);
}
void loop() {
lcd.setCursor(11,2);
lcd.print(T);
T=getTemp(); // Temperatur an T
if (T<=22){ //Heizung EIN
digitalWrite(10,LOW);
}else{
digitalWrite(10,HIGH);
}
lcd.setCursor(9,3); //Temp auf Display ausgeben
lcd.print(number);
Serial.println(T);
}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return 80;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return 70;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return 60;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
void isr_2()
{ // Pin2 went LOW
delay(1); // Debounce time
if(digitalRead(DrehLinks) == LOW){
if(digitalRead(DrehRechts) == HIGH && halfright == false) //Wert Decoder ++
{
halfright = true;
}
if(digitalRead(DrehRechts) == LOW && halfleft == true)
{
halfleft = false;
{
number++;
}
}
}
}
void isr_3()
{
delay(1); // Debounce time
if(digitalRead(DrehRechts) == LOW)
{
if(digitalRead(DrehLinks) == HIGH && halfleft == false) // Wert Decoder --
{
halfleft = true;
}
if(digitalRead(DrehLinks) == LOW && halfright == true)
{
halfright = false;
{
number--;
}
}
}
}
Ok, du gibst die Temperatur am seriellen Monitor aus, nicht am LCD.
Mein Tipp, stoppe das Auslesen des Sensors beim Drehen des Gebers und starte wieder nach Beendigung des Drehens.
Oder setze die Pausen zwischen dem Auslesen des Sensors höher.
Dieter,
gleich in der zweiten Zeile im loop schreibe ich auf LCD, weiter unten auch an seriellen Monitor.
Ich habe bereits probiert, Pausen zwischen Auslesen des Sensors zu setzen, irgendwann passiert es jedoch auch hier.
Wie kann ich denn definieren wann das Drhen beginnt und wann es endet?
Nimm eine Encoder Lib ohne Interrupt
Ich sehe in der Temperaturabfrage auch nicht das korrekte Timing
In jedem Loop die getTemp auf rufen macht keinen Sinn
christian_p:
Dieter,
gleich in der zweiten Zeile im loop schreibe ich auf LCD, weiter unten auch an seriellen Monitor.
Ich habe bereits probiert, Pausen zwischen Auslesen des Sensors zu setzen, irgendwann passiert es jedoch auch hier.
Wie kann ich denn definieren wann das Drhen beginnt und wann es endet?
Ups...sorry, das habe ich tatsächlich übersehen.
Vermutlich weil du erst danach die Variable "T" mit aktuellen Daten füllst.
Und da kann auch das Problem liegen.
Du solltest das tauschen, dann könnte das Problem seltener oder gelöst sein.
Oder wie EESpanol schreibt, das Auslesen der Temperatur per Timer (alle 5 sek.) zu lösen.
Hallo zusammen,
ich habe nun die Abfrage auf alle 3sek gesetzt und auch die Abfrage nach jeder Veränderung des Encoders für 1 sek gesperrt.
Nun funktioniert es, bzw. die Wahrscheinlichkeit ist sehr gering.
Es ist sicher nicht die sauberste Lösung, aber für mich ist das OK.
Danke für eure Hilfe
Christiam
christian_p:
Hallo zusammen,
ich habe nun die Abfrage auf alle 3sek gesetzt und auch die Abfrage nach jeder Veränderung des Encoders für 1 sek gesperrt.
Nun funktioniert es, bzw. die Wahrscheinlichkeit ist sehr gering.
Es ist sicher nicht die sauberste Lösung, aber für mich ist das OK.
Danke für eure Hilfe
Christiam
Prima und danke für die Rückmeldung.
Ich sehe das schon als richtige Lösung, da man den Sensor nicht ständig auslesen muss bzw. darf.
Hallo,
aber doch bitte nicht so. Christian muss lernen wie man mittels millis() in zeitlichen Intervallen bestimmte Dinge wiederholt und er sollte sich die Bsp. der Dallas Lib anschauen. Da wird auf die 750ms Wartezeit auch eingegangen ohne Blockierung.
Vorallen die beiden "WaitForConversion" Bsp.