This program is an advanced "IoT" thermometer using LM75B component library. It displays the current value to the Serial host in Celcius or Fahrenheit (possible to change using a switch). It also stores an historic and displays it to the user using the LCD screen. Moreover, you can change the orientation of the screen by turning the device, just like a smartphone.

Dependencies:   C12832 FXOS8700CQ LM75B mbed

main.cpp

Committer:
co838_gtvl2
Date:
2016-02-23
Revision:
8:6f30f477fa23
Parent:
7:e5732637dfd0

File content as of revision 8:6f30f477fa23:

/**
 *  This program is an advanced "IoT" thermometer using LM75B component library.
 *  It displays the current value to the Serial host in Celcius (BLUE) or Fahrenheit (GREEN).
 *  It is possible to change units using SW2 switch or computer's 'c' and 'f' keys.
 *  You can use SW3 to pause/resume to data collection or computer's 'p' key.
 *  It also stores a small historic and displays it to the user using the LCD screen.
 *  Moreover, you can change the orientation of the screen by turning the device, just like a smartphone.
 *
 *  Note that the use of printf in the Ticker or Timeout functions is properly done.
 *  If _DEBUG is defined, it is possible to have a buffer conflict, but not if _DEBUG is undefined. 
 *
 *
 *  Created by Guillaume Lefrant gtvl2
 **/

#include "main.h"
#include "ThermalDisplayer.h"
#include "MyTimeout.hpp"

Serial              pc(USBTX, USBRX);           // Serial Host
LM75B               lm_temp(D14, D15);          // Temperature Sensor
InterruptIn         sw2_int(SW2);               // SW2
InterruptIn         sw3_int(SW3);               // SW3
DigitalOut          tilt_led(LED1);             // Red LED
DigitalOut          r_led(PTA2);                // RGB LED
DigitalOut          g_led(PTC4);
DigitalOut          b_led(PTC12);
AnalogIn            pot(A0);                    // Potentiometer POT1
MyTimeout           process_timeout;            // Main timeout used for the whole process

volatile bool       celcius;                    // Global boolean for unit Celcius / Fahrenheit
volatile bool       running;                    // Either the program is running or paused
volatile int        refresh_time = 3000;

ThermalDisplayer    temp_display = ThermalDisplayer();

/*
 *  SW2 handler
 *  Changes the unit and adapts LED to the new one.
 */
void                sw2_interrupt(void)
{
    celcius = !celcius;

    if (running) {
        if (celcius) {
            r_led = 1.0;
            g_led = 1.0;
            b_led = 0.0;
        } else {
            r_led = 1.0;
            g_led = 0.0;
            b_led = 1.0;
        }
    }
}

/*
 *  SW3 handler
 *  Used to pause / resume the data collection and display.
 */
void                sw3_interrupt(void)
{
    running = !running;
    if (!running) {
        process_timeout.detach();
        r_led = 0.0;
        g_led = 1.0;
        b_led = 1.0;
    } else {
        celcius = !celcius;
        sw2_interrupt();
    }
}

/*
 *  Interrupt that does the same as SW2 handler above but using keyboard of host
 */
void                host_interrupt(void)
{
    if (pc.readable()) {
        switch(pc.getc()) {
            case 'c':
                celcius = false;
                sw2_interrupt();
                break;
            case 'f':
                celcius = true;
                sw2_interrupt();
                break;
            case 'p':
                sw3_interrupt();
                break;
            default:
                break;
        }
    }
}

void                process_function(void)
{
    tilt_led = 0.0;
    // IMPORTANT. Check MyTimeout.hpp for details.
    process_timeout.detach();
    
    /*
     * Get temperature using LM75B
     * and display it to LCD screen
     */
    float temperature = lm_temp.read();
    temp_display.addTemp(temperature);
    temp_display.adjustScale();
    temp_display.display();


    /*
     * Display value to host according to unit choosed with SW2.
     * Could have been a ternary, but it's easier to read like this.
     * In production (without _DEBUG), this is the only printf executed.
     */
    if (pc.writeable()) {
        if (celcius) {
            pc.printf("Temp: %.2f deg Celcius.\r\n", temperature);
        } else {
            pc.printf("Temp: %.2f deg Fahrenheit.\r\n", (temperature * 1.8f + 32.0f));
        }
    }

    /*
     * Change refresh_time according to POT1's value
     */
    refresh_time = (int) (MIN_REFRESH_TIME + ((1.0f - pot) * (MAX_REFRESH_TIME - MIN_REFRESH_TIME)));
    tilt_led = 1.0;
}

int                 main(void)
{
    pc.baud(38400);
    if (pc.writeable()) {
        pc.printf("Hello gtvl2, from FRDM-K64F!\r\nUse POT1 to change the refresh rate, POT2 to change the scale of the graphic, SW2 or keyboard to change the unit and SW3 to pause.\r\n");
    }

    // Initialize control interrupts
    sw2_int.mode(PullUp);
    sw2_int.fall(&sw2_interrupt);
    sw3_int.mode(PullUp);
    sw3_int.fall(&sw3_interrupt);
    pc.attach(&host_interrupt);

    // Initialize variables and LEDs
    running = false;
    celcius = true;
    sw3_interrupt();

    // Do once
    process_function();
    wait_ms(1);
    // Then forever
    while (true) {
        if (running && !process_timeout.hasAttachment()) {
#if defined _DEBUG
            pc.printf("Next cycle in %.3f seconds\r\n", refresh_time / 1000.0f);
#endif
            process_timeout.attach_us(&process_function, (float) refresh_time * 1000.0f);
        }
#if defined _DEBUG
        else {
            pc.printf("Won't attach again the timer.\r\n");
        }
#endif
        sleep();
    }
}