Durchflussregler

Hallo, ich habe einen Sketch von einem Hobbybrauer bekommen der für ein Durchflussregler ist und zwar soll das ganze so funktionieren dass ich eingebe wie viel Liter ich gerne hätte und der füllt mir das ein.

SainSmart habe ich mit LCD

Angezeigt wird alles aber meine Knöpfe reagieren nicht!!

Bitte um hilfe

Sketch:

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int lcd_key     = 0;
int adc_key_in  = 0;
float current_volume = 0;                //Current total volume passed though flow meter
float target_volume = 23;                //Total desired volume
float adjustment_volume = 0;             //Adjustment volume to take into account delays in solenoid closing. Subtracted from the current volume.

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define hltSIZE   50                       //Size of the Hot Liquor Tun in litres

#define SOLENOIDPIN 13                      //Solenoid relay on Pin 13
#define FLOWSENSORPIN 2                    //Flow sensore on Pin 2

// count how many pulses
volatile uint16_t pulses = 0;
// track the state of the pulse pin
volatile uint8_t lastflowpinstate;
// you can try to keep time of how long it is between pulses
volatile uint32_t lastflowratetimer = 0;
// and use that to calculate a flow rate
volatile float flowrate;
// Interrupt is called once a millisecond, looks for any pulses from the sensor!
SIGNAL(TIMER0_COMPA_vect) {
 uint8_t x = digitalRead(FLOWSENSORPIN);
 
 if (x == lastflowpinstate) {
   lastflowratetimer++;
   return; // nothing changed!
 }
 
 if (x == HIGH) {
   //low to high transition!
   pulses++;
 }
 lastflowpinstate = x;
 flowrate = 1000.0;
 flowrate /= lastflowratetimer; // in hertz
 lastflowratetimer = 0;
}

void useInterrupt(boolean v) {
 if (v) {
   // Timer0 is already used for millis() - we'll just interrupt somewhere
   // in the middle and call the "Compare A" function above
   OCR0A = 0xAF;
   TIMSK0 |= _BV(OCIE0A);
 } else {
   // do not call the interrupt function COMPA anymore
   TIMSK0 &= ~_BV(OCIE0A);
 }
}

void setup()
{
   
 Serial.begin(9600);
 Serial.print("Flow sensor test!");
 
 digitalWrite(SOLENOIDPIN,LOW);           //ACTIVE HIGH RELAY PUT THIS FIRST TO ENSURE PIN IS IN CORRECT STATE BEFORE WE INIT IT
 digitalWrite(FLOWSENSORPIN, HIGH);

 pinMode(SOLENOIDPIN, OUTPUT);
 pinMode(FLOWSENSORPIN, INPUT);

 
 lcd.begin(16, 2);                        // start the library

 printBanner(2000);                       // show banner for 2 seconds
 
 lcd.clear();
 
 printLabels();
 
 lastflowpinstate = digitalRead(FLOWSENSORPIN);
 useInterrupt(true);

}

void loop()
{

 while(current_volume < (target_volume - adjustment_volume))
 { 
   dowork();
 }
 
 digitalWrite(SOLENOIDPIN,LOW);          //Close solenoid

 lcd.setCursor(0,0);
 lcd.print("  VALVE CLOSED  ");
 lcd.setCursor(0,1);
 lcd.print("   TARGET HIT   ");
 
 //Debug Messaging
 Serial.println("  VALVE CLOSED  ");
 Serial.println("   TARGET HIT   ");

}

void printBanner(int bannerdelay)
{
 lcd.setCursor(0,0);                     
 lcd.print("        ^       ");
 lcd.setCursor(0,1);  
 lcd.print("  >=BrewShark>  ");
 delay(bannerdelay);
}

void printLabels()
{
 lcd.setCursor(0,0);
 lcd.print("Set Vol: ");
 lcd.setCursor(0,1);
 lcd.print("Cur Vol: ");
}

// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);
 /*  OLD BUTTONS at 3.3V
 if (adc_key_in > 1000) return btnNONE;
 if (adc_key_in < 50)   return btnRIGHT; 
 if (adc_key_in < 195)  return btnSELECT;
 if (adc_key_in < 380)  return btnUP;
 if (adc_key_in < 555)  return btnDOWN;
 if (adc_key_in < 790)  return btnLEFT; 
*/

 if (adc_key_in < 50)   return btnRIGHT; 
 if (adc_key_in > 1000 && adc_key_in < 1050) return btnNONE;
 if (adc_key_in > 130 && adc_key_in < 160)  return btnUP;
 if (adc_key_in > 300 && adc_key_in < 350)  return btnDOWN;
 if (adc_key_in > 480 && adc_key_in < 520)  return btnLEFT;  
 if (adc_key_in > 700 && adc_key_in < 800)  return btnSELECT; 

 return btnNONE;
}

void dowork()
{

 //Serial.print("Freq: "); Serial.println(flowrate);        //Uncomment these two lines to monitor the freq/pulses
 //Serial.print("Pulses: "); Serial.println(pulses, DEC);
 float liters = pulses;
 liters /= 7.5;
 liters /= 60.0;
 
 current_volume = liters;
 
 //Debug Messaging
 Serial.print("Cur: "); Serial.println(current_volume);
 Serial.print("Tar: "); Serial.println(target_volume);
 
 //Print the target volume value in litres
 lcd.setCursor(11,0);
 lcd.print(target_volume,2);
 lcd.setCursor(15,0);
 lcd.print("L");

 //Print the current volume value in litres
 lcd.setCursor(11,1);            
 lcd.print(current_volume,2);
 lcd.setCursor(15,1);
 lcd.print("L");

 lcd_key = read_LCD_buttons();    // read the buttons
 

 switch (lcd_key)               // depending on which button was pushed, we perform an action
 {
 case btnRIGHT:
   {
    if (digitalRead(SOLENOIDPIN == HIGH))
    {
            digitalWrite(SOLENOIDPIN,LOW);       //STOP FLOW
    }
     

     Serial.println("Solenoid Closed");
     break;
   }

 case btnLEFT:
   {
    if (digitalRead(SOLENOIDPIN == LOW))
    {
            digitalWrite(SOLENOIDPIN,HIGH);       //START FLOW
    }
     

     Serial.println("Solenoid Open");
     
     break;
   }

 case btnUP:
   {
     if (target_volume >= hltSIZE)  //don't go larger than the size of the vessel
     {
       target_volume = hltSIZE;
       break;
     }
     else
     {
       target_volume += 0.1;
       break;
     }

     break;
   }

 case btnDOWN:
   {
     if (target_volume <= 0)      //don't go below zero
     {
       target_volume = 0;
       break; 
     }
     else
     {
       target_volume -= 0.1;
     }
     break;
   }

 case btnNONE:
   {
     break;
   }
 }

}

Setze deinen Sketch bitte in Code-Tags, dann ist dieser auch für mobile Geräte besser lesbar.

Verwende dazu die Schaltfläche </> oben links im Editorfenster.
Das kannst du auch nachträglich machen.
Dazu den Sketch markieren und die Schaltfläche klicken.

Damit wird dieser für alle besser lesbar.

Wo hast du denn deine Taster im Setup eingerichtet.
Da sehe ich nichts.

Ich habe bis jetzt den Sketch soo wie ich ihn bekommen habe auf den Arduino geladen

VolkMo:
Ich habe bis jetzt den Sketch soo wie ich ihn bekommen habe auf den Arduino geladen

Äh ... ich bin irritiert ...

Der Sketch macht auf mich den Eindruck, als sei er per copy&paste entstanden, wobei das scheinbar jemand gemacht hat, der sich mit alldem noch nie beschäftigt hat. Und ich habe den Eindruck, dass da jemand etwas programmiert haben möchte und zwar ohne dafür eine Gegenleistung zu erbringen.

