Go Down

Topic: Drehgeber gibt bei längerem Code falsche Werte aus (Read 1 time) previous topic - next topic

HotSystems

Der Aufbau ist vll noch nicht ganz optimal. Bin noch blutiger Anfänger.
Das ist doch kein Problem, wir sind alle mal angefangen.

Wenn du aber die gemachten Ratschläge befolgst, wird es einfacher und der Sketch übersichtlicher.

Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Doc_Arduino

Hallo,

das mit der Klammersetzung haste sicherlich nirgendswo so gesehen.
Hab den Code mal formatiert. Jetzt siehst du auch was deine obige millis Funktion macht.
Sie macht nämlich nichts, außer eine Variable zu aktualisieren.
Und ob deine Temperaturvariablen am Anfang der loop als lokale richtig sind, waage ich anzuweifeln.
Denn diese werden mit jeder neuen loop Runde neu erstellt.
Und nicht initialisierte lokale Variablen haben keinen definierten Inhalt/Wert.
Praktisch alles außer present.
Dann haste 2x Serial.available hintereinander mit if und while. Bestimmt auch nicht so wie gedacht.
Wild zusammen kopiert nehme ich an. Das klappt leider fast nie.


Code: [Select]
 #include <Wire.h>
  #include <OneWire.h>
  #include <LiquidCrystal_I2C.h>
  
  // Display
  
   int CLK1 = 3;  // Connected to CLK on KY-040
   int DT1 = 4;  // Connected to DT on KY-040
   int CLK2 = 5;  // Connected to CLK on KY-040
   int DT2 = 6;  // Connected to DT on KY-040
   int SollTemp = 0;
   int Timer = 0;
   int CLK1Last;
   int aVal;
   boolean bCW1;
   int CLK2Last;
   int bVal;
   boolean bCW2;
   int Heizung = 9;
   OneWire  ds(10);
   unsigned long previousMillis = 0;
   const long interval = 1000;
   LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
  
void setup()  
{
    Serial.begin(9600);
    lcd.begin(20,4);  
    pinMode (CLK1,INPUT);
    pinMode (DT1,INPUT);
    pinMode(Heizung,OUTPUT);
    CLK1Last = digitalRead(CLK1);
}

  
void loop()  
{
    
    //Temperatur
    byte i;
    byte present = 0;
    byte type_s;
    byte data[12];
    byte addr[8];
    float celsius;
  
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
    }
      
    // when characters arrive over the serial port...
    if (Serial.available() > 0) {
      // wait a bit for the entire message to arrive
      // clear the screen
      lcd.clear();
      // read all the available characters
      while (Serial.available() > 0) {
        // display each character to the LCD
        lcd.write(Serial.read());
      }
    }
    
    if ( !ds.search(addr)) {
      Serial.println();
      ds.reset_search();
    }
    
    Serial.print("ROM =");
    for( i = 0; i < 8; i++) {
      Serial.write(' ');
      Serial.print(addr[i], HEX);
    }
  
    if (OneWire::crc8(addr, 7) != addr[7]) {
        Serial.println("CRC is not valid!");
    }
    
    Serial.println();
    // the first ROM byte indicates which chip
    switch (addr[0]) {
      Serial.println("  Chip = DS18B20");
      type_s = 0;
    }
    
    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);        // start conversion, with parasite power on at the end
    present = ds.reset();
    ds.select(addr);  
    ds.write(0xBE);         // Read Scratchpad
    Serial.print("  Data = ");
    Serial.print(present, HEX);
    Serial.print(" ");
    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
      Serial.print(data[i], HEX);
      Serial.print(" ");
    }
    
    Serial.print(" CRC=");
    Serial.print(OneWire::crc8(data, 8), HEX);
    Serial.println();
    // Convert the data to actual temperature
    // because the result is a 16 bit signed integer, it should
    // be stored to an "int16_t" type, which is always 16 bits
    // even when compiled on a 32 bit processor.
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    }
    else {
      byte cfg = (data[4] & 0x60);
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      //// default is 12 bit resolution, 750 ms conversion time
    }
    
    aVal = digitalRead(CLK1);
    if (aVal != CLK1Last){ // Means the knob is rotating
      // if the knob is rotating, we need to determine direction
      // We do that by reading pin B.
      if (digitalRead(DT1) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise
        SollTemp ++;
        bCW1 = true;
      }
      else {  // Otherwise B changed first and we're moving CCW
          bCW1 = false;
          SollTemp--;
      }
      
       Serial.print ("Rotated: ");
       if (bCW1){
         Serial.println ("clockwise");
       }else{
         Serial.println("counterclockwise");
       }
       Serial.print("SollTemp: ");
       Serial.println(SollTemp);
     }
     CLK1Last = aVal;
  
     bVal = digitalRead(CLK2);
    
     if (bVal != CLK2Last){ // Means the knob is rotating
       // if the knob is rotating, we need to determine direction
       // We do that by reading pin B.
       if (digitalRead(DT2) != bVal) {  // Means pin A Changed first - We're Rotating Clockwise
         Timer ++;
         bCW2 = true;
       } else {// Otherwise B changed first and we're moving CCW
         bCW2 = false;
         Timer--;
       }
       Serial.print ("Rotated: ");
       if (bCW2){
         Serial.println ("clockwise");
       }
       else{
         Serial.println("counterclockwise");
       }
      
       Serial.print("Timer: ");
       Serial.println(Timer);
     }
     CLK2Last = bVal;
 
    if (celsius < SollTemp) {
      digitalWrite(Heizung, HIGH);
    }
    else {
      digitalWrite(Heizung, LOW);
    }
  
    celsius = (float)raw / 16.0;
    lcd.setCursor(0,0);
    lcd.print("Soll Temp:");
    lcd.setCursor(11,0);
    lcd.print(SollTemp);
    lcd.setCursor(16,0);
    lcd.print("Grad");
    lcd.setCursor(0,1);
    lcd.print("Ist  Temp: ");
    lcd.setCursor(11,1);
    lcd.print(celsius);
    lcd.setCursor(16,1);
    lcd.print("Grad");
    lcd.setCursor(0,2);
    lcd.print("Timer:");
    lcd.setCursor(11,2);
    lcd.print(Timer);
    lcd.setCursor(16,2);
    lcd.print("Min");

}  // loop Ende

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Matthias321

