Go Down

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

Matthias321

Jun 27, 2016, 09:21 pm Last Edit: Jun 27, 2016, 09:26 pm by Matthias321
Hallo, ich nutze einen Arduino Mega mit zwei Drehgebern (KY-040), einem 4-Zeilendisplay und einem Temp-Sensor DS18B20 um eine Heizung anzusteuern. Die einzelnen Komponenten habe ich erfolgreich angesteuert. Auch die Drehgeber erzeugen im separaten Programm korrekte Werte, nur in meinem zusammengefügten Code kommt nichts vernünftiges bei rum. Liegt es am längeren Durchlaufzyklus? Würde mich über Hilfe freuen.
Gruß

buffalo64

Bin selbst Anfänger, aber die erste Frage, die dir gestellt wird, ist die nach dem Code. Sonst kann dir auch von den Profis leider keiner helfen.

Matthias321

#2
Jun 27, 2016, 09:31 pm Last Edit: Jun 28, 2016, 12:28 am by uwefed Reason: add [CODE] TAGs </>
Sorry, wusste nicht dass man nach jedem Post 5 Min warten muss, also hier noch der Code:


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);
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;
{
  // when characters arrive over the serial port...
  if (Serial.available()) {
    // 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();
  return;
}
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!");
    return;
}
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");
}

Serenifly

Wenn man den Sensor blockierend ausliest, dauert eine Wandlung je nach Auflösung 93-750ms. Während dessen kann nichts gemacht werden. Je nach Anwendung reicht es aber völlig wenn man Temperatur-Sensoren nur alle 30-60s Sekunden ausliest. Dann aber ohne delay()!

Matthias321

Schon mal vielen Dank für die Antwort, wie setzt man so eine punktuelle Auswertung ohne delay denn um?



HotSystems

Indem du millis() verwendest.
Hier solltest du noch das Beispiel "BlinkWithoutDelay" erwähnen, da kann man die Funktion von millis gut entnehmen.
Gruß Dieter

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

buffalo64


Doc_Arduino

Hallo,

und der übliche Hinweis. :)  Code bitte in Code Tags setzen. Ersten Button links  </>.
Geht auch nachträglich.


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

uwefed

Hallo,

und der übliche Hinweis. :)  Code bitte in Code Tags setzen. Ersten Button links  </>.
Geht auch nachträglich.
Hab's schon gemacht.
Uwe

Matthias321

Vielen Dank für die Antworten. Ich habe die Millis nun eingefügt, aber das Ergebnis stimmt noch nicht, habe ich einen Fehler gemacht?

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()) {
      // 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();
    return;
  }
  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!");
      return;
  }
  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");
 }







HotSystems

Ein Vorschlag zu deinem Sketch, hat nicht direkt etwas mit deinem Fehler zu tun:

Setze die einzelnen Programmteile (Temperatur, Anzeige) in Funktionen, dadurch wird der Sketch übersichtlicher und ein Programmfehler lässt sich so schneller finden.

Gruß Dieter

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

ElEspanol

Verfolgst du einen bestimmten Zweck mit deiner eigenartigen Klammersetzung?

Ich mach sowas nur in bestimmten Fällen, um lokale Variablen im loop mehrfach zu verwenden.

Matthias321

Der Aufbau ist vll noch nicht ganz optimal. Bin noch blutiger Anfänger.

Go Up