Wasserdosierung

Antworten
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Wasserdosierung

#1

Beitrag von VolkMo »

Hallo,
gibt es jemand der schon eine Art Wasserdosiersystem gebaut hat?

Quasi dass ich eingebe dass ich gerne 20 L hätte und die Anlage 20 L in meinen Topf laufen lässt.
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
Ladeberger
Moderator
Moderator
Beiträge: 7293
Registriert: Dienstag 20. November 2012, 18:29

Re: Wasserdosierung

#2

Beitrag von Ladeberger »

Hallo VolkMo,

ob das schon jemand gemacht hat weiß ich nicht. Wenn deine Wasserleitung einen relativ konstanten Druck aufweist, könntest du mit einem manuellen Ventil und einer "Bewässerungsuhr" eine relativ kostengünstige Lösung implementieren; zum Beispiel bei per Ventil justierten 5 l/min für 20 L auf der Bewässerungsuhr 4 min einstellen.

Eine universelle Lösung stelle ich mir komplexer vor. Hierfür bräuchte man wohl im Minimum einen Durchflusssensor im passenden Messbereich, ein Magnetventil, eine programmierbare Steuerung und Eingabemöglichkeit + Display für das Limit oder Anbindung als App. Da bist du aber sicher zwei Hunnis schon für das Bastelmaterial los.

Gruß
Andy
Benutzeravatar
Jomsviking
Posting Senior
Posting Senior
Beiträge: 478
Registriert: Montag 8. Mai 2017, 10:19
Wohnort: Rudersberg

Re: Wasserdosierung

#3

Beitrag von Jomsviking »

Es gibt fertige Wasserdosiergeräte. Die sind meist in der Industrie (Bäcker, etc.) zu finden.
Ob sich das für ca. 1.000€ lohnt muss jeder selbst wissen ;)
Bei 20L würde ich jedoch lieber einen Eimer, eine Gießkanne, oder was auch immer nehmen.
Benutzeravatar
tommes
Posting Freak
Posting Freak
Beiträge: 755
Registriert: Montag 24. August 2015, 18:18
Wohnort: Grevenbroich

Re: Wasserdosierung

#4

Beitrag von tommes »

Evtl ne Gardena-Wasseruhr - k.A. ob die genau genug sind - ansonsten was selber basteln aus Flowmeter + Magnetventil + Arduino
Krimson
Posting Junior
Posting Junior
Beiträge: 21
Registriert: Dienstag 27. September 2016, 00:26

Re: Wasserdosierung

#5

Beitrag von Krimson »

Kuckst du hier. Er hat das schön umgesetzt. Alles Tip Top automatisch:

viewtopic.php?f=20&t=6161
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#7

Beitrag von VolkMo »

So ich komme nimmer weiter :


Habe nen SainSmart gekauft den Sketch von Brewshark derauf und mein LCD Bildschirm zeigt mir alles an.

ABER:

Er startet von alleine ohne mein zutun und keine der Tasten funktioniert.

Kennt sich hier jemand mit Arduino und dessen Programmierung aus?

Hier der Link
https://github.com/stelawton/brewshark/ ... roller.ino
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
Ladeberger
Moderator
Moderator
Beiträge: 7293
Registriert: Dienstag 20. November 2012, 18:29

Re: Wasserdosierung

#8

Beitrag von Ladeberger »

Vielleicht wäre es sinnvoll, wenn du erst mal detailliert die vorhandenen Komponenten auflistest, wie sie aktuell verdrahtet/verrohrt/angeschlossen sind und deine persönlichen Elektronik- und Programmier-Vorkenntnisse schilderst.

Gruß
Andy
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#9

Beitrag von VolkMo »

Also ich möchte momentan eigentlich nur den Sketch testen ohne Komponenten aber die Tasten reagieren nicht.

Elektotechnisch dürfte es eigentlich keine Probleme geben nur beim Programmieren da bin ich neu dabei.
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
emilio
Posting Freak
Posting Freak
Beiträge: 1043
Registriert: Mittwoch 25. Dezember 2013, 09:17
Wohnort: Schopfheim, Wiechs
Kontaktdaten:

Re: Wasserdosierung

#10

Beitrag von emilio »

So wie der Sketch geschrieben ist fängt der immer sofort an zu zählen, wenn du keine Hardware angeschlossen hast. Durch den undefinierten Zustand am Port wird da immer mal high, mal low erkannt und er zählt damit. Leg mal Pin 2 auf Masse, dann sollte das aufhören. Bei den Tastern würde ich auf falsche Verkabelung oder ein nicht passendes Shield tippen.

Grüße,
Andreas
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#11

Beitrag von VolkMo »

Die wiederstandswerte haben nicht gepasst diese wurden nun angepasst jetzt gehen die Tasten

