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

Committer:
co838_gtvl2
Date:
Tue Feb 23 16:57:15 2016 +0000
Revision:
7:e5732637dfd0
Parent:
6:6c61186c8739
Child:
8:6f30f477fa23
FINAL VERSION.; Added Pause/Resume support using SW3 or 'p'

Who changed what in which revision?

UserRevisionLine numberNew contents of line
co838_gtvl2 4:5bf99eb2d740 1 /**
co838_gtvl2 4:5bf99eb2d740 2 * This program is an advanced "IoT" thermometer using LM75B component library.
co838_gtvl2 7:e5732637dfd0 3 * It displays the current value to the Serial host in Celcius (BLUE) or Fahrenheit (GREEN).
co838_gtvl2 6:6c61186c8739 4 * It is possible to change units using SW2 switch or computer's 'c' and 'f' keys.
co838_gtvl2 7:e5732637dfd0 5 * You can use SW3 to pause/resume to data collection or computer's 'p' key.
co838_gtvl2 6:6c61186c8739 6 * It also stores a small historic and displays it to the user using the LCD screen.
co838_gtvl2 6:6c61186c8739 7 * Moreover, you can change the orientation of the screen by turning the device, just like a smartphone.
co838_gtvl2 6:6c61186c8739 8 *
co838_gtvl2 6:6c61186c8739 9 * Note that the use of printf in the Ticker or Timeout functions is properly done.
co838_gtvl2 6:6c61186c8739 10 * If _DEBUG is defined, it is possible to have a buffer conflict, but not if _DEBUG is undefined.
co838_gtvl2 6:6c61186c8739 11 *
co838_gtvl2 4:5bf99eb2d740 12 *
co838_gtvl2 4:5bf99eb2d740 13 * Created by Guillaume Lefrant gtvl2
co838_gtvl2 4:5bf99eb2d740 14 **/
co838_gtvl2 4:5bf99eb2d740 15
co838_gtvl2 1:06713d1b69cf 16 #include "main.h"
co838_gtvl2 1:06713d1b69cf 17 #include "ThermalDisplayer.h"
co838_gtvl2 6:6c61186c8739 18 #include "MyTimeout.hpp"
co838_gtvl2 0:362773c24009 19
co838_gtvl2 6:6c61186c8739 20 Serial pc(USBTX, USBRX); // Serial Host
co838_gtvl2 7:e5732637dfd0 21 LM75B lm_temp(D14, D15); // Temperature Sensor
co838_gtvl2 6:6c61186c8739 22 InterruptIn sw2_int(SW2); // SW2
co838_gtvl2 7:e5732637dfd0 23 InterruptIn sw3_int(SW3); // SW3
co838_gtvl2 6:6c61186c8739 24 DigitalOut tilt_led(LED1); // Red LED
co838_gtvl2 6:6c61186c8739 25 DigitalOut r_led(PTA2); // RGB LED
co838_gtvl2 6:6c61186c8739 26 DigitalOut g_led(PTC4);
co838_gtvl2 6:6c61186c8739 27 DigitalOut b_led(PTC12);
co838_gtvl2 6:6c61186c8739 28 AnalogIn pot(A0); // Potentiometer POT1
co838_gtvl2 6:6c61186c8739 29 MyTimeout process_timeout; // Main timeout used for the whole process
co838_gtvl2 0:362773c24009 30
co838_gtvl2 7:e5732637dfd0 31 volatile bool celcius; // Global boolean for unit Celcius / Fahrenheit
co838_gtvl2 7:e5732637dfd0 32 volatile bool running; // Either the program is running or paused
co838_gtvl2 6:6c61186c8739 33 volatile int refresh_time = 3000;
co838_gtvl2 6:6c61186c8739 34
co838_gtvl2 6:6c61186c8739 35 ThermalDisplayer temp_display = ThermalDisplayer();
co838_gtvl2 0:362773c24009 36
co838_gtvl2 1:06713d1b69cf 37 /*
co838_gtvl2 6:6c61186c8739 38 * SW2 handler
co838_gtvl2 7:e5732637dfd0 39 * Changes the unit and adapts LED to the new one.
co838_gtvl2 1:06713d1b69cf 40 */
co838_gtvl2 7:e5732637dfd0 41 void sw2_interrupt(void)
co838_gtvl2 2:5d0c209e5c61 42 {
co838_gtvl2 6:6c61186c8739 43 celcius = !celcius;
co838_gtvl2 6:6c61186c8739 44
co838_gtvl2 0:362773c24009 45 if (celcius) {
co838_gtvl2 0:362773c24009 46 r_led = 1.0;
co838_gtvl2 4:5bf99eb2d740 47 g_led = 1.0;
co838_gtvl2 4:5bf99eb2d740 48 b_led = 0.0;
co838_gtvl2 0:362773c24009 49 } else {
co838_gtvl2 7:e5732637dfd0 50 r_led = 1.0;
co838_gtvl2 7:e5732637dfd0 51 g_led = 0.0;
co838_gtvl2 4:5bf99eb2d740 52 b_led = 1.0;
co838_gtvl2 2:5d0c209e5c61 53 }
co838_gtvl2 0:362773c24009 54 }
co838_gtvl2 0:362773c24009 55
co838_gtvl2 1:06713d1b69cf 56 /*
co838_gtvl2 7:e5732637dfd0 57 * SW3 handler
co838_gtvl2 7:e5732637dfd0 58 * Used to pause / resume the data collection and display.
co838_gtvl2 7:e5732637dfd0 59 */
co838_gtvl2 7:e5732637dfd0 60 void sw3_interrupt(void)
co838_gtvl2 7:e5732637dfd0 61 {
co838_gtvl2 7:e5732637dfd0 62 running = !running;
co838_gtvl2 7:e5732637dfd0 63 if (!running) {
co838_gtvl2 7:e5732637dfd0 64 process_timeout.detach();
co838_gtvl2 7:e5732637dfd0 65 r_led = 0.0;
co838_gtvl2 7:e5732637dfd0 66 g_led = 1.0;
co838_gtvl2 7:e5732637dfd0 67 b_led = 1.0;
co838_gtvl2 7:e5732637dfd0 68 } else {
co838_gtvl2 7:e5732637dfd0 69 celcius = !celcius;
co838_gtvl2 7:e5732637dfd0 70 sw2_interrupt();
co838_gtvl2 7:e5732637dfd0 71 }
co838_gtvl2 7:e5732637dfd0 72 }
co838_gtvl2 7:e5732637dfd0 73
co838_gtvl2 7:e5732637dfd0 74 /*
co838_gtvl2 7:e5732637dfd0 75 * Interrupt that does the same as SW2 handler above but using keyboard of host
co838_gtvl2 1:06713d1b69cf 76 */
co838_gtvl2 6:6c61186c8739 77 void host_interrupt(void)
co838_gtvl2 5:c5d7fca4d111 78 {
co838_gtvl2 6:6c61186c8739 79 if (pc.readable()) {
co838_gtvl2 7:e5732637dfd0 80 switch(pc.getc()) {
co838_gtvl2 6:6c61186c8739 81 case 'c':
co838_gtvl2 6:6c61186c8739 82 celcius = false;
co838_gtvl2 7:e5732637dfd0 83 sw2_interrupt();
co838_gtvl2 6:6c61186c8739 84 break;
co838_gtvl2 6:6c61186c8739 85 case 'f':
co838_gtvl2 6:6c61186c8739 86 celcius = true;
co838_gtvl2 7:e5732637dfd0 87 sw2_interrupt();
co838_gtvl2 7:e5732637dfd0 88 break;
co838_gtvl2 7:e5732637dfd0 89 case 'p':
co838_gtvl2 7:e5732637dfd0 90 sw3_interrupt();
co838_gtvl2 6:6c61186c8739 91 break;
co838_gtvl2 6:6c61186c8739 92 default:
co838_gtvl2 6:6c61186c8739 93 break;
co838_gtvl2 5:c5d7fca4d111 94 }
co838_gtvl2 5:c5d7fca4d111 95 }
co838_gtvl2 5:c5d7fca4d111 96 }
co838_gtvl2 5:c5d7fca4d111 97
co838_gtvl2 6:6c61186c8739 98 void process_function(void)
co838_gtvl2 2:5d0c209e5c61 99 {
co838_gtvl2 6:6c61186c8739 100 tilt_led = 0.0;
co838_gtvl2 6:6c61186c8739 101 // IMPORTANT. Check MyTimeout.hpp for details.
co838_gtvl2 6:6c61186c8739 102 process_timeout.detach();
co838_gtvl2 6:6c61186c8739 103
co838_gtvl2 6:6c61186c8739 104 /*
co838_gtvl2 6:6c61186c8739 105 * Get temperature using LM75B
co838_gtvl2 6:6c61186c8739 106 * and display it to LCD screen
co838_gtvl2 6:6c61186c8739 107 */
co838_gtvl2 6:6c61186c8739 108 float temperature = lm_temp.read();
co838_gtvl2 6:6c61186c8739 109 temp_display.addTemp(temperature);
co838_gtvl2 6:6c61186c8739 110 temp_display.adjustScale();
co838_gtvl2 6:6c61186c8739 111 temp_display.display();
co838_gtvl2 6:6c61186c8739 112
co838_gtvl2 6:6c61186c8739 113
co838_gtvl2 6:6c61186c8739 114 /*
co838_gtvl2 6:6c61186c8739 115 * Display value to host according to unit choosed with SW2.
co838_gtvl2 6:6c61186c8739 116 * Could have been a ternary, but it's easier to read like this.
co838_gtvl2 6:6c61186c8739 117 * In production (without _DEBUG), this is the only printf executed.
co838_gtvl2 6:6c61186c8739 118 */
co838_gtvl2 6:6c61186c8739 119 if (pc.writeable()) {
co838_gtvl2 6:6c61186c8739 120 if (celcius) {
co838_gtvl2 6:6c61186c8739 121 pc.printf("Temp: %.2f deg Celcius.\r\n", temperature);
co838_gtvl2 6:6c61186c8739 122 } else {
co838_gtvl2 6:6c61186c8739 123 pc.printf("Temp: %.2f deg Fahrenheit.\r\n", (temperature * 1.8f + 32.0f));
co838_gtvl2 6:6c61186c8739 124 }
co838_gtvl2 5:c5d7fca4d111 125 }
co838_gtvl2 2:5d0c209e5c61 126
co838_gtvl2 6:6c61186c8739 127 /*
co838_gtvl2 6:6c61186c8739 128 * Change refresh_time according to POT1's value
co838_gtvl2 6:6c61186c8739 129 */
co838_gtvl2 6:6c61186c8739 130 refresh_time = (int) (MIN_REFRESH_TIME + ((1.0f - pot) * (MAX_REFRESH_TIME - MIN_REFRESH_TIME)));
co838_gtvl2 6:6c61186c8739 131 tilt_led = 1.0;
co838_gtvl2 6:6c61186c8739 132 }
co838_gtvl2 2:5d0c209e5c61 133
co838_gtvl2 6:6c61186c8739 134 int main(void)
co838_gtvl2 6:6c61186c8739 135 {
co838_gtvl2 6:6c61186c8739 136 pc.baud(38400);
co838_gtvl2 6:6c61186c8739 137 if (pc.writeable()) {
co838_gtvl2 7:e5732637dfd0 138 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");
co838_gtvl2 6:6c61186c8739 139 }
co838_gtvl2 2:5d0c209e5c61 140
co838_gtvl2 1:06713d1b69cf 141 /*
co838_gtvl2 1:06713d1b69cf 142 * Thermal unit control
co838_gtvl2 1:06713d1b69cf 143 */
co838_gtvl2 0:362773c24009 144 sw2_int.mode(PullUp);
co838_gtvl2 7:e5732637dfd0 145 sw2_int.fall(&sw2_interrupt);
co838_gtvl2 6:6c61186c8739 146 pc.attach(&host_interrupt);
co838_gtvl2 7:e5732637dfd0 147 sw3_int.mode(PullUp);
co838_gtvl2 7:e5732637dfd0 148 sw3_int.fall(&sw3_interrupt);
co838_gtvl2 7:e5732637dfd0 149
co838_gtvl2 6:6c61186c8739 150 r_led = 1.0;
co838_gtvl2 6:6c61186c8739 151 g_led = 1.0;
co838_gtvl2 6:6c61186c8739 152 b_led = 0.0;
co838_gtvl2 7:e5732637dfd0 153 celcius = true;
co838_gtvl2 7:e5732637dfd0 154 running = true;
co838_gtvl2 2:5d0c209e5c61 155
co838_gtvl2 6:6c61186c8739 156 // Do once
co838_gtvl2 6:6c61186c8739 157 process_function();
co838_gtvl2 6:6c61186c8739 158 wait_ms(1);
co838_gtvl2 6:6c61186c8739 159 // Then forever
co838_gtvl2 6:6c61186c8739 160 while (true) {
co838_gtvl2 7:e5732637dfd0 161 if (running && !process_timeout.hasAttachment()) {
co838_gtvl2 6:6c61186c8739 162 #if defined _DEBUG
co838_gtvl2 7:e5732637dfd0 163 pc.printf("Next cycle in %.3f seconds\r\n", refresh_time / 1000.0f);
co838_gtvl2 6:6c61186c8739 164 #endif
co838_gtvl2 6:6c61186c8739 165 process_timeout.attach_us(&process_function, (float) refresh_time * 1000.0f);
co838_gtvl2 0:362773c24009 166 }
co838_gtvl2 6:6c61186c8739 167 #if defined _DEBUG
co838_gtvl2 6:6c61186c8739 168 else {
co838_gtvl2 6:6c61186c8739 169 pc.printf("Won't attach again the timer.\r\n");
co838_gtvl2 6:6c61186c8739 170 }
co838_gtvl2 6:6c61186c8739 171 #endif
co838_gtvl2 6:6c61186c8739 172 sleep();
co838_gtvl2 0:362773c24009 173 }
co838_gtvl2 0:362773c24009 174 }