Working Menu with selectable fields yet to add comparison with healthy temperature ranges

Dependencies:   TMP102_02

17665328_SmartVeterinaryThermometer.cpp

Committer:
ejh23
Date:
2022-02-04
Revision:
9:483d03b3e1bc
Child:
10:62da82b9b6de

File content as of revision 9:483d03b3e1bc:

/*******************************************************************************
Edward Hindley
Assistive Health device - measure temperature in an energy efficient and easy to use way 
Board is initialised and awaits edge triggered interrupts to enable 
    a menu, measurement type selection and an average temperature reading.


* Craig A. Evans, University of Leeds, TMP102 Library, Feb 2016
* Dr Edmond Nurellari, University of Lincoln, Joystick, N5110 Libraries, Feb 2022

*******************************************************************************/

#include "mbed.h"                                                               //Include all header files to be used throughout 
#include "Timer.h"
#include "TMP102.h"
#include "Bitmap.h"
#include "N5110.h"
#include "Joystick.h"

/*******************************************************************************
Set-up of all vital peripherals
Note that the following values correspond to these notes
 NOTE_C4  262, NOTE_CS4 277, NOTE_D4  294, NOTE_DS4 311
 NOTE_E4  330, NOTE_F4  349, NOTE_FS4 370, NOTE_G4  392
 NOTE_GS4 415, NOTE_A4  440, NOTE_AS4 466, NOTE_B4  494
 NOTE_C5  523, NOTE_CS5 554, NOTE_D5  587, NOTE_DS5 622
 NOTE_E5  659, NOTE_F5  698, NOTE_FS5 740, NOTE_G5  784
 NOTE_GS5 831, NOTE_A5  880, NOTE_AS5 932, NOTE_B5  988
 NOTE_C6  1047
 *Author Jorge Rancé, PUBLISHED December 4, 2017
*******************************************************************************/
TMP102 tmp102(I2C_SDA,I2C_SCL); 
N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11);
Joystick joystick(PTB10,PTB11,PTC16); 
InterruptIn StartButton(PTC5);
InterruptIn BackButton(PTB19);
InterruptIn MenuOnButton(PTB3);                                                 //Open Menu
InterruptIn MenuOffButton(PTB18);                                               //Close Menu
InterruptIn YButton(PTC12);                                                     //Set contrast 
DigitalIn AButton(PTB9);                                                        //Submit Joystick Position 
DigitalIn BButton(PTD0);                                                        //As Yet Unused
BusOut LedStatus(PTA1, PTA2, PTC2, PTC3, PTC4, PTD3);                           
PwmOut Buzz(PTC10); 
AnalogIn Pot(PTB2);                                                            
Serial pc(USBTX,USBRX);
/*******************************************************************************
Initiate Variables and Voids 
*******************************************************************************/
volatile int G_RepeatNum;                                                       //Global variables denoted G_ 
volatile float G_TempR;                                                         // TempR = Temp read from sensor
volatile float G_TempAve;
volatile int G_MLayerFlag;                                                       // MenuLayer flags  = Maintains while loops whilst navigating menus 
volatile bool G_APressed;
volatile bool G_BPressed;
volatile int G_PageNum;
volatile int G_PagePos;
volatile int G_SpeciesSelect;

Timer MLayer1Time;
Timer MLayer2Time; 
Timer ReviewTime;                                                                //Create Flag reset timer to initiate sleep in inactivity 

void SetContrast();
void initDevice();
void FillAnimal();
void OpenLayer1();
void OpenLayer2();
void PageOne();
void PageTwo();
void PageThree();
void PG2_0();
void PG2_1();
void PG2_2();
void PG2_3();
void PG2_4();
void PG3_0();
void PG3_1();
void PG3_2();
void PG3_3();
void PG3_4();
void TakeRdng();
void Display();
void HealthCheck();
void CloseMenu();
void RemPrompt();

typedef struct Animal{                                                                                                                             
    float UTemp;                                                                 
    float LTemp;
};

//******************************************************************************
void SetContrast()
{                                                                               //Move Potentiometer to required position and Press Y to Set  
    float PotValue = Pot.read();
    printf("Brightness %f\n",PotValue);
    lcd.setBrightness(PotValue);
}