Danke für Eure Hilfe! Muss ich dann die Variable meiner Temperatur mit Hilfe von Millis für die gewisse Zeit festsetzen?

Doc_Arduino

Hallo,

ich weis nicht wo du den Code her hast, dass einfachste wäre jedoch für dich du nimmst die Lib für den Sensor.
https://github.com/milesburton/Arduino-Temperature-Control-Library
Hier sind gute Bsp. dabei die man sich anschauen sollte.
Conversion 2 blockiert zum Bsp. nicht.
Im Grunde läuft das immer gleich ab. Ob blockierend oder nicht.
Der Sensor bekommt ein Request Befehlt geschickt das er messen soll. Das dauert eben bis zu 750ms lang.
Nach der Wartezeit kann man den Messwert abholen.
Ob man während der Wartezeit nochwas macht oder nicht ist erstmal egal.
Macht aber keinen Sinn dabei nichts zu tun. Deswegen nimmt man millis um während der Wartezeit andere sinnvolle Dinge dem µC aufzuhalsen.


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Die Lib wollte ich auch schon empfehlen.

Den Sensor nicht-blockierend auszulesen muss man erst mal nicht unbedingt machen. Gerade bei den geringen Kenntnissen. Aber es sollte schon mal eine Verbesserung darstellen wenn man den Sensor nicht dauernd ausliest. Dann sollte genug Zeit bleiben den Drehgeber abzuarbeiten.

Matthias321

Vielen Dank für eure Unterstützung. ich habe es mit Hilfe der WaitForConversion2 realisiert und es funktionieren sowohl die beiden Drehgeber als auch die Temperatur. Pflege ich jetzt jedoch noch das Display ein, kommt wieder kein vernünftiger Wert der Drehgeber bei rum.

Matthias321

Es hat sich herausgestellt, dass sobald ich Zeilen auf das Display ausgebe, die werte nicht mehr stimmen. Schreibe ich nichts auf dem Bildschirm, bekomme ich im Seriellen Monitor reale Werte. Kann jemand Helfen?

Doc_Arduino

Hallo,

