ECE 4180 final project. Sound and Bluetooth activated coffee maker

Dependencies:   mbed wave_player mbed-rtos C12832_lcd 4DGL-uLCD-SE LCD_fonts SDFileSystem

main.cpp

Committer:
nhummel3
Date:
2019-12-06
Revision:
8:a9b5acc63388
Parent:
7:2e274cc18797

File content as of revision 8:a9b5acc63388:

// example to test the mbed Lab Board lcd lib with the mbed rtos
// Pot1 changes the contrast
// Pot2 changes the speed of the sin wave

#include "mbed.h"
#include "rtos.h"
#include "Small_6.h"
#include "Small_7.h"
#include "Arial_9.h"
#include "stdio.h"
#include "C12832_lcd.h"
#include "sound.h"
#include "unsigned_fire_truck.h"
#include "uLCD_4DGL.h"
#include <mpr121.h>

#define sample_freq 11025.0
//get and set the frequency from wav conversion tool GUI

//set variables used to track throughout program
int reset = 1; //check if coffee pot is reset and ready to brew again
volatile int blink = 0; // check if blinking LED
int tmp_blue = 0;  // check if bluetooth has been triggered at least 2 times
int noise = 0; // check if still playing alarm
int i=0; //index for audio array
int d = 0; 
volatile int trigger = 0; // check if coffeepot has been triggered via sound or bluetooth
volatile int menu = 1; // check if coffeepot has been triggered via sound or bluetooth
int coffee = 0;
int tolerance = 600;
int brew_count = 0;

//Declarations
Ticker sampletick; //audio interrupt
uLCD_4DGL uLCD(p9,p10,p11);
AnalogIn Therm0(p18);
AnalogIn Therm1(p19);
DigitalOut key(p20);

Serial pc(USBTX,USBRX);
PwmOut Speaker(p26);
PwmOut RGBLED_r(p23);
PwmOut RGBLED_g(p22);
PwmOut RGBLED_b(p21);
DigitalIn user_button(p12);
Serial blue(p28,p27);

PwmOut pump(p24);
DigitalOut heater(p14); //inverted logic
AnalogIn therm_out(p18);
AnalogIn therm_heater(p19);

// Mutex declarations
Mutex lcd_mutex;
Mutex leds_mutex;
Mutex bmut;
Mutex mic_mutex;
Mutex trigger_mutex;

int out_temp;
int heater_temp;
int out_therm;
int heater_therm;
int target_temp = 190;

volatile float r = 0.0;
volatile float g = 0.0;
volatile float b = 0.0;

float a_coeff = 93.6469;
float b_coeff = 4681.5;

int therm_to_temp(int therm) {
    return int(a_coeff*log(therm/b_coeff));
}

int temp_to_therm(int temp) {
    return int(b_coeff*exp((temp)/a_coeff));
}

//Audio ISR 
void audio_sample ()
{
    //if noise flag set, play audio
    if(noise){
        Speaker = fire_truck_data[i%NUM_ELEMENTS_FIRE]/255.0;//scale to 0.0 to 1.0 for PWM
        i++;
    } else {
        Speaker = 0;
    }
}

// Temporary debug variables
int tmp = 0;
int tmp_button = 0;
int tmp2 = 0;
int tmp0 = 0;
int tmp1 = 0;
int tmpM = 0;

int num_trig = 0;

//Microphone class
class microphone
{
public :
    microphone(PinName pin);
    float read();
    operator float ();
private :
    AnalogIn _pin;
};
microphone::microphone (PinName pin):
    _pin(pin)
{
}
float microphone::read()
{
    return _pin.read();
}
inline microphone::operator float ()
{
    return _pin.read();
}
 
microphone mymicrophone(p16);
 

//
// Thread 1
// Debug thread for microphone on LCD 
void thread1(void const *args)
{
    lcd_mutex.lock();
    uLCD.filled_rectangle(0, 32, 128, 64, 0x00FF00);
    uLCD.locate(0,4);
    uLCD.color(WHITE);
    uLCD.textbackground_color(BLUE);
    uLCD.set_font(FONT_7X8);
    uLCD.text_mode(OPAQUE);
    uLCD.printf("Sensor Readings:\n\rMic:\n\rT0: \n\rT1: ");
    lcd_mutex.unlock();
    while(true) {       // thread loop
        //uLCD.cls();
        mic_mutex.lock();
        tmpM = int(abs((mymicrophone - (0.67/3.3)))*500.0);
        tmp0 = therm_to_temp(Therm0.read_u16());
        tmp1 = therm_to_temp(Therm1.read_u16());
        //tmp2 = user_button;
        mic_mutex.unlock();
        lcd_mutex.lock();
        
        uLCD.filled_rectangle(32, 40, 72, 63, 0x00FF00);
        uLCD.locate(4,5);
        uLCD.printf("%d",tmpM);
        uLCD.locate(4,6);
        uLCD.printf("%d", tmp0);
        uLCD.locate(4,7);
        uLCD.printf("%d", tmp1);
        
        lcd_mutex.unlock();
        Thread::wait(100);
    }
}

