ECE595 Hydroponics water balancing system (Project 2)

Dependencies:   mbed phread TextLCD

Committer:
thecreid1
Date:
Wed May 06 14:58:48 2020 +0000
Revision:
0:e628a132c5fa
Project 2 Firmware;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
thecreid1 0:e628a132c5fa 1 /** ECE595 Project 2: IoT Hydroponics
thecreid1 0:e628a132c5fa 2 ** ##Complete Firmware##
thecreid1 0:e628a132c5fa 3 **/
thecreid1 0:e628a132c5fa 4 /* mbed Microcontroller Library
thecreid1 0:e628a132c5fa 5 * Copyright (c) 2018 ARM Limited
thecreid1 0:e628a132c5fa 6 * SPDX-License-Identifier: Apache-2.0
thecreid1 0:e628a132c5fa 7 */
thecreid1 0:e628a132c5fa 8
thecreid1 0:e628a132c5fa 9 #include "mbed.h"
thecreid1 0:e628a132c5fa 10 #include "phread.h"
thecreid1 0:e628a132c5fa 11 #include "PwmOut.h"
thecreid1 0:e628a132c5fa 12 #include "TextLCD.h"
thecreid1 0:e628a132c5fa 13 #include <string>
thecreid1 0:e628a132c5fa 14 #include <sstream>
thecreid1 0:e628a132c5fa 15 #include <iomanip>
thecreid1 0:e628a132c5fa 16
thecreid1 0:e628a132c5fa 17 Serial HC06(PTC15, PTC14); //Create serial object for the HC06 to be read from/written to
thecreid1 0:e628a132c5fa 18 Serial pc(USBTX,USBRX); //Create serial object for the COM port to interface with a terminal application
thecreid1 0:e628a132c5fa 19 Ticker timeKeep; //Create the time keeping interrupt. More information below in its definition
thecreid1 0:e628a132c5fa 20
thecreid1 0:e628a132c5fa 21 //** Servo Initialization
thecreid1 0:e628a132c5fa 22 PwmOut smoto(PTA1);
thecreid1 0:e628a132c5fa 23 DigitalOut led1(LED1);
thecreid1 0:e628a132c5fa 24 DigitalOut phPump1(D0);
thecreid1 0:e628a132c5fa 25 DigitalOut phPump2(D1);
thecreid1 0:e628a132c5fa 26 PHread sensor(A0);
thecreid1 0:e628a132c5fa 27 //Serial pc(USBTX, USBRX);
thecreid1 0:e628a132c5fa 28
thecreid1 0:e628a132c5fa 29 //** LCD pin intialization
thecreid1 0:e628a132c5fa 30 TextLCD lcd(PTC12, PTC4, PTD0, PTD2, PTD3, PTD1); // rs, e, d4-d7
thecreid1 0:e628a132c5fa 31
thecreid1 0:e628a132c5fa 32
thecreid1 0:e628a132c5fa 33 //** Global ints to keep/track time
thecreid1 0:e628a132c5fa 34 int cthours = 0; //Current time integers
thecreid1 0:e628a132c5fa 35 int ctminutes = 0; //These are incremented using a ticker component to keep
thecreid1 0:e628a132c5fa 36 int ctseconds = 0; //real time.
thecreid1 0:e628a132c5fa 37
thecreid1 0:e628a132c5fa 38 float phMeas = 7.0;
thecreid1 0:e628a132c5fa 39 int gallon_cnt = 5; //User set: gallons currently in the tank //tohours
thecreid1 0:e628a132c5fa 40
thecreid1 0:e628a132c5fa 41 int min_cnt = 0; //Integer tracking the amount of time the pump is running
thecreid1 0:e628a132c5fa 42
thecreid1 0:e628a132c5fa 43 char buffer[10]; //buffer for the serial comms between BT module and board, sent from mobile app to BT
thecreid1 0:e628a132c5fa 44 char *initarray[3]; //array for inital storage of timer info
thecreid1 0:e628a132c5fa 45
thecreid1 0:e628a132c5fa 46 //** Delimiter section for parsing data
thecreid1 0:e628a132c5fa 47 char sdelim[] = " "; //seperation delimiter
thecreid1 0:e628a132c5fa 48 char cdelim[] = "c"; //current time command
thecreid1 0:e628a132c5fa 49 char gdelim[] = "g"; //Gallon Measurement Sent from the App
thecreid1 0:e628a132c5fa 50
thecreid1 0:e628a132c5fa 51 bool pumpIt = false;
thecreid1 0:e628a132c5fa 52
thecreid1 0:e628a132c5fa 53 std::string phOut;
thecreid1 0:e628a132c5fa 54 std::string timeOut;
thecreid1 0:e628a132c5fa 55
thecreid1 0:e628a132c5fa 56 std::stringstream phStream;
thecreid1 0:e628a132c5fa 57 std::stringstream timeStream;
thecreid1 0:e628a132c5fa 58
thecreid1 0:e628a132c5fa 59 //** prereference functions
thecreid1 0:e628a132c5fa 60 void timekeep(void);
thecreid1 0:e628a132c5fa 61 void hcRxCallback(void);
thecreid1 0:e628a132c5fa 62 float ph_measurement(void);
thecreid1 0:e628a132c5fa 63 void pumpOn(void);
thecreid1 0:e628a132c5fa 64 void pumpOff(void);
thecreid1 0:e628a132c5fa 65 void printTime(void);
thecreid1 0:e628a132c5fa 66
thecreid1 0:e628a132c5fa 67 //** main function
thecreid1 0:e628a132c5fa 68 int main()
thecreid1 0:e628a132c5fa 69 {
thecreid1 0:e628a132c5fa 70 //*Baud rate init
thecreid1 0:e628a132c5fa 71 HC06.baud(9600);
thecreid1 0:e628a132c5fa 72 pc.baud(9600);
thecreid1 0:e628a132c5fa 73
thecreid1 0:e628a132c5fa 74 //*interupt init
thecreid1 0:e628a132c5fa 75 timeKeep.attach(&timekeep, 0.999);
thecreid1 0:e628a132c5fa 76 HC06.attach(&hcRxCallback, Serial::RxIrq);
thecreid1 0:e628a132c5fa 77
thecreid1 0:e628a132c5fa 78 //*infinite loop
thecreid1 0:e628a132c5fa 79 while(1) {
thecreid1 0:e628a132c5fa 80 if(pumpIt){ //if pump has not been run this hour
thecreid1 0:e628a132c5fa 81 if(phMeas > 7.5){ //run either pump for a second if needed
thecreid1 0:e628a132c5fa 82 phPump1.write(1);
thecreid1 0:e628a132c5fa 83 wait(1);
thecreid1 0:e628a132c5fa 84 phPump1 = 0;
thecreid1 0:e628a132c5fa 85 }
thecreid1 0:e628a132c5fa 86 else if(phMeas < 6.5){
thecreid1 0:e628a132c5fa 87 phPump2 = 1;
thecreid1 0:e628a132c5fa 88 wait(1);
thecreid1 0:e628a132c5fa 89 phPump2 = 0;
thecreid1 0:e628a132c5fa 90 }
thecreid1 0:e628a132c5fa 91 else{}
thecreid1 0:e628a132c5fa 92 pumpIt = false; //stop pumps from running for another hour
thecreid1 0:e628a132c5fa 93 }
thecreid1 0:e628a132c5fa 94 }
thecreid1 0:e628a132c5fa 95 }
thecreid1 0:e628a132c5fa 96
thecreid1 0:e628a132c5fa 97 //** Timekeeping function. This function is triggered every 0.999 seconds as an interrupt
thecreid1 0:e628a132c5fa 98 void timekeep()
thecreid1 0:e628a132c5fa 99 {
thecreid1 0:e628a132c5fa 100
thecreid1 0:e628a132c5fa 101 ctseconds += 1; //Increment the seconds and compare to 60
thecreid1 0:e628a132c5fa 102 if (ctseconds >= 60) {
thecreid1 0:e628a132c5fa 103 ctminutes += 1;
thecreid1 0:e628a132c5fa 104 ctseconds = 0;
thecreid1 0:e628a132c5fa 105
thecreid1 0:e628a132c5fa 106 if(min_cnt == 1) //if the minute counter was just reset, turn on the pump
thecreid1 0:e628a132c5fa 107 pumpOn();
thecreid1 0:e628a132c5fa 108 else if(min_cnt == 16){ //after 15 minutes, turn the pump off
thecreid1 0:e628a132c5fa 109 pumpOff();
thecreid1 0:e628a132c5fa 110 min_cnt = 0; //stop minute counter
thecreid1 0:e628a132c5fa 111 }
thecreid1 0:e628a132c5fa 112 else{}; //empty else loop
thecreid1 0:e628a132c5fa 113
thecreid1 0:e628a132c5fa 114 if(min_cnt % 2){ //on odd minutes, run this code
thecreid1 0:e628a132c5fa 115 phMeas = ph_measurement(); //read and set measurements
thecreid1 0:e628a132c5fa 116 printTime(); //set time
thecreid1 0:e628a132c5fa 117 lcd.printf("%s\n%s", phOut, timeOut); //send ph and time to LCD
thecreid1 0:e628a132c5fa 118 }
thecreid1 0:e628a132c5fa 119
thecreid1 0:e628a132c5fa 120
thecreid1 0:e628a132c5fa 121 if(min_cnt){ //if minute count is not 0, increment
thecreid1 0:e628a132c5fa 122 min_cnt++;
thecreid1 0:e628a132c5fa 123 }
thecreid1 0:e628a132c5fa 124 }
thecreid1 0:e628a132c5fa 125 if (ctminutes >= 60) { //compare minutes to 60
thecreid1 0:e628a132c5fa 126 cthours += 1;
thecreid1 0:e628a132c5fa 127 ctminutes = 0;
thecreid1 0:e628a132c5fa 128 min_cnt = 1; //reset the minute counter
thecreid1 0:e628a132c5fa 129 pumpIt = true; //reset the boolean allowing the pumps to run
thecreid1 0:e628a132c5fa 130 }
thecreid1 0:e628a132c5fa 131 if (cthours >= 24) { //compare hours to 24
thecreid1 0:e628a132c5fa 132 cthours = 0;
thecreid1 0:e628a132c5fa 133 }
thecreid1 0:e628a132c5fa 134
thecreid1 0:e628a132c5fa 135 pc.printf("time: %d : %d : %d\n\n",cthours,ctminutes,ctseconds);
thecreid1 0:e628a132c5fa 136 return;
thecreid1 0:e628a132c5fa 137 }
thecreid1 0:e628a132c5fa 138
thecreid1 0:e628a132c5fa 139 /* This the RX_IRQ. There are global variables altered within this function,
thecreid1 0:e628a132c5fa 140 ** therefore disabling IRQ will allow this to operate without any interruption
thecreid1 0:e628a132c5fa 141 ** ***Note*** this function will not exit and print unless the buffer has read
thecreid1 0:e628a132c5fa 142 ** into it 8 bits of data.
thecreid1 0:e628a132c5fa 143 **/
thecreid1 0:e628a132c5fa 144 void hcRxCallback()
thecreid1 0:e628a132c5fa 145 {
thecreid1 0:e628a132c5fa 146 __disable_irq();
thecreid1 0:e628a132c5fa 147 HC06.gets(buffer, 8);
thecreid1 0:e628a132c5fa 148 pc.printf("recieved: %s\n",buffer);
thecreid1 0:e628a132c5fa 149
thecreid1 0:e628a132c5fa 150 //*String Concatenation
thecreid1 0:e628a132c5fa 151 int i = 0;
thecreid1 0:e628a132c5fa 152 char *p = strtok(buffer, sdelim); //Delimiter to parse the string into tokens
thecreid1 0:e628a132c5fa 153 while(p != NULL) { //loops while there is data to be read
thecreid1 0:e628a132c5fa 154 initarray[i++] = p; //Saves the value of P into the next slot of initarray
thecreid1 0:e628a132c5fa 155 p = strtok(NULL, sdelim); //rinse and repeat
thecreid1 0:e628a132c5fa 156 }
thecreid1 0:e628a132c5fa 157 /** For debug purposes, this will print the array elements for the
thecreid1 0:e628a132c5fa 158 ** user to review.
thecreid1 0:e628a132c5fa 159 **/
thecreid1 0:e628a132c5fa 160 for(i = 0; i<3; i++) {
thecreid1 0:e628a132c5fa 161 pc.printf("%s\n",initarray[i]);
thecreid1 0:e628a132c5fa 162 }
thecreid1 0:e628a132c5fa 163 //*String sorting
thecreid1 0:e628a132c5fa 164 if (!strcmp(initarray[0], cdelim)) { //Compare the command character to the 'c' command
thecreid1 0:e628a132c5fa 165 cthours = atoi(initarray[1]);
thecreid1 0:e628a132c5fa 166 ctminutes = atoi(initarray[2]);
thecreid1 0:e628a132c5fa 167 pc.printf("new time: %d %d\n\n",cthours,ctminutes);
thecreid1 0:e628a132c5fa 168 }
thecreid1 0:e628a132c5fa 169 if (!strcmp(initarray[0], gdelim)) { //Compare the command character to the 'g' command
thecreid1 0:e628a132c5fa 170 gallon_cnt = atoi(initarray[1]);
thecreid1 0:e628a132c5fa 171 pc.printf("Current Gallon Amount: %d\n\n",gallon_cnt);
thecreid1 0:e628a132c5fa 172 }
thecreid1 0:e628a132c5fa 173
thecreid1 0:e628a132c5fa 174 __enable_irq();
thecreid1 0:e628a132c5fa 175 return;
thecreid1 0:e628a132c5fa 176 }
thecreid1 0:e628a132c5fa 177
thecreid1 0:e628a132c5fa 178 //** Time Condition Begin, EveryHOur on the Hour, cycle a water pump for 15 min
thecreid1 0:e628a132c5fa 179 //** and add ph up and/or ph downt to the mixture for desired ph level
thecreid1 0:e628a132c5fa 180 float ph_measurement()
thecreid1 0:e628a132c5fa 181 {
thecreid1 0:e628a132c5fa 182 float phMeasurement;
thecreid1 0:e628a132c5fa 183 //Check ph
thecreid1 0:e628a132c5fa 184 phMeasurement = sensor.get_pH();
thecreid1 0:e628a132c5fa 185 phStream << "pH : " << std::fixed << std::setprecision(2) << phMeasurement;
thecreid1 0:e628a132c5fa 186 phOut = phStream.str();
thecreid1 0:e628a132c5fa 187 return phMeasurement;
thecreid1 0:e628a132c5fa 188 }
thecreid1 0:e628a132c5fa 189
thecreid1 0:e628a132c5fa 190 void printTime()
thecreid1 0:e628a132c5fa 191 {
thecreid1 0:e628a132c5fa 192 std::stringstream sHours;
thecreid1 0:e628a132c5fa 193 std::stringstream sMinutes;
thecreid1 0:e628a132c5fa 194
thecreid1 0:e628a132c5fa 195 if(cthours == 24)
thecreid1 0:e628a132c5fa 196 sHours << "00";
thecreid1 0:e628a132c5fa 197 else if(cthours < 10)
thecreid1 0:e628a132c5fa 198 sHours << "0" << cthours;
thecreid1 0:e628a132c5fa 199 else
thecreid1 0:e628a132c5fa 200 sHours << cthours;
thecreid1 0:e628a132c5fa 201
thecreid1 0:e628a132c5fa 202 if(ctminutes == 60)
thecreid1 0:e628a132c5fa 203 sMinutes << "00";
thecreid1 0:e628a132c5fa 204 else if(ctminutes < 10)
thecreid1 0:e628a132c5fa 205 sMinutes << "0" << ctminutes;
thecreid1 0:e628a132c5fa 206 else
thecreid1 0:e628a132c5fa 207 sMinutes << ctminutes;
thecreid1 0:e628a132c5fa 208
thecreid1 0:e628a132c5fa 209 timeStream << "Time : " << sHours.str() << ":" << sMinutes.str();
thecreid1 0:e628a132c5fa 210 timeOut = timeStream.str();
thecreid1 0:e628a132c5fa 211 }
thecreid1 0:e628a132c5fa 212
thecreid1 0:e628a132c5fa 213 void pumpOn()
thecreid1 0:e628a132c5fa 214 {
thecreid1 0:e628a132c5fa 215 smoto.pulsewidth_ms(2.0f);
thecreid1 0:e628a132c5fa 216 }
thecreid1 0:e628a132c5fa 217
thecreid1 0:e628a132c5fa 218 void pumpOff()
thecreid1 0:e628a132c5fa 219 {
thecreid1 0:e628a132c5fa 220 smoto.pulsewidth_ms(0.0f);
thecreid1 0:e628a132c5fa 221 }
thecreid1 0:e628a132c5fa 222