Dieser Eindruck hat eine stark demotivierende Wirkung auf mich. Verstehe ich vielleicht etwas falsch?!

Gruß

Gregor

Hier habe ich den Sketch her, link ist von einem Hobbybrauer der diesen Regler auch schon mal gebaut hat.

Link

Mit der Hardware kenne ich mich etwas aus aber auf dem Gebiet der Software bin ich neu. Daher ein fertigen Sketch.

VolkMo:
...
Mit der Hardware kenne ich mich etwas aus aber auf dem Gebiet der Software bin ich neu. Daher ein fertigen Sketch.

Und was erhoffst Du, dass wir damit machen?

Gruß

Gregor

Ich erhoffe mir dass ihr mir helft und mir erklärt wie ich den rest machen muss, man hat mir auch gesagt ich soll die Wiederstandswerte der Tasten messen habe ich auch schon gemacht.

VolkMo:
Ich erhoffe mir dass ihr mir helft und mir erklärt wie ich den rest machen muss, man hat mir auch gesagt ich soll die Wiederstandswerte der Tasten messen habe ich auch schon gemacht.

Und was war das Ergebnis Deiner Messungen?

Zum Code: Lies ihn und verstehe, wie er funktioniert. So ein Einstieg in die Programmierung halte ich zwar für vollkommen daneben, aber nunja. Wenn Du die „Mechanik“ des Codes verstehst, weißt Du mehr oder weniger automatisch, was da an welcher Stelle passiert und evtl. geändert werden muss.

Fang am besten schonmal damit an, die Kommentare zu verstehen und zu übersetzen. Möglicherweise hast Du dann schon den größten Teil der Arbeit hinter Dir. Und frag, wenn was unklar ist.

Gruß

Gregor

SELECT 1023
LEFT 7753
RIGHT 0023
UP 2213
DOWN 5053

Das Komische ist es geht keine Taste außer der Reset diese funktioniert

Ist das nicht das Setup für die Tasten?

 if (adc_key_in < 0023)   return btnRIGHT; 
  if (adc_key_in > 1023 && adc_key_in < 1023) return btnNONE;
  if (adc_key_in > 2213 && adc_key_in < 2213)  return btnUP;
  if (adc_key_in > 5053 && adc_key_in < 5053)  return btnDOWN;
  if (adc_key_in > 7753 && adc_key_in < 7753)  return btnLEFT;  
  if (adc_key_in > 1023 && adc_key_in < 1023)  return btnSELECT;

VolkMo:
Das Komische ist es geht keine Taste außer der Reset diese funktioniert

  if (adc_key_in > 2213 && adc_key_in < 2213)  return btnUP;

Das ist gar nicht komisch. Bei der Abfrage müsste adc_key_in gleichzeitig größer und kleiner als 2213 sein. Das ist mathematisch schlicht nicht erfüllbar. Schau dir die Stelle im originalen Sketch noch mal an. Da werden jeweils Bereiche genannt, wo die Taste erkannt wird.

VolkMo:
SELECT 1023
LEFT 7753
RIGHT 0023
UP 2213
DOWN 5053

Wie hast du die Werte ermittelt? An sich ermittelt analogRead einen Wert von 0 bis 1023. Da deine Werte darüber liegen, kann das auch deshalb nicht funktionieren.

Ich weiß gar nicht, wo ich anfangen soll.

  • Welcher Arduino?
  • Saintsmart mit LED ??? Ich kann jetzt vermuten... aber so ein Link, oder ein Foto ?
  • Welcher Durchflussregler? Datenblatt ?
  • Dass die Reset-Taste funktioniert ist jetzt nicht so ganz verwunderlich.

BITTE !!!

Fang KLEIN an mit dem Programmieren UND DER HARDWARE.
Erst wenn Du die Grundlagen verstehst, macht ein solches Projekt Sinn.