void initDevice()
{
        pc.baud(9600);                                                          //Set compatible to Terminal software 
        lcd.init();                                                             //Use library initialisation function for onboard devices
        tmp102.init();
        joystick.init();                                                          
        StartButton.mode(PullDown);                                             //Set so rise is press and fall is release 
        BackButton.mode(PullDown);
        MenuOnButton.mode(PullDown);
        MenuOffButton.mode(PullDown);
        AButton.mode(PullDown);
        BButton.mode(PullDown);
        YButton.mode(PullDown);
        printf("Hardware Initialisation Complete \n");
}

void FillAnimal()
{
    Animal Dog[2];
    {
        Dog.UTemp = 39.2;
        Dog.LTemp = 37.5;
    }
    Animal Horse[2];
    {
        Horse.UTemp = 38.6;
        Horse.LTemp = 37.5;
    }
    Animal Rabbit[2];
    {
        Rabbit.UTemp = 40.0;
        Rabbit.LTemp = 38.5;
    }
    Animal Snake[2];
    {
        Snake.UTemp = 31.1;
        Snake.LTemp = 23.8;
    }
}

//****************************************************************************** Separator to aid readability
void OpenLayer1()
{
    G_MLayerFlag = 1;
    MLayer1Time.start();                                                          //MLayer1Time timer started in case this is first time
    MLayer1Time.reset();                                                          //    running and reset incase this is not first time running
    PageOne();
    wait(2.0);
    if (G_PageNum==1)
    {
        while(G_MLayerFlag==1)
        {
            //printf("G_MLayerFlag is True \n");
            Direction d = joystick.get_direction();                                 //Upon each cycle of while, check joystick direction and buttons statuses
            //printf("Direction %i \n", d);
            G_APressed = AButton.read();
            G_BPressed = BButton.read();
            printf("A Button Status : %d \n", G_APressed);
            wait(0.1);
            float TimeGone = MLayer1Time.read();
            
            if(TimeGone >= 10)                                                      //Set value for timer comparitor called TimeGone (Seconds)
            {
                CloseMenu();
            }
            else if(d==1)                                           //1 corresponds to North in the Enumerator (from joystick header)
            {
                printf("North Time is %.1f \n", TimeGone);
                G_PagePos = 1;
                G_SpeciesSelect = 1;
                PageTwo();
                MLayer1Time.reset();
                wait(0.05);
            }
            else if(d==3)                                           //3 corresponds to East in the Enumerator (from joystick header)
            {
                printf("East Time is %.1f \n", TimeGone);
                G_PagePos = 2;
                G_SpeciesSelect = 2;
                PageTwo();
                MLayer1Time.reset();
                wait(0.2);
            }
            else if(d==5)                                           //5 correspsonds to South in the Enumerator (from joystick header)
            {
                printf("South Time is %.1f \n", TimeGone);
                G_PagePos = 3;
                G_SpeciesSelect = 3;
                PageTwo();
                MLayer1Time.reset();
                wait(0.05);            
            }
            else if(d==7)                                           //7 corresponds to West in the Enumerator (from joystick header)
            {
                printf("West Time is %.1f \n", TimeGone);
                G_PagePos = 4;
                G_SpeciesSelect = 4;
                PageTwo();
                MLayer1Time.reset();
                wait(0.05);
            }
            else if(TimeGone >=2)
            {
                PG2_0();
            }
            if(G_BPressed==1)
            {
                if(G_PageNum==1)
                {
                    printf("Go to CloseMenu");
                    CloseMenu();
                }
                else if(G_PageNum==2)
                {
                    printf("Go to PageOne");
                    PageOne();   
                }
            }
        }
    }
    else if(G_PageNum==2)
    {
        OpenLayer2();                                                           //if MLayer2Flag == 1 should return to OpenLayer2 
    }
    else if(G_PageNum==0)
    {
        printf("Menue Closed");
    }
}
//******************************************************************************
void PageOne()
{
    float PotValue = Pot.read();
    lcd.setBrightness(PotValue);
    printf("Start Page");
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("  Veterinary  ",0,1);                                         
    lcd.printString("Thermometer",0,2);                                          
    lcd.printString("            ",0,3);                                         
    lcd.printString("EJH - Feb '22",0,4);                                      
    lcd.drawLine(1,47,84,47,1);
    wait(1.0);                                    
    lcd.refresh();
    G_PageNum = 1;
    return; 
}

