Hello,
I'm building a controller for garden irrigation with 8 valves to control 8 different zones for watering plants. To control the valves I bought 5v relay boards with optical isolation. Interference problems have already been fixed with a ferrite ring.
The time eacht zone has to stay active can be set in the eprom via the controls. The whole program is controlled with a rotary encoder which includes a pushbutton. When I for example select 30 minutes, the program will run just as expected untill it reaches 23 minutes in the countdown. At this moment the arduino crashes, displays weird characters on the display and self-resets. This reset turns off all relays and the irrigation stops. So It can only water plants for 6 minutes.
I know the way of programming here is not ideal, but it should work. What am I overseeing, what am I doing wrong?
Code below:
/*
* MARK VAN VEGGEL
* ARDUINO LCD MENU V0.1
* YOUTUBE.COM/AMPSOURCE
*
*/
#include <OneButton.h>+
#include <Encoder.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x20,2,1,0,4,5,6,7);
// ROTARY ENCODER
long oldPosition = 0;
int encoderDTpin = 2;
int encoderCLKpin = 3;
int mode = 1;
int timerMin = 0;
int timerSec;
int timerRustSec;
int timerSettingSec;
int timerRustMin = 15;
int timerSettingMin;
bool pomprust = true;
int addr1 = 0;
int addr2 = 8;
Encoder myEnc(encoderDTpin, encoderCLKpin);
#define buttonPin 8
#define Valve1 4
#define Valve2 5
#define Valve3 6
#define Valve4 7
#define Valve5 9
#define Valve6 10
#define Valve7 11
#define Valve8 12
OneButton button0 = OneButton(
buttonPin, // Input pin for the button
false, // Button is active high
false // Disable internal pull-up resistor
);
void setup() {
Serial.begin(9600);
// Map rotary button to actions single and doubleclick.
button0.attachClick(singleClick);
button0.attachLongPressStart(longPressStart);
button0.attachDoubleClick(doubleClick);
lcd.begin (16,2);
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home();
// Create the custom character.
lcd.setCursor (2,0);
lcd.print("R. Heleven");
delay(1000);
lcd.setCursor (0,0);
lcd.print(" ");
lcdUpdate();
pinMode(Valve1,OUTPUT);
pinMode(Valve2,OUTPUT);
pinMode(Valve3,OUTPUT);
pinMode(Valve4,OUTPUT);
pinMode(Valve5,OUTPUT);
pinMode(Valve6,OUTPUT);
pinMode(Valve7,OUTPUT);
pinMode(Valve8,OUTPUT);
digitalWrite(Valve1,HIGH);
digitalWrite(Valve2,HIGH);
digitalWrite(Valve3,HIGH);
digitalWrite(Valve4,HIGH);
digitalWrite(Valve5,HIGH);
digitalWrite(Valve6,HIGH);
digitalWrite(Valve7,HIGH);
digitalWrite(Valve8,HIGH);
timerSettingMin = EEPROM.read(addr1);
pomprust = EEPROM.read(addr2);
timerMin = timerSettingMin;
timerRustMin = 15;
timerSettingSec = 60*timerSettingMin;
timerSec = timerSettingSec;
timerRustSec = 60*timerRustMin;
}
void loop() {
// Listen to button presses.
button0.tick();
// Listen if the rotary encoder moves.
rotary_check();
// Print the LCD menu.
//lcdUpdate();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////:
void singleClick() {
switch (mode) {
case 1:
mode = 11;
break;
case 2:
mode = 31;
break;
case 3:
mode = 51;
break;
case 51:
mode = 71;
break;
case 52:
mode = 72;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
lcdUpdate();
Serial.println(mode);
}
void longPressStart() {
switch (mode) {
case 11:
mode = 21;
break;
case 12:
mode = 22;
break;
case 13:
mode = 23;
break;
case 14:
mode = 24;
break;
case 15:
mode = 25;
break;
case 16:
mode = 26;
break;
case 17:
mode = 27;
break;
case 18:
mode = 28;
break;
case 31:
screen41();
break;
case 32:
screen42();
break;
case 71:
mode = 100;
break;
case 72:
mode = 101;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
lcdUpdate();
}
void doubleClick() {
mode = 1;
lcdUpdate();
}
void rotary_check(){
// Constantly read the position of the rotary encoder
long newPosition = myEnc.read() / 4;
// IF the new position of the encoder is different then the old position
if (newPosition != oldPosition) {
if(newPosition > oldPosition){
if (mode==71){
timerSettingMin++;
if (timerSettingMin >= 90){timerSettingMin = 90;}
}
if (mode==72){
if (pomprust == true){pomprust=false;}
}
if ((mode!=71)&&(mode!=72)){
if (((mode<=2)&&(mode>=0))||((mode>=11)&&(mode<=17))||((mode>=21)&&(mode<=23))||((mode==51))||(mode==31)){
mode++;
Serial.println(mode);
}
}
}
else if (newPosition < oldPosition){
if (mode==71){
timerSettingMin--;
if (timerSettingMin <= 5){timerSettingMin = 5;}
}
if (mode==72){
if (pomprust == false){pomprust=true;}
}
if((mode!=71)&&(mode!=72)){
if (((mode>=2)&&(mode<=3))||((mode>=12)&&(mode<=18))||((mode>=22)&&(mode<=24))||((mode==52))||(mode==32)){
mode--;
if (mode <= 1){mode=1;}
Serial.println(mode);
}
}
}
oldPosition = newPosition;
lcdUpdate();
}
}
void lcdUpdate(){
switch (mode) {
case 0:
screen0();
break;
case 1:
screen1();
break;
case 2:
screen2();
break;
case 3:
screen3();
break;
case 11:
screen11();
break;
case 12:
screen12();
break;
case 13:
screen13();
break;
case 14:
screen14();
break;
case 15:
screen15();
break;
case 16:
screen16();
break;
case 17:
screen17();
break;
case 18:
screen18();
break;
case 21:
screen21();
break;
case 22:
screen22();
break;
case 23:
screen23();
break;
case 24:
screen24();
break;
case 25:
screen25();
break;
case 26:
screen26();
break;
case 27:
screen27();
break;
case 28:
screen28();
break;
case 31:
screen31();
break;
case 32:
screen32();
break;
case 51:
screen51();
break;
case 52:
screen52();
break;
case 71:
screen71();
break;
case 72:
screen72();
break;
case 100:
screen100();
break;
case 101:
screen101();
break;
case 200:
screen200();
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
lcd.setCursor(0, 2);
//lcd.print(mode);
}
void wateringZONE1(){
digitalWrite(Valve1,LOW);
mode = 21;
delay(940);
timerSec--;
Serial.println(timerSec);
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve1,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE2(){
digitalWrite(Valve2,LOW);
mode = 22;
delay(940);
timerSec--;
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve2,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE3(){
digitalWrite(Valve3,LOW);
mode = 23;
delay(940);
timerSec--;
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve3,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE4(){
digitalWrite(Valve4,LOW);
mode = 24;
delay(940);
timerSec--;
Serial.println(timerSec);
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve4,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE5(){
digitalWrite(Valve5,LOW);
mode = 25;
delay(940);
timerSec--;
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve5,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE6(){
digitalWrite(Valve6,LOW);
mode = 26;
delay(940);
timerSec--;
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve6,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE7(){
digitalWrite(Valve7,LOW);
mode = 27;
delay(940);
timerSec--;
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve7,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringZONE8(){
digitalWrite(Valve8,LOW);
mode = 28;
delay(940);
timerSec--;
if ((timerSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
digitalWrite(Valve8,HIGH);
}
timerMin = timerSec/60;
lcdUpdate();
}
void wateringAUTO(){
wateringZONE1();
lcdUpdate();
if (pomprust==true){
pompRust();
}
wateringZONE2();
lcdUpdate();
if (pomprust==true){
pompRust();
}
wateringZONE3();
lcdUpdate();
if (pomprust==true){
pompRust();
}
wateringZONE4();
lcdUpdate();
}
void wateringAUTO2(){
wateringZONE5();
lcdUpdate();
if (pomprust==true){
pompRust();
}
wateringZONE6();
lcdUpdate();
if (pomprust==true){
pompRust();
}
wateringZONE7();
lcdUpdate();
if (pomprust==true){
pompRust();
}
wateringZONE8();
lcdUpdate();
}
void pompRust(){
mode = 200;
delay(950);
timerRustSec--;
if ((timerRustSec <= 0)|(digitalRead(buttonPin)== 1)){
mode=0;
}
timerRustMin = timerRustSec/60;
lcdUpdate();
}
void screen0(){
timerRustMin = 15;
timerSettingSec = 60*timerSettingMin;
timerSec = timerSettingSec;
timerRustSec = 60*timerRustMin;
lcd.clear();
lcd.print("Geselecteerd");
lcd.setCursor(0,1);
lcd.print("prog voltooid");
}
void screen1(){
timerRustMin = 15;
timerSettingSec = 60*timerSettingMin;
timerSec = timerSettingSec;
timerRustSec = 60*timerRustMin;
lcd.clear();
lcd.print("Manuele");
lcd.setCursor(0,1);
lcd.print("modus");
}
void screen2(){
lcd.clear();
lcd.print("Automatische");
lcd.setCursor(0,1);
lcd.print("modus");
}
void screen3(){
lcd.clear();
lcd.print("Instellingen");
}
void screen11(){
lcd.clear();
lcd.print("ZONE 1");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen12(){
lcd.clear();
lcd.print("ZONE 2");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen13(){
lcd.clear();
lcd.print("ZONE 3");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen14(){
lcd.clear();
lcd.print("ZONE 4");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen15(){
lcd.clear();
lcd.print("ZONE 5");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen16(){
lcd.clear();
lcd.print("ZONE 6");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen17(){
lcd.clear();
lcd.print("ZONE 7");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen18(){
lcd.clear();
lcd.print("ZONE 8");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen21(){
lcd.clear();
lcd.print("ZONE 1 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE1();
}
void screen22(){
lcd.clear();
lcd.print("ZONE 2 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE2();
}
void screen23(){
lcd.clear();
lcd.print("ZONE 3 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE3();
}
void screen24(){
lcd.clear();
lcd.print("ZONE 4 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE4();
}
void screen25(){
lcd.clear();
lcd.print("ZONE 5 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE5();
}
void screen26(){
lcd.clear();
lcd.print("ZONE 6 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE6();
}
void screen27(){
lcd.clear();
lcd.print("ZONE 7 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE7();
}
void screen28(){
lcd.clear();
lcd.print("ZONE 8 Actief");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerMin);
lcd.setCursor(13,1);
lcd.print("min");
wateringZONE8();
}
void screen31(){
lcd.clear();
lcd.print("Auto ZONE 1234");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen32(){
lcd.clear();
lcd.print("Auto ZONE 5678");
lcd.setCursor(0,1);
lcd.print("> Houd ingedrukt");
}
void screen41(){
lcd.clear();
lcd.print("Automatische");
lcd.setCursor(0,1);
lcd.print("modus gestart");
delay(2000);
wateringAUTO();
}
void screen42(){
lcd.clear();
lcd.print("Automatische");
lcd.setCursor(0,1);
lcd.print("modus gestart");
delay(2000);
wateringAUTO2();
}
void screen51(){
lcd.clear();
lcd.print("Zonetijd");
}
void screen52(){
lcd.clear();
lcd.print("Pompinstelling");
}
void screen71(){
lcd.clear();
lcd.print("Tijdinstelling:");
lcd.setCursor(0,1);
lcd.print(timerSettingMin);
lcd.setCursor(3,1);
lcd.print("min");
}
void screen72(){
lcd.clear();
lcd.print("Afkoelpauze:");
lcd.setCursor(0,1);
if (pomprust==true){lcd.print("AAN");}
if (pomprust==false){lcd.print("UIT");}
}
void screen100(){
lcd.clear();
lcd.print("Instellingen");
lcd.setCursor(0,1);
lcd.print("opgeslagen");
EEPROM.update(addr1,timerSettingMin);
delay(2000);
mode = 1;
lcdUpdate();
}
void screen101(){
lcd.clear();
lcd.print("Instellingen");
lcd.setCursor(0,1);
lcd.print("opgeslagen");
EEPROM.update(addr2,pomprust);
pomprust = EEPROM.read(addr2);
delay(2000);
mode = 1;
lcdUpdate();
}
void screen200(){
lcd.clear();
lcd.print("AFKOELPAUZE pomp");
lcd.setCursor(0,1);
lcd.print("Resterend:");
lcd.setCursor(11,1);
lcd.print(timerRustMin);
lcd.setCursor(13,1);
lcd.print("min");
pompRust();
}