diff --git a/watering_system_mini_project/MenuItem.cpp b/watering_system_mini_project/MenuItem.cpp index 62e94d0..e74a71e 100644 --- a/watering_system_mini_project/MenuItem.cpp +++ b/watering_system_mini_project/MenuItem.cpp @@ -1,28 +1,34 @@ #include "MenuItem.h" #include "Arduino.h" +// **** class and method definitions **** MenuItem::MenuItem() { } +// **** overall MenuItem **** MenuItem::MenuItem(const char* name) { MenuItem::name = name; MenuItem::parent = NULL; MenuItem::next = NULL; } +// links to the defined 'parent' menu item MenuItem* MenuItem::goBack() { return MenuItem::parent; } +// links to the defined 'next' menu item MenuItem* MenuItem::goDown() { return MenuItem::next; } +// no default behaviour MenuItem* MenuItem::goRight() { return NULL; } +// left empty for the default menu item as it doesn't apply here void MenuItem::selectLeft() { } @@ -33,15 +39,19 @@ return false; } +// spits out the name and nothing else String MenuItem::display() { return MenuItem::name; } +// **** BranchMenuItem **** +// points to a set of menu items higher in th etree BranchMenuItem::BranchMenuItem(const char* name, const MenuItem* child) { BranchMenuItem::name = name; BranchMenuItem::child = child; } +// the goRight() function points towards a child menu item MenuItem* BranchMenuItem::goRight() { return BranchMenuItem::child; } @@ -50,7 +60,8 @@ return String(BranchMenuItem::name) + " ->"; } - +// **** IntValueItem **** +// contains an integer, whose value can be edited by the user IntValueItem::IntValueItem(char const* name, int initial, int min, int max) { IntValueItem::name = name; IntValueItem::value = initial; @@ -59,40 +70,50 @@ } -void IntValueItem::selectRight() { // increment +// selectLeft() and selectRight() - decrease or increase the value of the integer by 1, respectively +void IntValueItem::selectRight() { if (IntValueItem::value < IntValueItem::max){ IntValueItem::value++; } } -void IntValueItem::selectLeft() { // increment +void IntValueItem::selectLeft() { if (IntValueItem::value > IntValueItem::min){ IntValueItem::value--; } } +// display() - outputs the name and current value of the integer on separate lines. String IntValueItem::display() { return String(IntValueItem::name) + "\n" + String(IntValueItem::value); } + +// indicates that it's possible to select this item bool IntValueItem::select() { return true; } +// **** BoolValueItem **** +// contains a boolean, whose value can be edited by the user BoolValueItem::BoolValueItem(char const* name, bool initial) { BoolValueItem::name = name; BoolValueItem::value = initial; } -void BoolValueItem::selectRight() { // toggle +// both selectRight() and selectLeft() invert the current value of the item +void BoolValueItem::selectRight() { BoolValueItem::value = !BoolValueItem::value; } -void BoolValueItem::selectLeft() { // toggle +void BoolValueItem::selectLeft() { BoolValueItem::value = !BoolValueItem::value; } +// display() - outputs the name and current value of the boolean on separate lines. String BoolValueItem::display() { return String(BoolValueItem::name) + "\n" + (BoolValueItem::value ? "true" : "false"); } + +// indicates that it's possible to select this item bool BoolValueItem::select() { return true; } \ No newline at end of file diff --git a/watering_system_mini_project/MenuItem.h b/watering_system_mini_project/MenuItem.h index dac800b..ed67dbd 100644 --- a/watering_system_mini_project/MenuItem.h +++ b/watering_system_mini_project/MenuItem.h @@ -1,8 +1,11 @@ #ifndef MenuItem_h #define MenuItem_h +// **** class and method declarations **** #include "Arduino.h" +// MenuItem - +// default class, whose only functionality is to display its name and act as a node in the network class MenuItem { public: MenuItem(); @@ -20,6 +23,7 @@ virtual String display(); }; +// subclass of MenuItem, allows for linking to a 'child' menu item, for linking to another layer of menus class BranchMenuItem: public MenuItem { public: BranchMenuItem(const char* name, const MenuItem* child); @@ -28,6 +32,7 @@ String display(); }; +// subclass of MenuItem, allows storage and editing of a single integer value class IntValueItem: public MenuItem { public: IntValueItem(const char* name, const int initialValue, const int min, const int max); @@ -43,6 +48,7 @@ String IntValueItem::display(); }; +// subclass of MenuItem, allows for storage and editing of a single boolean value class BoolValueItem: public MenuItem { public: BoolValueItem(const char* name, const bool initialValue); diff --git a/watering_system_mini_project/watering_system_mini_project.ino b/watering_system_mini_project/watering_system_mini_project.ino index 05ac36d..e338bea 100644 --- a/watering_system_mini_project/watering_system_mini_project.ino +++ b/watering_system_mini_project/watering_system_mini_project.ino @@ -10,18 +10,28 @@ # define LED_RED 5 # define LED_BLUE 3 +// LCD +# define RS 7 +# define EN 8 +# define DB4 9 +# define DB5 10 +# define DB6 11 +# define DB7 12 + +// constants (to avoid unnamed magic numbers in the program) # define cycle_extra_resolution 20 // number of 'substeps' per main step, allowing for extra resolution within the steps # define stepTime 150 // step time in ms # define duty_cycle_max 10 // granularity of the duty cycle - the min value is always 0, and the max is this value, meaning 100% # define duration_max 24 -MenuItem* lightToggle = new BoolValueItem("Toggle", false); +// initialise menu items +BoolValueItem* lightToggle = new BoolValueItem("Toggle", true); IntValueItem* lightCyclePower = new IntValueItem("Cycle Power", 1, 0, 10); IntValueItem* lightCycleOnDuty = new IntValueItem("Cycle On Duty", 1, 0, duty_cycle_max); IntValueItem* lightCycleDuration = new IntValueItem("Cycle Duration", 1, 0, duration_max); -MenuItem* waterToggle = new BoolValueItem("Toggle", false); +BoolValueItem* waterToggle = new BoolValueItem("Toggle", true); IntValueItem* waterCyclePower = new IntValueItem("Cycle Power", 1, 0, 10); IntValueItem* waterCycleOnDuty = new IntValueItem("Cycle On Percent", 1, 0, duty_cycle_max); IntValueItem* waterCycleDuration = new IntValueItem("Cycle Duration", 1, 0, duration_max); @@ -32,12 +42,7 @@ MenuItem* top = new BranchMenuItem("Main menu", waterSettings); MenuItem* current = top; -// MenuItem* toggle = new BoolValueItem("A switch", false); -// MenuItem* sub = new BranchMenuItem("Sub menu", toggle); -// MenuItem* next = new IntValueItem("Power", 1); - -// with the Arduino pin number they are connected to -const int RS = 7, EN = 8, DB4 = 9, DB5 = 10, DB6 = 11, DB7 = 12; +// declare LCD display LiquidCrystal lcd(RS, EN, DB4, DB5, DB6, DB7); // loop control @@ -51,6 +56,65 @@ unsigned long lastStepTime = 0; int waterCyclePosition = 0; int lightCyclePosition = 0; + +void setup() { + Serial.begin(9600); + // pins setup + + // joystick pins + pinMode(JOY_HORIZ, INPUT); + pinMode(JOY_VERT, INPUT); + pinMode(JOY_BUTTON, INPUT); + + // LED pins + pinMode(LED_RED, OUTPUT); + pinMode(LED_BLUE, OUTPUT); + + // initialization for menu items + { + lightSettings->next = waterSettings; + waterSettings->next = lightSettings; + + lightSettings->parent = top; + waterSettings->parent = top; + + top->next = top; + top->parent = top; + + lightToggle->next = lightCyclePower; + lightCyclePower->next = lightCycleOnDuty; + lightCycleOnDuty->next = lightCycleDuration; + lightCycleDuration->next = lightToggle; + + lightToggle->parent = lightSettings; + lightCyclePower->parent = lightSettings; + lightCycleOnDuty->parent = lightSettings; + lightCycleDuration->parent = lightSettings; + + waterToggle->next = waterCyclePower; + waterCyclePower->next = waterCycleOnDuty; + waterCycleOnDuty->next = waterCycleDuration; + waterCycleDuration->next = waterToggle; + + waterToggle->parent = waterSettings; + waterCyclePower->parent = waterSettings; + waterCycleOnDuty->parent = waterSettings; + waterCycleDuration->parent = waterSettings; + } + + + // init LCD + lcd.begin(16, 2); + + // display initial menu + displayMenu(); +} + +/* + * void displayMenu() + * requests the display() string from the currently selected menu item, and outputs it to the LCD + * returns nothing +*/ void displayMenu() { // grab the menu item's display string String out = current->display(); @@ -64,18 +128,28 @@ lcd.print(out.substring(0, sepPos)); lcd.setCursor(0, 1); - + // print selection indicator if(current->select()){ if (selected) lcd.print("#"); else lcd.print(":"); } + // print line 2 // only print if the string has two parts if (sepPos != -1){ lcd.print(out.substring(sepPos+1)); } } +/* + * void handleInterface() + * called each loop + * handles the user controls and menu - + * - grabs the joystick position + * - handles debouncing + * - parse these control signals + * returns nothing +*/ void handleInterface(){ // grab joystick positions int pos_x = analogRead(JOY_HORIZ); @@ -146,6 +220,12 @@ } } +/* + * void handleControl() + * called each loop + * handles the output cycles of the system + * returns nothing +*/ void handleControl(){ // each stepTime millis, advance one in the water cycle. if (millis()-lastStepTime > stepTime){ @@ -156,7 +236,7 @@ if (waterCyclePosition == waterCycleDuration->value*cycle_extra_resolution) waterCyclePosition = 0; // magic no float equation to determine the current position in the cycle, and compare it to the duty cycle - if (duty_cycle_max*(waterCyclePosition) / (waterCycleDuration->value) < (waterCycleOnTime->value*cycle_extra_resolution)) { + if (duty_cycle_max*(waterCyclePosition) / (waterCycleDuration->value) < (waterCycleOnDuty->value*cycle_extra_resolution) && waterToggle->value) { // if the current cycle position has passed the cycleontime variable, turn off the motor. else, turn it on. // MOTORON @@ -174,7 +254,7 @@ Serial.println(duty_cycle_max*(lightCyclePosition) / (lightCycleDuration->value)); Serial.println(lightCycleOnDuty->value*cycle_extra_resolution); - if (duty_cycle_max*(lightCyclePosition) / (lightCycleDuration->value) < (lightCycleOnDuty->value*cycle_extra_resolution)) { + if (duty_cycle_max*(lightCyclePosition) / (lightCycleDuration->value) < (lightCycleOnDuty->value*cycle_extra_resolution) && lightToggle->value) { // if the current cycle position has passed the cycleontime variable, turn off the motor. else, turn it on. // LEDON digitalWrite(LED_RED, HIGH); @@ -184,57 +264,6 @@ } } } -void setup() { - Serial.begin(9600); - // pins setup - - // LCD brightness pin - pinMode(JOY_HORIZ, INPUT); - pinMode(JOY_VERT, INPUT); - pinMode(JOY_BUTTON, INPUT); - - pinMode(LED_RED, OUTPUT); - pinMode(LED_BLUE, OUTPUT); - - // initialization for menu items - { - lightSettings->next = waterSettings; - waterSettings->next = lightSettings; - - lightSettings->parent = top; - waterSettings->parent = top; - - top->next = top; - top->parent = top; - - lightToggle->next = lightCyclePower; - lightCyclePower->next = lightCycleOnDuty; - lightCycleOnDuty->next = lightCycleDuration; - lightCycleDuration->next = lightToggle; - - lightToggle->parent = lightSettings; - lightCyclePower->parent = lightSettings; - lightCycleOnDuty->parent = lightSettings; - lightCycleDuration->parent = lightSettings; - - waterToggle->next = waterCyclePower; - waterCyclePower->next = waterCycleOnDuty; - waterCycleOnDuty->next = waterCycleDuration; - waterCycleDuration->next = waterToggle; - - waterToggle->parent = waterSettings; - waterCyclePower->parent = waterSettings; - waterCycleOnDuty->parent = waterSettings; - waterCycleDuration->parent = waterSettings; - } - - - // init LCD - lcd.begin(16, 2); - - // display initial menu - displayMenu(); -} void loop() { handleInterface();