void PageTwo()
{
    G_PageNum = 2;
    if(G_PagePos==1)
    {
        PG2_1();
    }          
    else if(G_PagePos==2)
    {
        PG2_2();
    } 
    else if(G_PagePos==3)
    {
        PG2_3();
    } 
    else if(G_PagePos==4)
    {
        PG2_4();
    } 
    return;
}
void PG2_0()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("   Dog",0,1);                                         
    lcd.printString("   Horse",0,2);                                          
    lcd.printString("   Rabbit",0,3);                                         
    lcd.printString("   Snake",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    return;
}
void PG2_1()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("-> Dog",0,1);                                         
    lcd.printString("   Horse",0,2);                                          
    lcd.printString("   Rabbit",0,3);                                         
    lcd.printString("   Snake",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    if (G_APressed==1)
    {
        G_PageNum=2;
        G_MLayerFlag=2;
        OpenLayer2();
    }
    else
    {
        return;
    }
}
void PG2_2()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("   Dog",0,1);                                         
    lcd.printString("-> Horse",0,2);                                          
    lcd.printString("   Rabbit",0,3);                                         
    lcd.printString("   Snake",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    if (G_APressed==1)
    {
        G_PageNum=2;
        G_MLayerFlag=2;
        OpenLayer2();
    }
    else
    {
        return;
    } 
}
void PG2_3()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("   Dog",0,1);                                         
    lcd.printString("   Horse",0,2);                                          
    lcd.printString("-> Rabbit",0,3);                                         
    lcd.printString("   Snake",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    if (G_APressed==1)
    {
        G_PageNum=2;
        G_MLayerFlag=2;
        OpenLayer2();
    }
    else
    {
        return;
    }   
}
void PG2_4()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("   Dog",0,1);                                         
    lcd.printString("   Horse",0,2);                                          
    lcd.printString("   Rabbit",0,3);                                         
    lcd.printString("-> Snake",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    if (G_APressed==1)
    {
        G_PageNum=2;
        G_MLayerFlag=2;
        OpenLayer2();
    }
    else
    {
        return;
    }    
}
//******************************************************************************
void OpenLayer2()
{
    wait(1.0);
    MLayer2Time.start();                                                        //MLayer2Time timer started in case this is first time
    MLayer2Time.reset();                                                        //    running and reset incase this is not first time running    
                                                            
    if(G_PageNum==2)
    {
        while(G_MLayerFlag==2)
        {
            //printf("G_MLayerFlag is True \n");
            Direction d = joystick.get_direction();                                 //Upon each cycle of while, check joystick direction and buttons statuses
            printf("Direction %i \n", d);
            bool G_APressed = AButton.read();
            bool G_BPressed = BButton.read();
            //printf("A Button Status : %d \n", G_APressed);
            wait(0.05);
            float TimeGone2 = MLayer2Time.read();
            
            if(TimeGone2 >= 10)                                                      //Set value for timer comparitor called TimeGone (Seconds)
            {
                OpenLayer1();
            }
            else if(d==1)                                                           //1 corresponds to North in the Enumerator (from joystick header)
            {
                printf("North Time is %.1f \n", TimeGone2);
                G_PagePos = 5;
                PageThree();
                MLayer2Time.reset();
                wait(0.05);
            }
            else if(d==3)                                                           //3 corresponds to East in the Enumerator (from joystick header)
            {
                printf("East Time is %.1f \n", TimeGone2);
                G_PagePos = 6;
                PageThree();
                MLayer2Time.reset();
                wait(0.05);
            }
            else if(d==5)                                                           //5 correspsonds to South in the Enumerator (from joystick header)
            {
                printf("South Time is %.1f \n", TimeGone2);
                G_PagePos = 7;
                PageThree();
                MLayer2Time.reset();
                wait(0.05);            
            }
            else if(d==7)                                                           //7 corresponds to West in the Enumerator (from joystick header)
            {
                printf("West Time is %.1f \n", TimeGone2);
                G_PagePos = 8;
                PageThree();
                MLayer2Time.reset();
                wait(0.05);
            }
            else if(TimeGone2 >=2)
            {
                PG3_0();
            }
            else if(G_BPressed==1)
            {
                G_PageNum=1;
                OpenLayer1();
            }
        }
        if (G_MLayerFlag==3)
        {
            TakeRdng();
        }
    }
    else if(G_PageNum==1)
    {
        OpenLayer1();                                                           //if MLayer2Flag == 1 should return to OpenLayer2 
    }
}
//******************************************************************************