//
// Thread 2
// Debug thread for microphone on LCD 
void thread2(void const *args)
{
    lcd_mutex.lock();
    uLCD.filled_rectangle(0, 0, 128, 31, 0x00FF00);
    uLCD.locate(0,0);
    uLCD.color(WHITE);
    uLCD.textbackground_color(BLUE);
    uLCD.set_font(FONT_7X8);
    uLCD.text_mode(OPAQUE);
    uLCD.printf("Select Mode:");
    uLCD.locate(0,1);
    uLCD.printf(">COFFEE\n\r TEA");
    lcd_mutex.unlock();
    while(true) {       // thread loop
        if(menu) {
            if(user_button == 0) {
                coffee = !coffee;
                if(coffee) {
                    lcd_mutex.lock();
                    uLCD.filled_rectangle(0, 8, 7, 31, 0x00FF00);
                    uLCD.locate(0,1);
                    uLCD.color(WHITE);
                    uLCD.textbackground_color(BLUE);
                    uLCD.set_font(FONT_7X8);
                    uLCD.text_mode(OPAQUE);
                    uLCD.printf(">\n\r ");
                    lcd_mutex.unlock();
                    Thread::wait(500);
                } else {
                    lcd_mutex.lock();
                    uLCD.filled_rectangle(0, 8, 7, 31, 0x00FF00);
                    uLCD.locate(0,1);
                    uLCD.color(WHITE);
                    uLCD.textbackground_color(BLUE);
                    uLCD.set_font(FONT_7X8);
                    uLCD.text_mode(OPAQUE);
                    uLCD.printf(" \n\r>");
                    lcd_mutex.unlock();
                    Thread::wait(500);
                }
            }
        }
    }
}


// Thread 3
// Blink LED 
void thread3(void const *args)
{
    while(1) {
        // if blink flag is set then blink red LED with PWM fade
        if(blink) {
            leds_mutex.lock();
            RGBLED_g = 0;
            RGBLED_b = 0;
            leds_mutex.unlock();
            for(float j = 0.2; j<= 1.0; j+=0.1) {
                leds_mutex.lock();
                RGBLED_r = j;  
                leds_mutex.unlock();
                Thread::wait(20);
            }   
            Thread::wait(100);
            for(float j = 1.0; j>= 0.2; j-=0.1) {
                leds_mutex.lock();
                RGBLED_r = j;  
                leds_mutex.unlock();
                Thread::wait(10);
            }   
            Thread::wait(100);   // value of pot1 / 100
        }
    }
}
//
//// Thread 4
//// Microphone parser, triggers coffee pot when over certain value
void thread4(void const *args)
{
    while(1) {
//read in, subtract 0.67 DC bias, take absolute value, and scale up .1Vpp to 15 for builtin LED display
        mic_mutex.lock();
        tmp = int(abs((mymicrophone - (0.67/3.3)))*500.0);
        mic_mutex.unlock();
        if(tmp > 15) {
            num_trig = num_trig+1;
            //only trigger if get sample above value 3 times in a row
            if(num_trig == 2) {
                trigger_mutex.lock();
                trigger = 1;
                trigger_mutex.unlock();
                tmp = 0;
                Thread::wait(200);
            }
        } else {
            num_trig = 0;
        }
    }
}
// Thread 5
// Bluetooth parser to trigger coffee pot
void thread5(void const *args)
{   
    while(true) {         
        //if recieve any button from bluetooth, increment tmp_blue
        if (blue.readable()){
            bmut.lock();
            if (blue.getc() == '!') {
                if (blue.getc() == 'B') {
                    tmp_blue++;         
                }
            }
            
            bmut.unlock();
        }
        // if receive message from bluetooth twice in a row, trigger coffee pot
        if(tmp_blue == 2) {
            trigger_mutex.lock();
            trigger = 1;         
            trigger_mutex.unlock();
            tmp_blue = 0;
        } 
    }
}

void brew() {
    if(coffee) {
        target_temp = 190;
    } else {
        target_temp = 180;
    }
    brew_count = 0;
    while(1) {
        out_therm = therm_out.read_u16();
        heater_therm = therm_heater.read_u16();
        //pc.printf("Iteration:%d; Output Temp:%d, Heater Temp:%d\n\r", i, therm_to_temp(out_therm), therm_to_temp(heater_therm));
        if(brew_count > 20 && out_therm > 40600) {
            //Done
            heater = 1;
            pump = 1;
            wait(3);
            pump = 0;
            return;   
        } else {
            if(out_therm - temp_to_therm(target_temp) > tolerance) {
                //cool down
                pump = 0.8;
                heater = 1; //off bc inverted
            } else if(out_therm - temp_to_therm(target_temp) < tolerance) {
                //heat up
                pump = 0.25;
                heater = 0; //on
            } else {
                pump = 0.4;
                heater = 0; //on
            }
            wait(0.5);
        }
    brew_count++;
    }
}