Was mich noch stört ist wenn ich das Volumen erhöhen will geht dies nur sehr ungenau da der Wert sehr schnell nach oben geht
Kann man dies irgendwie ändern?
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
emilio
Posting Freak
Posting Freak
Beiträge: 1043
Registriert: Mittwoch 25. Dezember 2013, 09:17
Wohnort: Schopfheim, Wiechs
Kontaktdaten:

Re: Wasserdosierung

#12

Beitrag von emilio »

Klar, erhöhe die Volumen Variable nur um 0.01 und runde sie zur Ausgabe oder erhöhe die Variable nur bei jedem fünften Schleifendurchlauf.

Wenn du dazu Hilfe beim Code brauchst, sag Bescheid.

Grüße,
Andreas
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#13

Beitrag von VolkMo »

Da wäre etwas Hilfe echt super
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#14

Beitrag von VolkMo »

Das ist mein aktueller Code


Code: Alles auswählen

#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(5000);   // 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(" Ventil bei ");
  lcd.setCursor(0, 1);
  lcd.print(" geschlossen ");

  //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("  Wassermenge");
  delay(bannerdelay);
}

void printLabels()
{
  lcd.setCursor(0, 0);
  lcd.print("Soll: ");
  lcd.setCursor(0, 1);
  lcd.print("Aktuell: ");
}

int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in < 110) {
    return btnRIGHT;
  }
  if (adc_key_in < 360) {
    return btnUP;
  }
  if (adc_key_in < 640) {
    return btnDOWN;
  }
  if (adc_key_in < 900) {
    return btnLEFT;
  }
  if (adc_key_in < 1000) {
    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;
      }
  }

}
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
katzlbt
Posting Senior
Posting Senior
Beiträge: 315
Registriert: Montag 21. März 2016, 20:14
Wohnort: Innsbruck

Re: Wasserdosierung

#15

Beitrag von katzlbt »

Vielleicht wäre ein Durchflussbegrenzer hilfreich.
Dann könnte man die Menge einfach über die Zeit bestimmen.
https://www.filterzentrale.com/zubehoer ... -flow-1000
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#16

Beitrag von VolkMo »

ich habe einen durchflusssensor drin der misst wie viel liter druch sind - ich muss nur irgendwie im code noch einstellen dass ich beim eingeben kleinere schritte machen kann
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
tommes
Posting Freak
Posting Freak
Beiträge: 755
Registriert: Montag 24. August 2015, 18:18
Wohnort: Grevenbroich

Re: Wasserdosierung

#17

Beitrag von tommes »

VolkMo hat geschrieben:ich muss nur irgendwie im code noch einstellen dass ich beim eingeben kleinere schritte machen kann
mach doch hinter den Tastenabfragen nach Veränderung der Liter ein kleines Delay

Code: Alles auswählen

    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;
          delay(100);
          break;
        }

        break;
durch 100ms delay solltest du nur noch 10 Schritte pro Sekunde machen - also 1L/sek hoch/runter.
Musst du natürlich bei beiden Richtungen machen.
Benutzeravatar
tommes
Posting Freak
Posting Freak
Beiträge: 755
Registriert: Montag 24. August 2015, 18:18
Wohnort: Grevenbroich

Re: Wasserdosierung

#18

Beitrag von tommes »

oder besser: wenn sich der Tastenzustand ändert, nimmst du ein längeres Delay, in der Wiederholung ein kurzes:
die Abschnitte zwischen den Kommentaren mit TK: sind neu

Code: Alles auswählen

..... rest vor vorher

  lcd_key = read_LCD_buttons();    // read the buttons

  // TK: Tastenstatus prüfen, wenn neue Taste gedrückt, lange warten, wenn gleiche Taste dann kurz warten
  // es kann sein das die 2 Zeilen an den Anfang des Sketches müssen
  int old_lcd_key = 0;
  int delay_time = 0;

  if(old_lcd_key != lcd_key) 
  {
    old_lcd_key = lcd_key;
    delay_time = 1000; // am Anfang 1 sek warten
  } else {
    delay_time = 50;
  }
  // TK: Ende

  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;
          // TK: warten
          delay(delay_time);
          // TK: ende
          break;
        }

        break;
      }

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

    case btnNONE:
      {
        break;
      }
  }

}
Benutzeravatar
emilio
Posting Freak
Posting Freak
Beiträge: 1043
Registriert: Mittwoch 25. Dezember 2013, 09:17
Wohnort: Schopfheim, Wiechs
Kontaktdaten:

Re: Wasserdosierung

#19

Beitrag von emilio »

Würde ich so nicht tun. Während des Delays läuft der ganze Code auch nicht weiter. Ob das Auswirkungen hat ist allerdings fraglich.
Ich würe das eher so tun...

Code: Alles auswählen