unsere Glaskugeln sind im Moment milchig. Du weist warum?  ;)
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Matthias321

Sorry :)
Code: [Select]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define I2C_ADDR    0x27 // <<----- Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
#define ONE_WIRE_BUS 10
int x = 0;
int y = 0;
//int n = 1;
int row = 20; //  <<----- My LCD was 16x2
int column = 4; //  <<----- My LCD was 16x2
int CLK1 = 3;  // Connected to CLK on KY-040
int DT1 = 4;  // Connected to DT on KY-040
int SollTemp = 0;
int CLK1Last; 
int aVal;
boolean bCW1;
int CLK2 = 5;  // Connected to CLK on KY-040
int DT2 = 6;  // Connected to DT on KY-040
int Timer = 0;
int CLK2Last; 
int bVal;
boolean bCW2;
 
LiquidCrystal_I2C   lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
OneWire oneWire(ONE_WIRE_BUS);

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

DeviceAddress tempDeviceAddress;

int  resolution = 12;
unsigned long lastTempRequest = 0;
int  delayInMillis = 0;
float temperature = 0.0;
int  idle = 0;
void setup()
{
  lcd.begin (row,column);
// Switch on the backlight
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home ();         
  pinMode (CLK1,INPUT);
   pinMode (DT1,INPUT);
   /* Read Pin A
   Whatever state it's in will reflect the last position   
   */
   CLK1Last = digitalRead(CLK1);   
   Serial.begin (9600);
}

void loop()
{
 lcd.setCursor(0,0);
  lcd.print("Soll Temp:");



 aVal = digitalRead(CLK1);
   if (aVal != CLK1Last){ // Means the knob is rotating
     // if the knob is rotating, we need to determine direction
     // We do that by reading pin B.
     if (digitalRead(DT1) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise
       SollTemp ++;
       bCW1 = true;
     } else {// Otherwise B changed first and we're moving CCW
       bCW1 = false;
       SollTemp--;
     }
     Serial.print("SollTemp: ");
     Serial.println(SollTemp);
     
   }
   CLK1Last = aVal;

   bVal = digitalRead(CLK2);
   if (bVal != CLK2Last){ // Means the knob is rotating
     // if the knob is rotating, we need to determine direction
     // We do that by reading pin B.
     if (digitalRead(DT2) != bVal) {  // Means pin A Changed first - We're Rotating Clockwise
       Timer ++;
       bCW2 = true;
     } else {// Otherwise B changed first and we're moving CCW
       bCW2 = false;
       Timer--;
     }
   
     Serial.print("Timer: ");
     Serial.println(Timer);
     
   }
   CLK2Last = bVal;

   if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
    digitalWrite(13, LOW);
    Serial.print(" Temperature: ");
    temperature = sensors.getTempCByIndex(0);
    Serial.println(temperature, resolution - 8);

    idle = 0;
       
    // immediately after fetching the temperature we request a new sample
 // in the async modus
    // for the demo we let the resolution change to show differences
    resolution++;
    if (resolution > 12) resolution = 9;
   
    sensors.setResolution(tempDeviceAddress, resolution);
    sensors.requestTemperatures();
    delayInMillis = 750 / (1 << (12 - resolution));
    lastTempRequest = millis();
  }
 
  digitalWrite(13, HIGH);
  // we can do usefull things here
  // for the demo we just count the idle time in millis
  delay(1);
  idle++;
 lcd.setCursor(0,0);
  lcd.print("Soll Temp:      Grad");
  lcd.setCursor(0,1);
  lcd.print("Ist  Temp:      Grad");
  lcd.setCursor(0,2);
  lcd.print("Timer:           Min");
 
}

ElEspanol

#24
Jun 29, 2016, 10:52 pm Last Edit: Jun 29, 2016, 10:54 pm by ElEspanol
Du solltest nicht in jedem loop das Display aktualisieren. und dann alle Sekunde z.B. nur die Werte schreiben, die sich geändert haben.

DrDiettrich