int main()
{
    // ---------Enter Initialize State---------
    //set key to high initially to not trigger coffee pot
    key = 1;
    pump = 0;
    heater = 0;
    RGBLED_r  = 0.5;
    wait(0.1);
    //set baud rate
    blue.baud(9600);
    //set speaker period
    Speaker.period(1.0/250000.0);
    Thread t1(thread1); //start thread1
    Thread t2(thread2); //start thread3
    Thread t3(thread3); //start thread3
    Thread t4(thread4); //start thread4
    Thread t5(thread5); //start thread5
    
    //set button mode 
    user_button.mode(PullUp);
    wait(0.001);
    
    //---------Enter Ready State---------
    lcd_mutex.lock();
    uLCD.cls();
    uLCD.filled_rectangle(0, 79, 128, 112, 0x00FF00);
    uLCD.locate(0,10);
    uLCD.color(WHITE);
    uLCD.textbackground_color(BLUE);
    uLCD.set_font(FONT_7X8);
    uLCD.text_mode(OPAQUE);
    uLCD.printf("State:");
    uLCD.locate(0,11);
    uLCD.printf("READY");
    lcd_mutex.unlock();
    
    //attach audio interrupt
    sampletick.attach(&audio_sample, 1.0 / sample_freq);
        
    while(1){
        Thread::wait(50);
        //set mutex lock for trigger 
        //pc.printf("%d\n\n\r",Therm0.read_u16());
        //if trigger flag is set, start coffee pot
        if(trigger) {
            // ---------Enter Brewing State---------
            menu = 0;
            trigger_mutex.lock();
            //write to LCD 
            lcd_mutex.lock();
            uLCD.filled_rectangle(0, 88, 100, 111, 0x00FF00);
            uLCD.locate(0,11);
            uLCD.printf("BREWING...");
            lcd_mutex.unlock();
            
            //set microphone mutex lock to prevent false trigger while running 
            mic_mutex.lock();
            
            // set coffee pot trigger to low
            //key = 0;
            //changing LED to indicate trigger
            leds_mutex.lock();
            RGBLED_r = 0;
            RGBLED_b = 0;                
            RGBLED_g  = 1;
            leds_mutex.unlock();
            Thread::wait(200);
            
            // set coffee pot trigger back to high after pulse
            //key = 1;
            
            // change LED to indicate running
            leds_mutex.lock();
            RGBLED_g = 0;
            RGBLED_b  = 1;
            leds_mutex.unlock();
            
            // Brew Drink
            //wait(3);
            brew();
            
            // ---------Enter Reset State---------
            
            // set noise flag high
            noise = 1;
            lcd_mutex.lock();
            uLCD.filled_rectangle(0, 88, 100, 111, 0x00FF00);
            uLCD.locate(0,11);
            uLCD.printf("COFFEE READY\n\rPLEASE PRESS\n\rRESET");
            lcd_mutex.unlock();
            
            // set led blink flag high
            blink = 1;
            
            //wait for reset button press from user
            while(reset) {
                reset = user_button;
                Thread::wait(1);
            }
            //---------Enter User Restock---------
            blink = 0;
            // set noise flag low
            noise = 0; 
            lcd_mutex.lock();
            uLCD.filled_rectangle(0, 88, 100, 111, 0x00FF00);
            uLCD.locate(0,11);
            uLCD.printf("Please Restock\n\rThe Machine");
            lcd_mutex.unlock();
            
            wait(0.5);
            reset = user_button;
            while(reset) {
                reset = user_button;
                Thread::wait(1);
            }
            
            //---------Enter Ready State---------
            
            // set led blink flag low
            blink = 0;
            lcd_mutex.lock();
            uLCD.filled_rectangle(0, 88, 100, 111, 0x00FF00);
            uLCD.locate(0,11);
            uLCD.printf("READY");
            lcd_mutex.unlock();
            
            // set noise flag low
            noise = 0;
            // set reset flag high
            reset = 1;
            
            // change leds to indicate ready state
            leds_mutex.lock();
            RGBLED_g = 0;
            RGBLED_b = 0;
            RGBLED_r  = 1;
            leds_mutex.unlock();
            
            // set trigger flag low
            trigger = 0;
            wait(0.4);
            mic_mutex.unlock();
            trigger_mutex.unlock();
            menu = 1;
        }
    }
}