void PageThree()
{
    //G_PageNum = 3;
    if(G_PagePos==5)
    {
        PG3_1();
    }     
    else if(G_PagePos==6)
    {
        PG3_2();
    } 
    else if(G_PagePos==7)
    {
        PG3_3();
    } 
    else if(G_PagePos==8)
    {
        PG3_4();
    } 
    return;
}
void PG3_0()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("  1   Reading",0,1);                                         
    lcd.printString("  5   Readings",0,2);                                          
    lcd.printString("  20  Readings",0,3);                                         
    lcd.printString("  100 Readings",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    return;
}
void PG3_1()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("->1   Reading",0,1);                                         
    lcd.printString("  5   Readings",0,2);                                          
    lcd.printString("  20  Readings",0,3);                                         
    lcd.printString("  100 Readings",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    bool G_APressed = AButton.read();
    if (G_APressed==1)
    {
        G_RepeatNum = 1;
        G_MLayerFlag=3;
        //TakeRdng();
    }
    else
    {
        return;
    }   
}
void PG3_2()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("  1   Reading",0,1);                                         
    lcd.printString("->5   Readings",0,2);                                          
    lcd.printString("  20  Readings",0,3);                                         
    lcd.printString("  100 Readings",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    bool G_APressed = AButton.read();
    if (G_APressed==1)
    {
        G_RepeatNum = 5;
        G_MLayerFlag=3;
        //TakeRdng();
    }
    else
    {
        return;
    }
}
void PG3_3()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("  1   Reading",0,1);                                         
    lcd.printString("  5   Readings",0,2);                                          
    lcd.printString("->20  Readings",0,3);                                         
    lcd.printString("  100 Readings",0,4);                                      
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    bool G_APressed = AButton.read();
    if (G_APressed==1)
    {
        G_RepeatNum = 20;
        G_MLayerFlag=3;
        //TakeRdng();
    }
    else
    {
        return;
    }
}
void PG3_4()
{
    lcd.clear();                                                                
    lcd.drawLine(1,1,84,1,1);                                     
    lcd.printString("  1   Reading",0,1);                                         
    lcd.printString("  5   Readings",0,2);                                          
    lcd.printString("  20  Readings",0,3);                                         
    lcd.printString("->100 Readings",0,4);                                    
    lcd.drawLine(1,47,84,47,1);                                     
    wait(0.05);                                    
    lcd.refresh();
    bool G_APressed = AButton.read();
    if (G_APressed==1)
    {
        G_RepeatNum = 100;
        G_MLayerFlag=3;
        //TakeRdng();
    }
    else
    {
        return;
    }   
}
void CloseMenu()
{
    lcd.setBrightness(0.00);
    G_PageNum = 0;
    G_MLayerFlag = 0;
    lcd.clear();
    lcd.refresh();
    printf("Menu Closed and Flag Reset \n");
}


