1 | #include <LiquidCrystal.h>
|
2 |
|
3 | LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
|
4 |
|
5 | int lcd_key = 0;
|
6 | int adc_key_in = 0;
|
7 | float current_volume = 0; //Current total volume passed though flow meter
|
8 | float target_volume = 0.5; //Total desired volume
|
9 | float adjustment_volume = 0; //Adjustment volume to take into account delays in solenoid closing. Subtracted from the current volume.
|
10 |
|
11 | #define btnRIGHT 0
|
12 | #define btnUP 1
|
13 | #define btnDOWN 2
|
14 | #define btnLEFT 3
|
15 | #define btnSELECT 4
|
16 | #define btnNONE 5
|
17 |
|
18 | #define hltSIZE 0.6 //Size of the Hot Liquor Tun in litres
|
19 |
|
20 | #define SOLENOIDPIN 13 //Solenoid relay on Pin 13
|
21 | #define FLOWSENSORPIN 12 //Flow sensore on Pin 2
|
22 |
|
23 | // count how many pulses
|
24 | volatile uint16_t pulses = 0;
|
25 | // track the state of the pulse pin
|
26 | volatile uint8_t lastflowpinstate;
|
27 | // you can try to keep time of how long it is between pulses
|
28 | volatile uint32_t lastflowratetimer = 0;
|
29 | // and use that to calculate a flow rate
|
30 | volatile float flowrate;
|
31 | // Interrupt is called once a millisecond, looks for any pulses from the sensor!
|
32 | SIGNAL(TIMER0_COMPA_vect) {
|
33 | uint8_t x = digitalRead(FLOWSENSORPIN);
|
34 |
|
35 | if (x == lastflowpinstate) {
|
36 | lastflowratetimer++;
|
37 | return; // nothing changed!
|
38 | }
|
39 |
|
40 | if (x == HIGH) {
|
41 | //low to high transition!
|
42 | pulses++;
|
43 | }
|
44 | lastflowpinstate = x;
|
45 | flowrate = 1000.0;
|
46 | flowrate /= lastflowratetimer; // in hertz
|
47 | lastflowratetimer = 0;
|
48 | }
|
49 |
|
50 | void useInterrupt(boolean v) {
|
51 | if (v) {
|
52 | // Timer0 is already used for millis() - we'll just interrupt somewhere
|
53 | // in the middle and call the "Compare A" function above
|
54 | OCR0A = 0xAF;
|
55 | TIMSK0 |= _BV(OCIE0A);
|
56 | } else {
|
57 | // do not call the interrupt function COMPA anymore
|
58 | TIMSK0 &= ~_BV(OCIE0A);
|
59 | }
|
60 | }
|
61 |
|
62 | void setup()
|
63 | {
|
64 |
|
65 | Serial.begin(9600);
|
66 | Serial.print("Flow sensor test!");
|
67 |
|
68 | digitalWrite(SOLENOIDPIN,LOW); //ACTIVE HIGH RELAY PUT THIS FIRST TO ENSURE PIN IS IN CORRECT STATE BEFORE WE INIT IT
|
69 | digitalWrite(FLOWSENSORPIN, HIGH);
|
70 |
|
71 | pinMode(SOLENOIDPIN, OUTPUT);
|
72 | pinMode(FLOWSENSORPIN, INPUT);
|
73 |
|
74 |
|
75 | lcd.begin(16, 2); // start the library
|
76 |
|
77 | printBanner(3000); // show banner for 2 seconds
|
78 |
|
79 | lcd.clear();
|
80 |
|
81 | printLabels();
|
82 |
|
83 | lastflowpinstate = digitalRead(FLOWSENSORPIN);
|
84 | useInterrupt(true);
|
85 |
|
86 | }
|
87 | void loop()
|
88 | {
|
89 |
|
90 | while(current_volume < (target_volume - adjustment_volume))
|
91 | {
|
92 | dowork();
|
93 | }
|
94 |
|
95 | digitalWrite(SOLENOIDPIN,HIGH); //Close solenoid //normal low!!
|
96 |
|
97 | lcd.setCursor(0,0);
|
98 | lcd.print("Waschm. dosieren");
|
99 | lcd.setCursor(0,1);
|
100 | lcd.print(" Start druecken ");
|
101 |
|
102 | //Debug Messaging
|
103 | Serial.println(" VALVE CLOSED ");
|
104 | Serial.println(" TARGET HIT ");
|
105 |
|
106 | }
|
107 |
|
108 | void printBanner(int bannerdelay)
|
109 | {
|
110 | lcd.setCursor(0,0);
|
111 | lcd.print(" Waschmittel ");
|
112 | lcd.setCursor(0,1);
|
113 | lcd.print(" wird dosiert ");
|
114 | delay(bannerdelay);
|
115 | }
|
116 |
|
117 | void printLabels()
|
118 | {
|
119 | lcd.setCursor(0,0);
|
120 | lcd.print("Ziel: ");
|
121 | lcd.setCursor(0,1);
|
122 | lcd.print("Aktuell: ");
|
123 | }
|
124 |
|
125 | // read the buttons
|
126 | int read_LCD_buttons()
|
127 | {
|
128 | adc_key_in = analogRead(0);
|
129 | /* OLD BUTTONS at 3.3V
|
130 | if (adc_key_in > 1000) return btnNONE;
|
131 | if (adc_key_in < 50) return btnRIGHT;
|
132 | if (adc_key_in < 195) return btnSELECT;
|
133 | if (adc_key_in < 380) return btnUP;
|
134 | if (adc_key_in < 555) return btnDOWN;
|
135 | if (adc_key_in < 790) return btnLEFT;
|
136 | */
|
137 |
|
138 | if (adc_key_in > 1000) return btnNONE;
|
139 | if (adc_key_in < 50) return btnRIGHT;
|
140 | if (adc_key_in < 195) return btnUP;
|
141 | if (adc_key_in < 380) return btnDOWN;
|
142 | if (adc_key_in < 555) return btnLEFT;
|
143 | if (adc_key_in < 790) return btnSELECT;
|
144 |
|
145 | return btnNONE;
|
146 | }
|
147 |
|
148 | void dowork()
|
149 | {
|
150 |
|
151 | //Serial.print("Freq: "); Serial.println(flowrate); //Uncomment these two lines to monitor the freq/pulses
|
152 | //Serial.print("Pulses: "); Serial.println(pulses, DEC);
|
153 | float liters = pulses;
|
154 | liters /= 7.5;
|
155 | liters /= 60.0;
|
156 |
|
157 | current_volume = liters;
|
158 |
|
159 | //Debug Messaging
|
160 | Serial.print("Cur: "); Serial.println(current_volume);
|
161 | Serial.print("Tar: "); Serial.println(target_volume);
|
162 |
|
163 | //Print the target volume value in litres
|
164 | lcd.setCursor(11,0);
|
165 | lcd.print(target_volume,2);
|
166 | lcd.setCursor(15,0);
|
167 | lcd.print("L");
|
168 |
|
169 | //Print the current volume value in litres
|
170 | lcd.setCursor(11,1);
|
171 | lcd.print(current_volume,2);
|
172 | lcd.setCursor(15,1);
|
173 | lcd.print("L");
|
174 |
|
175 | lcd_key = read_LCD_buttons(); // read the buttons
|
176 |
|
177 |
|
178 | switch (lcd_key) // depending on which button was pushed, we perform an action
|
179 | {
|
180 | case btnRIGHT:
|
181 | {
|
182 | if (digitalRead(SOLENOIDPIN == HIGH))
|
183 | {
|
184 | digitalWrite(SOLENOIDPIN,LOW); //STOP FLOW
|
185 | }
|
186 |
|
187 |
|
188 | Serial.println("Solenoid Closed");
|
189 | break;
|
190 | }
|
191 |
|
192 | case btnLEFT:
|
193 | {
|
194 | if (digitalRead(SOLENOIDPIN == LOW))
|
195 | {
|
196 | digitalWrite(SOLENOIDPIN,HIGH); //START FLOW
|
197 | }
|
198 |
|
199 |
|
200 | Serial.println("Solenoid Open");
|
201 |
|
202 | break;
|
203 | }
|
204 |
|
205 | case btnUP:
|
206 | {
|
207 | if (target_volume >= hltSIZE) //don't go larger than the size of the vessel
|
208 | {
|
209 | target_volume = hltSIZE;
|
210 | break;
|
211 | }
|
212 | else
|
213 | {
|
214 | target_volume += 0.01;
|
215 | break;
|
216 | }
|
217 |
|
218 | break;
|
219 | }
|
220 |
|
221 | case btnDOWN:
|
222 | {
|
223 | if (target_volume <= 0) //don't go below zero
|
224 | {
|
225 | target_volume = 0;
|
226 | break;
|
227 | }
|
228 | else
|
229 | {
|
230 | target_volume -= 0.01;
|
231 | }
|
232 | break;
|
233 | }
|
234 |
|
235 |
|
236 | case btnNONE:
|
237 | {
|
238 | break;
|
239 | }
|
240 | }
|
241 |
|
242 | }
|