Ich helfe wirklich gerne, aber nicht mit Informationsbrocken und der
Bitte, ich solle den Rest machen.
Wenn Du detaillierte Fragen hast und den Aufbau anständig beschreibst
gerne wieder.

Stefan

Wie wäre es mit

  if (adc_key_in < 90) {
    return btnRIGHT;
  }
  if (adc_key_in < 230) {
    return btnUP;
  }
  if (adc_key_in < 415) {
    return btnDOWN;
  }
  if (adc_key_in < 610) {
    return btnLEFT;
  }
  if (adc_key_in < 900) {
    return btnSELECT;
  }
  return btnNONE;

Meiner Ansicht nach reicht es mit jeweils nur einer Grenze zu entscheiden welche Taste es sein muss,
ich habe die Werte auf die Mitte zwischen deinen Bereichsgrenzen gesetzt.
Kann natürlich sein, dass das bei dir nicht passt, aber das ist ja anpassbar.

Hier der Link zum SainSmart.

Kann nicht jemand mal drüber schauen und mir sagen dass hier und da was nicht ganz stimmt?

VolkMo:
Kann nicht jemand mal drüber schauen und mir sagen dass hier und da was nicht ganz stimmt?

Ich habe dir gesagt, was nicht stimmt und Whandall hat anschließend einen Verbesserungsvorschlag auf dem Silbertablett präsentiert. Was sollen wir sonst noch tun?

Ganz ohne Grundlagen und eigenes Einarbeiten geht es beim Arduino nicht.

Mehr als eine getestete Lösung kann ich dir nicht anbieten, und das habe ich schon.

Der Sketch funktioniert bei mir mit der angegebenen Keyroutine.

Den code von Whandall habe ich so an die Stelle im Sketch übertragen und es geht immernoch nicht.

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int lcd_key     = 0;
int adc_key_in  = 0;
float current_volume = 0;                //Current total volume passed though flow meter
float target_volume = 23;                //Total desired volume
float adjustment_volume = 0;             //Adjustment volume to take into account delays in solenoid closing. Subtracted from the current volume.

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define hltSIZE   50                       //Size of the Hot Liquor Tun in litres

#define SOLENOIDPIN 13                      //Solenoid relay on Pin 13
#define FLOWSENSORPIN 2                    //Flow sensore on Pin 2

// count how many pulses
volatile uint16_t pulses = 0;
// track the state of the pulse pin
volatile uint8_t lastflowpinstate;
// you can try to keep time of how long it is between pulses
volatile uint32_t lastflowratetimer = 0;
// and use that to calculate a flow rate
volatile float flowrate;
// Interrupt is called once a millisecond, looks for any pulses from the sensor!
SIGNAL(TIMER0_COMPA_vect) {
  uint8_t x = digitalRead(FLOWSENSORPIN);

  if (x == lastflowpinstate) {
    lastflowratetimer++;
    return; // nothing changed!
  }

  if (x == HIGH) {
    //low to high transition!
    pulses++;
  }
  lastflowpinstate = x;
  flowrate = 1000.0;
  flowrate /= lastflowratetimer; // in hertz
  lastflowratetimer = 0;
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
  }
}

void setup()
{
  Serial.begin(250000);
  Serial.println("Flow sensor test!");

  // ACTIVE HIGH RELAY does not need special setup
  pinMode(SOLENOIDPIN, OUTPUT);
  pinMode(FLOWSENSORPIN, INPUT_PULLUP);

  lcd.begin(16, 2);
  printBanner(2000);   // show banner for 2 seconds
  lcd.clear();
  printLabels();

  lastflowpinstate = digitalRead(FLOWSENSORPIN);
  useInterrupt(true);
}

void loop()
{

  while (current_volume < (target_volume - adjustment_volume))
  {
    dowork();
  }

  digitalWrite(SOLENOIDPIN, LOW);         //Close solenoid

  lcd.setCursor(0, 0);
  lcd.print("  VALVE CLOSED  ");
  lcd.setCursor(0, 1);
  lcd.print("   TARGET HIT   ");

  //Debug Messaging
  Serial.println("  VALVE CLOSED  ");
  Serial.println("   TARGET HIT   ");

}