void TakeRdng()
{
        float TempSum = 0;
        G_TempR = tmp102.get_temperature();                                     // read temperature save to variable TempR                                      
        for(int i=0; i<G_RepeatNum; i++) {                                      //change G_RepeatNum set by user in menu
        printf("Temp was %.2f \n", G_TempR);
        TempSum = TempSum + G_TempR;                                
        printf("TempSum = %.2f \n",TempSum);
        /*Buzz.period(1.0/523.0);                                                  
        Buzz = 0.5;                                                                                
        wait(0.5);                                                              //Rough time between readings 
        */Buzz = 0;
            if(G_BPressed==1)
            {
                G_RepeatNum = 0;
                OpenLayer2();
            }
        }
        G_TempAve = TempSum / G_RepeatNum;                                      //Average Temperature Calculation using the RepeatNum 
        HealthCheck();                                                              //      variable as number of elements in average 
}
enum SpeciesPage
{
    SpeciesDog=1,
    SpeciesHorse=2,
    SpeciesRabbit=3,
    SpeciesSnake=4,
    SpeciesState=5,
};
void Display()
{
    int DisplayType = SpeciesState;
    int NextDisplayType = SpeciesState;
    switch(DisplayType)
    {
        case SpeciesState: 
        {
            if(G_SpeciesSelect == 1)
            {
                NextDisplayType = SpeciesDog;
            }
            else if(G_SpeciesSelect == 2)
            {
                NextDisplayType = SpeciesHorse;
            }
            else if(G_SpeciesSelect == 3)
            {
                NextDisplayType = SpeciesRabbit;
            }
            else if(G_SpeciesSelect == 4)
            {
                NextDisplayType = SpeciesSnake;
            }
        }
        case SpeciesDog:
        {
            lcd.clear();
            lcd.drawLine(1,1,84,1,1);
            lcd.printString("Dog Health",0,1);      
            char buffer[14];
            int length = sprintf(buffer,"T=%.3f 'C", G_TempAve);
            if (length <= 14)                                                       //check string fits on screen (14 lots of 6 wide characters)
                lcd.printString(buffer,0,2); 
            lcd.drawLine(1,47,84,47,1);
            lcd.refresh();
                if (G_TempAve >= Dog.LTemp and G_TempAve <= Dog.UTemp)
                {
                    lcd.printString("Temperature OK",0,3);      
                }
        }
        case SpeciesHorse:
        {
            lcd.clear();
            lcd.drawLine(1,1,84,1,1);
            lcd.printString("Horse Health",0,1);      
            char buffer[14];
            int length = sprintf(buffer,"T=%.3f 'C", G_TempAve);
            if (length <= 14)                                                       //check string fits on screen (14 lots of 6 wide characters)
                lcd.printString(buffer,0,2); 
            lcd.drawLine(1,47,84,47,1);
            lcd.refresh();
                if (G_TempAve >= Horse.LTemp and G_TempAve <= Horse.UTemp)
                {
                    lcd.printString("Temperature OK",0,3);      
                }
        }
        case SpeciesRabbit:
        {
            lcd.clear();
            lcd.drawLine(1,1,84,1,1);
            lcd.printString("Rabbit Health",0,1);      
            char buffer[14];
            int length = sprintf(buffer,"T=%.3f 'C", G_TempAve);
            if (length <= 14)                                                       //check string fits on screen (14 lots of 6 wide characters)
                lcd.printString(buffer,0,2); 
            lcd.drawLine(1,47,84,47,1);
            lcd.refresh();
                if (G_TempAve >= Rabbit.LTemp and G_TempAve <= Rabbit.UTemp)
                {
                    lcd.printString("Temperature OK",0,3);      
                }
        }
        case SpeciesSnake:
        {
            lcd.clear();
            lcd.drawLine(1,1,84,1,1);
            lcd.printString("Snake Health",0,1);      
            char buffer[14];
            int length = sprintf(buffer,"T=%.3f 'C", G_TempAve);
            if (length <= 14)                                                       //check string fits on screen (14 lots of 6 wide characters)
                lcd.printString(buffer,0,2); 
            lcd.drawLine(1,47,84,47,1);
            lcd.refresh();
                if (G_TempAve >= Snake.LTemp and G_TempAve <= Snake.UTemp)
                {
                    lcd.printString("Temperature OK",0,3);      
                }
        }
    }
        /*printf("Average Reading = %.2f \n",G_TempAve);
        lcd.clear();
        char buffer[14];
        int length = sprintf(buffer,"T=%.3f 'C", G_TempAve);
        if (length <= 14)                                                       //check string fits on screen (14 lots of 6 wide characters)
            lcd.printString(buffer,0,1);           
        lcd.refresh();      */
}
void RemPrompt()
{
        lcd.clear();
        lcd.drawLine(1,1,84,1,1);                                                                            
        lcd.printString("Device may",0,1);                              
        lcd.printString("sleep soon!",0,2);                                      
        lcd.printString("A to keep Temp",0,3);
        lcd.printstring("B to main menu",0,4);                                    
        lcd.drawLine(1,47,84,47,1);        
        lcd.refresh();    
}                                                              //Prompts user to allow screen to sleep
void HealthCheck()
{
    ReviewTime.start();                                                         //ReviewTime timer started in case this is first time
    bool G_APressed = AButton.read();
    Display();
    while(ReviewTime<=30)
    {
        if(ReviewTime>=10)
        {
            RemPrompt();
        }
        if (G_APressed==1)
        {
            ReviewTime.reset();
        }
        else if(G_BPressed==1) 
        {
            G_MLayerFlag =1;
            G_PageNum =1;
            OpenLayer1();
        } 
    }
    CloseMenu();                                                  
}

int main()
{ 
        initDevice();
        FillAnimal();                                                           //Initiate Hardware
        YButton.rise(&SetContrast);                                             //Interrupts connected to voids 
        StartButton.rise(&TakeRdng);
        MenuOnButton.rise(&OpenLayer1);
        MenuOffButton.rise(&CloseMenu);                                         //Obselete
}