Gerade bei Encodern würde ich Interrupts verwenden, um keine Flanke zu verpassen. Ich habe dazu ein sehr effizientes Beispiel gesehen, weiß aber nicht mehr wo :-(

Doc_Arduino

#26
Jun 30, 2016, 08:04 am Last Edit: Jun 30, 2016, 08:05 am by Doc_Arduino
Hallo,

hab mal wieder aufgeräumt, dabei fiel auf, dass du eine ganze Menge in setup vergessen hast für die Temperaturmessung. Vielleicht liegt es daran.  Testen kann ich es nicht, jedoch kompliliert es.

Dein Display, ist das ein 16x2 oder ein 20x4 ?  Nicht das die Einstellung falsch ist.
Müssen wirklich zwei LCD Libs eingebunden werden?  LCD und LiquidCrystal I2C ?

Wegen Encoder. Kommt darauf an wie schnell die loop und wie schnell der Encoder ist.
Weis jetzt nicht was es für eine Drehgeber ist, wenn 2 normale Impulse rauskommen,
dann empfehle ich den Code von Peter Dannegger. Falls der jetzige Problem machen sollte.
Kann auch noch was anderes sein.


Code: [Select]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define I2C_ADDR    0x27 // <<----- Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
#define ONE_WIRE_BUS 10
int x = 0;
int y = 0;
//int n = 1;
int row = 20; //  <<----- My LCD was 16x2
int column = 4; //  <<----- My LCD was 16x2
int CLK1 = 3;  // Connected to CLK on KY-040
int DT1 = 4;  // Connected to DT on KY-040
int SollTemp = 0;
int CLK1Last;
int aVal;
boolean bCW1;
int CLK2 = 5;  // Connected to CLK on KY-040
int DT2 = 6;  // Connected to DT on KY-040
int Timer = 0;
int CLK2Last;
int bVal;
boolean bCW2;
 
LiquidCrystal_I2C   lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
int  resolution = 9;
float temperature = 0.0;
int  idle = 0;


void setup()
{
  Serial.begin (9600);
  sensors.begin();     // Start up the Dallas Library
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  lastTempRequest = millis();  

  lcd.begin (row,column);
  // Switch on the backlight
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home ();        
  pinMode (CLK1,INPUT);
  pinMode (DT1,INPUT);
  /* Read Pin A
  Whatever state it's in will reflect the last position  
  */
  CLK1Last = digitalRead(CLK1);    
}

void loop()
{
 
 aVal = digitalRead(CLK1);
   if (aVal != CLK1Last){ // Means the knob is rotating
     // if the knob is rotating, we need to determine direction
     // We do that by reading pin B.
     if (digitalRead(DT1) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise
       SollTemp ++;
       bCW1 = true;
     } else {// Otherwise B changed first and we're moving CCW
       bCW1 = false;
       SollTemp--;
     }
     Serial.print(F("SollTemp: "));
     Serial.println(SollTemp);
    
   }
   CLK1Last = aVal;

   bVal = digitalRead(CLK2);
   if (bVal != CLK2Last){ // Means the knob is rotating
     // if the knob is rotating, we need to determine direction
     // We do that by reading pin B.
     if (digitalRead(DT2) != bVal) {  // Means pin A Changed first - We're Rotating Clockwise
       Timer ++;
       bCW2 = true;
     } else {// Otherwise B changed first and we're moving CCW
       bCW2 = false;
       Timer--;
     }
  
     Serial.print(F("Timer: "));
     Serial.println(Timer);
    
   }
   CLK2Last = bVal;

   if (millis() - lastTempRequest > 750)  {   // aktualisiert aller 750ms
     Dallas_Temp_Refresh();
     lastTempRequest = millis();  
   }
    
   digitalWrite(13, HIGH);
  
   Display_Refresh();
 
}


void Dallas_Temp_Refresh()
{
   digitalWrite(13, LOW);
   Serial.print(F("Temperature: "));
   temperature = sensors.getTempCByIndex(0);
   Serial.println(temperature);  
   sensors.requestTemperatures();
   lastTempRequest = millis();  
}



void Display_Refresh()
{
  static int lastRefresh = 0;
  
  if ( millis() - lastRefresh > 500 ) {   // aktualisiert aller 500ms
    lastRefresh = millis();
    lcd.setCursor(0,0); lcd.print(F("Soll Temp:      Grad"));
    lcd.setCursor(0,1); lcd.print(F("Ist  Temp:      Grad"));
    lcd.setCursor(0,2); lcd.print(F("Timer:           Min"));  
  }
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up