void printBanner(int bannerdelay)
{
  lcd.setCursor(0, 0);
  lcd.print("        ^       ");
  lcd.setCursor(0, 1);
  lcd.print("  >=BrewShark>  ");
  delay(bannerdelay);
}

void printLabels()
{
  lcd.setCursor(0, 0);
  lcd.print("Set Vol: ");
  lcd.setCursor(0, 1);
  lcd.print("Cur Vol: ");
}

int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in < 90) {
    return btnRIGHT;
  }
  if (adc_key_in < 230) {
    return btnUP;
  }
  if (adc_key_in < 415) {
    return btnDOWN;
  }
  if (adc_key_in < 610) {
    return btnLEFT;
  }
  if (adc_key_in < 900) {
    return btnSELECT;
  }
  return btnNONE;
}

void dowork()
{

  //Serial.print("Freq: "); Serial.println(flowrate);        //Uncomment these two lines to monitor the freq/pulses
  //Serial.print("Pulses: "); Serial.println(pulses, DEC);
  float liters = pulses;
  liters /= 7.5;
  liters /= 60.0;

  current_volume = liters;

  static unsigned long lastPrint;
  if (millis() - lastPrint > 5000) {
    lastPrint = millis();
    Serial.print("Tar: ");
    Serial.print(target_volume);
    Serial.print(" Cur: ");
    Serial.println(current_volume);
  }
  //Print the target volume value in litres
  lcd.setCursor(11, 0);
  lcd.print(target_volume, 2);
  lcd.setCursor(15, 0);
  lcd.print("L");

  //Print the current volume value in litres
  lcd.setCursor(11, 1);
  lcd.print(current_volume, 2);
  lcd.setCursor(15, 1);
  lcd.print("L");

  lcd_key = read_LCD_buttons();    // read the buttons


  switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
    case btnRIGHT:
      {
        if (digitalRead(SOLENOIDPIN == HIGH))
        {
          digitalWrite(SOLENOIDPIN, LOW);      //STOP FLOW
        }


        Serial.println("Solenoid Closed");
        break;
      }

    case btnLEFT:
      {
        if (digitalRead(SOLENOIDPIN == LOW))
        {
          digitalWrite(SOLENOIDPIN, HIGH);      //START FLOW
        }


        Serial.println("Solenoid Open");

        break;
      }

    case btnUP:
      {
        if (target_volume >= hltSIZE)  //don't go larger than the size of the vessel
        {
          target_volume = hltSIZE;
          break;
        }
        else
        {
          target_volume += 0.1;
          break;
        }

        break;
      }

    case btnDOWN:
      {
        if (target_volume <= 0)      //don't go below zero
        {
          target_volume = 0;
          break;
        }
        else
        {
          target_volume -= 0.1;
        }
        break;
      }

    case btnNONE:
      {
        break;
      }
  }

}

Funktioniert (im Sinne von “nimmt Tasten an”) bei mir auf Uno mit einem baugleichen Shield.
Ich habe natürlich keinen Flusssensor oder Magnetventil angeschlossen.

Der Sketch enthält einige echt grobe Fehler, aber die Tasten gehen.

Bei mir funktioniert nun die UP Taste und Reset die anderen reagieren immernoch nicht

VolkMo:
Bei mir funktioniert nun die UP Taste und Reset die anderen reagieren immernoch nicht

Du musst noch die Widerstandsschwellen anpassen. Offensichtlich hat dein LCD-Shield etwas andere Werte. Lass dir mit dem Beispiel AnalogInOutSerial aus der IDE die Werte auf den seriellen Monitor ausgeben. Dann nimmst du als Schwellen Werte dazwischen, damit kleine Abweichungen zu keinen Fehlern führen.