#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line display
Adafruit_SSD1306 display(128, 64, &Wire, -1);
//Counters to change positions of pages and sub-menus
int page_counter=1 ; //To move beetwen pages
int subpage_counter=0; //To move submenu 1 valve1
int subpage2_counter=0; //To move submenu 2 drop1
//-------Pins-----//
int up = 19; //Up/Yes button
int sel = 18; //Select button
int down = 5; //Down/No button
int valve = 26; //valve 1
int trigger = 27; //Trigger
//---------Storage states of buttons for debounce function-----//
boolean current_up = LOW;
boolean last_up=LOW;
boolean current_sel = LOW;
boolean last_sel = LOW;
boolean last_down = LOW;
boolean current_down = LOW;
boolean continue_up = LOW;
boolean continue_down =LOW;
//--------Valve states-----------//
int drop_1 = 200;
int drop_2 = 200;
int drop_3 = 200;
int delay_1 = 200;
int delay_2 = 200;
int delay_test = 250;
int valvesel1 =0;
int valvesel2 =0;
int valvesel3 =0;
int valve_cycle =1;
int trigger_1 =200;
int var=0;
int var2=0;
//Custom return char
byte back[8] = {
0b00100,
0b01000,
0b11111,
0b01001,
0b00101,
0b00001,
0b00001,
0b11111
};
//Custom arrow char
byte arrow[8] = {
0b01000,
0b00100,
0b00010,
0b11111,
0b00010,
0b00100,
0b01000,
0b00000
};
void setup() {
// Declare pin modes
pinMode(valve,OUTPUT);
pinMode(trigger,OUTPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(20, 10);
display.println("Simple Dropper");
display.setCursor(58, 25);
display.println("V3");
display.setCursor(30, 52);
display.println("By Jan Kops");
display.display();
delay(2000);
display.clearDisplay();
display.display();
}
//---- De-bouncing function for all buttons----//
boolean debounce(boolean last, int pin)
{
boolean current = digitalRead(pin);
if (last != current)
{
delay(10);
current = digitalRead(pin);
}
return current;
}
void loop() {
current_up = debounce(last_up, up); //Debounce for Up button
current_sel = debounce(last_sel, sel); //Debounce for Select button
current_down = debounce(last_down, down); //Debounce for Down button
//----Page counter function to move pages----//
if(subpage_counter==0 && subpage2_counter==0){ // up/down buttons enabled if subcounters are 0,Disabled if 1,2..etc to work on submenus
//Page Up
if (last_up== LOW && current_up == HIGH){ //Up button pressed
display.clearDisplay();
display.display(); //Clear lcd if page is changed to print new one
if(page_counter <8){ //Page counter never higher than 3(total of pages)
page_counter= page_counter +1; //Page up
}
else{
page_counter= 1; //If higher than 3 (last page) stay on page 3(change to 1 if you want to rotate)
}
}
last_up = current_up; //Save up button last state
//Page Down
if (last_down== LOW && current_down == HIGH){//Down button pressed
display.clearDisplay();
display.display(); //Clear lcd if page is changed to print new one
if(page_counter >1){ //Page counter never lower than 1 (total of pages)
page_counter= page_counter -1; //Page down
}
else{
page_counter= 8; //If lower than 1(first page) stay on page 1(change to 3 if you want to rotate)
}
}
last_down = current_down; //Save down button last state
}
//------- Switch function to write and show what you want---//
switch (page_counter) {
case 1: { //Design of page 1
//Static objects
display.clearDisplay();
display.setCursor(0, 10);
display.println("Drop Select");
display.setCursor(5, 20);
display.println("1th");
display.setCursor(5, 30);
display.println("2nd");
display.setCursor(5, 40);
display.println("3rd");
display.setCursor(64, 20);
display.println(drop_1);
display.setCursor(64, 30);
display.println(drop_2);
display.setCursor(64, 40);
display.println(drop_3);
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <4){ // subpage counter never higher than 2(total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 2 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage1_counter =1) Drop 1
if(subpage2_counter==1){
display.setCursor(100, 20);
display.println("*");
//Control drop_1 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=continue_down;
}
//2nd item control(subpage1_counter =2) Drop 2
if(subpage2_counter==2){
display.setCursor(100, 30);
display.println("*");
//Control drop_2 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(drop_2 < 1000){ //drop_2 never higher than 1000 (max value)
drop_2 += 1 ;
}
else{
drop_2 = 0; //If drop_2 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(drop_2 >0){ //drop_2 never lower than 0
drop_2 -=1;
}
else{
drop_2 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=continue_down;
}
//3rd item control(subpage1_counter =3) Drop 3
if(subpage2_counter==3){
display.setCursor(100, 40);
display.println("*");
//Control drop_3 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(drop_3 < 1000){ //drop_3 never higher than 1000 (max value)
drop_3 += 1 ;
}
else{
drop_3 = 0; //If drop_3 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(drop_3 >0){ //drop_3 never lower than 0
drop_3 -=1;
}
else{
drop_3 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=continue_down;
}
//quit submenu
//Second item control (subpage1_counter==2) back
if(subpage2_counter==4){
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to valve1 control
}
last_down=current_down;
}
display.display();
}//case 1 end
break;
case 2: { //Design of page 2
//Static objects
display.clearDisplay();
display.setCursor(0, 10);
display.println("Delay");
display.setCursor(5, 20);
display.println("1th");
display.setCursor(5, 30);
display.println("2nd");
display.setCursor(64, 20);
display.println(delay_1);
display.setCursor(64, 30);
display.println(delay_2);
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <3){ // subpage counter never higher than 2(total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 2 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage1_counter =1) Drop 1
if(subpage2_counter==1){
display.setCursor(100, 20);
display.println("*");
//Control delay_1 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(delay_1 < 1000){ //delay_1 never higher than 1000 (max value)
delay_1 += 1 ;
}
else{
delay_1 = 0; //If delay_1 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(delay_1 >0){ //delay_1 never lower than 0
delay_1 -=1;
}
else{
delay_1 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=continue_down;
}
//2nd item control(subpage1_counter =2) Drop 2
if(subpage2_counter==2){
display.setCursor(100, 30);
display.println("*");
//Control delay_2 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(delay_2 < 1000){ //delay_2 never higher than 1000 (max value)
delay_2 += 1 ;
}
else{
delay_2 = 0; //If delay_2 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(delay_2 >0){ //delay_2 never lower than 0
delay_2 -=1;
}
else{
delay_2 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=continue_down;
}
//quit submenu
//Second item control (subpage1_counter==2) back
if(subpage2_counter==3){
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to valve1 control
}
last_down=current_down;
}
}//case 2 end
display.display();
break;
case 3: { //Design of page 3
//Static objects
display.clearDisplay();
display.setCursor(0, 10);
display.println("Camera Delay");
display.setCursor(5, 20);
display.println(trigger_1);
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <2){ // subpage counter never higher than 2(total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 2 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage1_counter =1) trigger_1
if(subpage2_counter==1){
display.setCursor(100, 20);
display.println("*");
//Control trigger_1 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(trigger_1 < 1000){ //trigger_1 never higher than 1000 (max value)
trigger_1 += 1 ;
}
else{
trigger_1 = 0; //If trigger_1 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(trigger_1 >0){ //trigger_1 never lower than 0
trigger_1 -=1;
}
else{
trigger_1 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(trigger_1 < 1000){ //trigger_1 never higher than 1000 (max value)
trigger_1 += 1 ;
}
else{
trigger_1 = 0; //If trigger_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(trigger_1 >0){ //trigger_1 never lower than 0
trigger_1 -=1;
}
else{
trigger_1 = 0;
}
}
last_down=continue_down;
}
//quit submenu
//Second item control (subpage1_counter==2) back
if(subpage2_counter==2){
lcd.setCursor(16,1);
lcd.print(" "); //Delete last arrow position
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to valve1 control
}
last_down=current_down;
}
display.display();
}//case 3 end
break;
case 4: { //Design of page 5
//Static objects
lcd.setCursor(2,0);
lcd.print("Release 2 drops");
lcd.setCursor(7,2);
}
lcd.print("Ready");
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
while (var < valve_cycle) {
digitalWrite(valve, HIGH);
delay(drop_1);
digitalWrite(valve, LOW);
delay(delay_1);
digitalWrite(valve, HIGH);
delay(drop_2);
digitalWrite(valve, LOW);
delay(trigger_1);
digitalWrite(trigger, HIGH);
delay(500);
digitalWrite(trigger, LOW);
delay(50);
var++;
}
var=0;
//Second item control (subpage1_counter==2) back
if(subpage2_counter==2){
lcd.setCursor(6,1);
lcd.print(" "); //Delete last arrow position
lcd.setCursor(14,1); //Place the arrow
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
lcd.setCursor(14,1);
lcd.print(" ");
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to int valve_cycle control
}
last_down=current_down;
}
}//case 4 end
break;
case 5: { //Design of page 7
//Static objects
lcd.setCursor(2,0);
lcd.print("Release 3 drops");
lcd.setCursor(7,2);
}
lcd.print("Ready");
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
while (var < valve_cycle) {
digitalWrite(valve, HIGH);
delay(drop_1);
digitalWrite(valve, LOW);
delay(delay_1);
digitalWrite(valve, HIGH);
delay(drop_2);
digitalWrite(valve, LOW);
delay(delay_2);
digitalWrite(valve, HIGH);
delay(drop_3);
digitalWrite(valve, LOW);
delay(trigger_1);
digitalWrite(trigger, HIGH);
delay(500);
digitalWrite(trigger, LOW);
delay(50);
var++;
}
var=0;
//Second item control (subpage1_counter==2) back
if(subpage2_counter==2){
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to int valve_cycle control
}
last_down=current_down;
}
}//case 5 end
break;
case 6: { //Design of page 8
//Static objects
lcd.setCursor(5,0);
lcd.print("Test drop");
lcd.setCursor(8,2);
lcd.print("Run");
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <2){ // subpage counter never higher than 2(total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 2 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage1_counter =1) Drop 1
if(subpage2_counter==1){
lcd.setCursor(6,2);
lcd.print("*");
//Control drop_1 variable
if (last_up== LOW && current_up == HIGH){ //Up +
digitalWrite(valve, HIGH);
delay(60);
digitalWrite(valve, LOW);
delay(250);
}
else{
}
}
//quit submenu
//Second item control (subpage1_counter==2) back
if(subpage2_counter==2){
lcd.setCursor(6,2);
lcd.print(" "); //Delete last arrow position
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to valve1 control
}
last_down=current_down;
}
}//case 6 end
break;
case 7: { //Design of page 4
//Static objects
lcd.setCursor(0,0);
lcd.print("Valve");
lcd.setCursor(7,0);
lcd.print("1th");
lcd.setCursor(11,0);
lcd.print("Delay");
lcd.setCursor(7,1);
if(drop_1 <100){ //To avoid "0" of number 10
lcd.setCursor(7,1);
lcd.print(" ");
lcd.setCursor(8,1);
}
lcd.print(drop_1);
lcd.setCursor(12,1);
if(delay_test <100){ //To avoid "0" of number 10
lcd.setCursor(12,1);
lcd.print(" ");
lcd.setCursor(13,1);
}
lcd.print(delay_test);
lcd.setCursor(17,1);
lcd.print("Run");
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <4){ // subpage counter never higher than 2(total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 2 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage1_counter =1) Drop 1
if(subpage2_counter==1){
lcd.setCursor(6,1);
lcd.print("*");
//Control drop_1 variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(drop_1 < 1000){ //drop_1 never higher than 1000 (max value)
drop_1 += 1 ;
}
else{
drop_1 = 0; //If drop_1 higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(drop_1 >0){ //drop_1 never lower than 0
drop_1 -=1;
}
else{
drop_1 = 0;
}
}
last_down=continue_down;
}
//2nd item control(subpage1_counter =2) Drop 2
if(subpage2_counter==2){
lcd.setCursor(6,1);
lcd.print(" "); //Delete last arrow position
lcd.setCursor(11,1);
lcd.print("*");
//Control delay_test variable
if (last_up== LOW && current_up == HIGH){ //Up +
if(delay_test < 1000){ //delay_test never higher than 1000 (max value)
delay_test += 1 ;
}
else{
delay_test = 0; //If delay_test higher than 1000, return to 0
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){ //Down -
if(delay_test >0){ //delay_test never lower than 0
delay_test -=1;
}
else{
delay_test = 0;
}
}
last_down=current_down;
if (last_up== HIGH && continue_up == HIGH){ //Up +
if(delay_test < 1000){ //delay_test never higher than 1000 (max value)
delay_test += 1 ;
}
else{
delay_test = 0; //If delay_test higher than 1000, return to 0
}
}
last_up=continue_up;
if(last_down== HIGH && continue_down == HIGH){ //Down -
if(delay_test >0){ //delay_test never lower than 0
delay_test -=1;
}
else{
delay_test = 0;
}
}
last_down=continue_down;
}
//3rd item control(subpage1_counter =3) Drop 3
if(subpage2_counter==3){
lcd.setCursor(11,1);
lcd.print(" "); //Delete last arrow position
lcd.setCursor(16,1);
lcd.print("*");
//Control valvesel3 variable
if (last_up== LOW && current_up == HIGH){
digitalWrite(valve, HIGH);
delay(drop_1);
digitalWrite(valve, LOW);
delay(delay_test);
digitalWrite(trigger, HIGH);
delay(500);
digitalWrite(trigger, LOW);
delay(50);
}
last_up=current_up;
}
//quit submenu
//Second item control (subpage1_counter==2) back
if(subpage2_counter==4){
lcd.setCursor(16,1);
lcd.print(" "); //Delete last arrow position
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to valve1 control
}
last_down=current_down;
}
}//case 7 end
break;
case 8: { //Design of page 8
//Static objects
lcd.setCursor(2,0);
lcd.print("Empty Reservoar");
lcd.setCursor(8,2);
lcd.print("Run");
// Sub counter 1 control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <2){ // subpage counter never higher than 2(total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 2 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage1_counter =1) Drop 1
if(subpage2_counter==1){
lcd.setCursor(6,2);
lcd.print("*");
//Control drop_1 variable
if (last_up== LOW && current_up == HIGH){ //Up +
digitalWrite(valve, HIGH);
}
if(last_down== LOW && current_down == HIGH){
digitalWrite(valve, LOW);
}
else{
}
}
//quit submenu
//Second item control (subpage1_counter==2) back
if(subpage2_counter==2){
lcd.setCursor(6,2);
lcd.print(" "); //Delete last arrow position
if (last_up== LOW && current_up == HIGH){
subpage2_counter=0; //Exit submenu, up/down pages enabled
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){
subpage2_counter=1; //Stay on sub menu, return to valve1 control
}
last_down=current_down;
}
}//case 8 end
break;
}//switch end
}//loop end