#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 target_count_volume = 23;
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(5000);   // 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(" Ventil bei ");
  lcd.setCursor(0, 1);
  lcd.print(" geschlossen ");

  //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("  Wassermenge");
  delay(bannerdelay);
}

void printLabels()
{
  lcd.setCursor(0, 0);
  lcd.print("Soll: ");
  lcd.setCursor(0, 1);
  lcd.print("Aktuell: ");
}

int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in < 110) {
    return btnRIGHT;
  }
  if (adc_key_in < 360) {
    return btnUP;
  }
  if (adc_key_in < 640) {
    return btnDOWN;
  }
  if (adc_key_in < 900) {
    return btnLEFT;
  }
  if (adc_key_in < 1000) {
    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_count_volume += 0.02;          
          target_volume = round ( target_count_volume * 10 );
          target_volume = target_volume / 10;
          break;
        }

        break;
      }

    case btnDOWN:
      {
        if (target_volume <= 0)      //don't go below zero
        {
          target_volume = 0;
          break;
        }
        else
        {
          target_count_volume -= 0.02;          
          target_volume = round ( target_count_volume * 10 );
          target_volume = target_volume / 10;
        }
        break;
      }

    case btnNONE:
      {
        break;
      }
  }

}
Grüße,
Andreas
Benutzeravatar
tommes
Posting Freak
Posting Freak
Beiträge: 755
Registriert: Montag 24. August 2015, 18:18
Wohnort: Grevenbroich

Re: Wasserdosierung

#20

Beitrag von tommes »

emilio hat geschrieben:Würde ich so nicht tun. Während des Delays läuft der ganze Code auch nicht weiter.
Ja haste recht, meine Idee war eher dirty als quick, habe gerade über delay() nachgelesen. Da fällt mir ein ich muss unbedingt mal was mit Arduino machen.
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#21

Beitrag von VolkMo »

Habe ihn noch etwas abgeändert das ist nun der fertige Sketch jetzt warte ich noch auf den Sensor dann sollte alles gehen.

Code: Alles auswählen

#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 target_count_volume = 23;
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(5000);   // 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(" Ventil bei ");
  lcd.setCursor(0, 1);
  lcd.print(" geschlossen ");

  //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("  Wassermenge");
  delay(bannerdelay);
}

void printLabels()
{
  lcd.setCursor(0, 0);
  lcd.print("Soll: ");
  lcd.setCursor(0, 1);
  lcd.print("Aktuell: ");
}

int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in < 110) {
    return btnRIGHT;
  }
  if (adc_key_in < 360) {
    return btnUP;
  }
  if (adc_key_in < 640) {
    return btnDOWN;
  }
  if (adc_key_in < 900) {
    return btnLEFT;
  }
  if (adc_key_in < 1000) {
    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_count_volume += 0.002;          
          target_volume = round ( target_count_volume * 10 );
          target_volume = target_volume / 10;
          break;
        }

        break;
      }

    case btnDOWN:
      {
        if (target_volume <= 0)      //don't go below zero
        {
          target_volume = 0;
          break;
        }
        else
        {
          target_count_volume -= 0.002;          
          target_volume = round ( target_count_volume * 10 );
          target_volume = target_volume / 10;
        }
        break;
      }

    case btnNONE:
      {
        break;
      }
  }

}
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
VolkMo
Posting Junior
Posting Junior
Beiträge: 58
Registriert: Dienstag 22. November 2016, 12:41
Wohnort: Winden im Elztal

Re: Wasserdosierung

#22

Beitrag von VolkMo »

jemand ne idee wie ich die abdeckung der knöpfe machen kann die an meinem LCD Shild dran sind?
6 qm Sudhaus :) Oberwindenbräu lässt grüßen

viewtopic.php?f=20&t=13979&view=unread#unread
Benutzeravatar
emilio
Posting Freak
Posting Freak
Beiträge: 1043
Registriert: Mittwoch 25. Dezember 2013, 09:17
Wohnort: Schopfheim, Wiechs
Kontaktdaten:

Re: Wasserdosierung

#23

Beitrag von emilio »

Das ist der Grund warum ich einen Encoder und nicht die Tastenversion benutze. Ist einfacher schick einzubauen.

Grüße,
Andreas
Bjmang
Posting Klettermax
Posting Klettermax
Beiträge: 141
Registriert: Freitag 25. Dezember 2015, 11:52
Wohnort: Rodalben
Kontaktdaten:

Re: Wasserdosierung

#24

Beitrag von Bjmang »

Die Version von "emilio" ist Top!
Benutze ich auch.
Bediene das Shield über Umgekehrt locker ins Gehäuse eingebaute Blindnieten.
Leider zu viele Löcher gebohrt :redhead
Dateianhänge
IMG_20170603_115025.jpg
IMG_20170603_120531.jpg
12561.jpg
Antworten