ECE595 Hydroponics water balancing system (Project 2)

Dependencies:   mbed phread TextLCD

main.cpp

Committer:
thecreid1
Date:
2020-05-06
Revision:
0:e628a132c5fa

File content as of revision 0:e628a132c5fa:

/**     ECE595 Project 2: IoT Hydroponics
 **         ##Complete Firmware##
**/
/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 */

#include "mbed.h"
#include "phread.h"
#include "PwmOut.h"
#include "TextLCD.h"
#include <string>
#include <sstream>
#include <iomanip>

Serial HC06(PTC15, PTC14);  //Create serial object for the HC06 to be read from/written to
Serial pc(USBTX,USBRX);     //Create serial object for the COM port to interface with a terminal application
Ticker timeKeep;            //Create the time keeping interrupt. More information below in its definition

//**    Servo Initialization
PwmOut smoto(PTA1);
DigitalOut led1(LED1);
DigitalOut phPump1(D0);
DigitalOut phPump2(D1);
PHread sensor(A0);
//Serial pc(USBTX, USBRX);

//**    LCD pin intialization
    TextLCD lcd(PTC12, PTC4, PTD0, PTD2, PTD3, PTD1); // rs, e, d4-d7


//**    Global ints to keep/track time 
int cthours     = 0;    //Current time integers
int ctminutes   = 0;    //These are incremented using a ticker component to keep
int ctseconds   = 0;    //real time.

float phMeas = 7.0;
int gallon_cnt  = 5;    //User set: gallons currently in the tank    //tohours

int min_cnt     = 0;    //Integer tracking the amount of time the pump is running

char buffer[10];        //buffer for the serial comms between BT module and board, sent from mobile app to BT
char *initarray[3];     //array for inital storage of timer info

//**    Delimiter section for parsing data
char sdelim[] = " ";    //seperation delimiter
char cdelim[] = "c";    //current time command
char gdelim[] = "g";    //Gallon Measurement Sent from the App

bool pumpIt = false;

std::string phOut;
std::string timeOut;

std::stringstream phStream;
std::stringstream timeStream;

//**    prereference functions
void timekeep(void);
void hcRxCallback(void);
float ph_measurement(void);
void pumpOn(void);
void pumpOff(void);
void printTime(void);

//**    main function
int main()
{
    //*Baud rate init
    HC06.baud(9600);
    pc.baud(9600);
    
    //*interupt init
    timeKeep.attach(&timekeep, 0.999);
    HC06.attach(&hcRxCallback, Serial::RxIrq);

    //*infinite loop
    while(1) {
        if(pumpIt){                 //if pump has not been run this hour
            if(phMeas > 7.5){       //run either pump for a second if needed
                phPump1.write(1);
                wait(1);
                phPump1 = 0;
            }
            else if(phMeas < 6.5){
                phPump2 = 1;
                wait(1);
                phPump2 = 0;
            }
            else{}
            pumpIt = false;         //stop pumps from running for another hour
        }
    }
}

//**    Timekeeping function. This function is triggered every 0.999 seconds as an interrupt
void timekeep()
{

    ctseconds += 1;             //Increment the seconds and compare to 60
    if (ctseconds >= 60) {
        ctminutes += 1;
        ctseconds  = 0;
        
        if(min_cnt == 1)        //if the minute counter was just reset, turn on the pump
            pumpOn();
        else if(min_cnt == 16){ //after 15 minutes, turn the pump off
            pumpOff();
            min_cnt = 0;        //stop minute counter
        }
        else{};                 //empty else loop
        
        if(min_cnt % 2){                //on odd minutes, run this code
            phMeas = ph_measurement();  //read and set measurements
            printTime();                //set time
            lcd.printf("%s\n%s", phOut, timeOut);   //send ph and time to LCD
        }
        
        
        if(min_cnt){                    //if minute count is not 0, increment
            min_cnt++;    
        }
    }
    if (ctminutes >= 60) {      //compare minutes to 60
        cthours  += 1;
        ctminutes = 0;
        min_cnt = 1;            //reset the minute counter
        pumpIt = true;          //reset the boolean allowing the pumps to run
    }
    if (cthours >= 24) {        //compare hours to 24
        cthours = 0;
    }
    
    pc.printf("time: %d : %d : %d\n\n",cthours,ctminutes,ctseconds);
    return;
}

/*   This the RX_IRQ. There are global variables altered within this function,
**   therefore disabling IRQ will allow this to operate without any interruption
**   ***Note*** this function will not exit and print unless the buffer has read
**              into it 8 bits of data.
**/
void hcRxCallback()
{
    __disable_irq();
    HC06.gets(buffer, 8);
    pc.printf("recieved: %s\n",buffer);

    //*String Concatenation
    int i = 0;
    char *p = strtok(buffer, sdelim);       //Delimiter to parse the string into tokens
    while(p != NULL) {                      //loops while there is data to be read
        initarray[i++] = p;                 //Saves the value of P into the next slot of initarray
        p = strtok(NULL, sdelim);           //rinse and repeat
    }
    /**   For debug purposes, this will print the array elements for the
     **   user to review.
     **/
    for(i = 0; i<3; i++) {
        pc.printf("%s\n",initarray[i]);
    }
    //*String sorting
    if (!strcmp(initarray[0], cdelim)) {    //Compare the command character to the 'c' command
        cthours = atoi(initarray[1]);
        ctminutes = atoi(initarray[2]);
        pc.printf("new time: %d %d\n\n",cthours,ctminutes);
    }
    if (!strcmp(initarray[0], gdelim)) {    //Compare the command character to the 'g' command
        gallon_cnt = atoi(initarray[1]);
        pc.printf("Current Gallon Amount: %d\n\n",gallon_cnt);
    }
    
    __enable_irq();
    return;
}

//** Time Condition Begin, EveryHOur on the Hour, cycle a water pump for 15 min 
//** and add ph up and/or ph downt to the mixture for desired ph level
float ph_measurement()
{
    float phMeasurement;
    //Check ph
    phMeasurement = sensor.get_pH();
    phStream << "pH : " << std::fixed << std::setprecision(2) << phMeasurement;
    phOut = phStream.str();
    return phMeasurement;
}

void printTime()
{
    std::stringstream sHours;
    std::stringstream sMinutes;
    
    if(cthours == 24)
        sHours << "00";
    else if(cthours < 10)
        sHours << "0" << cthours;
    else
        sHours << cthours;
        
    if(ctminutes == 60)
        sMinutes << "00";
    else if(ctminutes < 10)
        sMinutes << "0" << ctminutes;
    else
        sMinutes << ctminutes;
        
    timeStream << "Time : " << sHours.str() << ":" << sMinutes.str();
    timeOut = timeStream.str();
}

void pumpOn()
{
    smoto.pulsewidth_ms(2.0f);
}

void pumpOff()
{
    smoto.pulsewidth_ms(0.0f);
}