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@6:6c61186c8739, 2016-02-22 (annotated)
- Committer:
- co838_gtvl2
- Date:
- Mon Feb 22 19:09:17 2016 +0000
- Revision:
- 6:6c61186c8739
- Parent:
- 5:c5d7fca4d111
- Child:
- 7:e5732637dfd0
New version (might be FINAL) including sleep() for lowering power consumption and MyTimeout (custom class of Timeout) to deal with interrupts without breaking cycle delay. No more RTOS Thread, now using Serial::attach() to deal with keyboard input.
Who changed what in which revision?
User | Revision | Line number | New 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 | 6:6c61186c8739 | 3 | * It displays the current value to the Serial host in Celcius or Fahrenheit. |
co838_gtvl2 | 6:6c61186c8739 | 4 | * It is possible to change units using SW2 switch or computer's 'c' and 'f' keys. |
co838_gtvl2 | 6:6c61186c8739 | 5 | * It also stores a small historic and displays it to the user using the LCD screen. |
co838_gtvl2 | 6:6c61186c8739 | 6 | * Moreover, you can change the orientation of the screen by turning the device, just like a smartphone. |
co838_gtvl2 | 6:6c61186c8739 | 7 | * |
co838_gtvl2 | 6:6c61186c8739 | 8 | * Note that the use of printf in the Ticker or Timeout functions is properly done. |
co838_gtvl2 | 6:6c61186c8739 | 9 | * If _DEBUG is defined, it is possible to have a buffer conflict, but not if _DEBUG is undefined. |
co838_gtvl2 | 6:6c61186c8739 | 10 | * |
co838_gtvl2 | 4:5bf99eb2d740 | 11 | * |
co838_gtvl2 | 4:5bf99eb2d740 | 12 | * Created by Guillaume Lefrant gtvl2 |
co838_gtvl2 | 4:5bf99eb2d740 | 13 | **/ |
co838_gtvl2 | 4:5bf99eb2d740 | 14 | |
co838_gtvl2 | 1:06713d1b69cf | 15 | #include "main.h" |
co838_gtvl2 | 1:06713d1b69cf | 16 | #include "ThermalDisplayer.h" |
co838_gtvl2 | 6:6c61186c8739 | 17 | #include "MyTimeout.hpp" |
co838_gtvl2 | 0:362773c24009 | 18 | |
co838_gtvl2 | 6:6c61186c8739 | 19 | Serial pc(USBTX, USBRX); // Serial Host |
co838_gtvl2 | 6:6c61186c8739 | 20 | LM75B lm_temp(D14, D15); // Thermal Sensor |
co838_gtvl2 | 6:6c61186c8739 | 21 | InterruptIn sw2_int(SW2); // SW2 |
co838_gtvl2 | 6:6c61186c8739 | 22 | DigitalOut tilt_led(LED1); // Red LED |
co838_gtvl2 | 6:6c61186c8739 | 23 | DigitalOut r_led(PTA2); // RGB LED |
co838_gtvl2 | 6:6c61186c8739 | 24 | DigitalOut g_led(PTC4); |
co838_gtvl2 | 6:6c61186c8739 | 25 | DigitalOut b_led(PTC12); |
co838_gtvl2 | 6:6c61186c8739 | 26 | AnalogIn pot(A0); // Potentiometer POT1 |
co838_gtvl2 | 6:6c61186c8739 | 27 | MyTimeout process_timeout; // Main timeout used for the whole process |
co838_gtvl2 | 0:362773c24009 | 28 | |
co838_gtvl2 | 6:6c61186c8739 | 29 | volatile bool celcius = true; // Global boolean for unit Celcius / Fahrenheit |
co838_gtvl2 | 6:6c61186c8739 | 30 | volatile int refresh_time = 3000; |
co838_gtvl2 | 6:6c61186c8739 | 31 | |
co838_gtvl2 | 6:6c61186c8739 | 32 | ThermalDisplayer temp_display = ThermalDisplayer(); |
co838_gtvl2 | 0:362773c24009 | 33 | |
co838_gtvl2 | 1:06713d1b69cf | 34 | /* |
co838_gtvl2 | 6:6c61186c8739 | 35 | * SW2 handler |
co838_gtvl2 | 1:06713d1b69cf | 36 | */ |
co838_gtvl2 | 6:6c61186c8739 | 37 | void sw_interrupt(void) |
co838_gtvl2 | 2:5d0c209e5c61 | 38 | { |
co838_gtvl2 | 6:6c61186c8739 | 39 | celcius = !celcius; |
co838_gtvl2 | 6:6c61186c8739 | 40 | |
co838_gtvl2 | 0:362773c24009 | 41 | if (celcius) { |
co838_gtvl2 | 0:362773c24009 | 42 | r_led = 1.0; |
co838_gtvl2 | 4:5bf99eb2d740 | 43 | g_led = 1.0; |
co838_gtvl2 | 4:5bf99eb2d740 | 44 | b_led = 0.0; |
co838_gtvl2 | 0:362773c24009 | 45 | } else { |
co838_gtvl2 | 0:362773c24009 | 46 | r_led = 0.0; |
co838_gtvl2 | 0:362773c24009 | 47 | g_led = 1.0; |
co838_gtvl2 | 4:5bf99eb2d740 | 48 | b_led = 1.0; |
co838_gtvl2 | 2:5d0c209e5c61 | 49 | } |
co838_gtvl2 | 0:362773c24009 | 50 | } |
co838_gtvl2 | 0:362773c24009 | 51 | |
co838_gtvl2 | 1:06713d1b69cf | 52 | /* |
co838_gtvl2 | 6:6c61186c8739 | 53 | * Interrupt that does the same as above but using keyboard of host |
co838_gtvl2 | 1:06713d1b69cf | 54 | */ |
co838_gtvl2 | 6:6c61186c8739 | 55 | void host_interrupt(void) |
co838_gtvl2 | 5:c5d7fca4d111 | 56 | { |
co838_gtvl2 | 6:6c61186c8739 | 57 | #if defined _DEBUG |
co838_gtvl2 | 6:6c61186c8739 | 58 | pc.printf("Check if pc key as been pressed\r\n"); |
co838_gtvl2 | 6:6c61186c8739 | 59 | #endif |
co838_gtvl2 | 6:6c61186c8739 | 60 | if (pc.readable()) { |
co838_gtvl2 | 6:6c61186c8739 | 61 | char c = pc.getc(); |
co838_gtvl2 | 6:6c61186c8739 | 62 | switch(c) { |
co838_gtvl2 | 6:6c61186c8739 | 63 | case 'c': |
co838_gtvl2 | 6:6c61186c8739 | 64 | celcius = false; |
co838_gtvl2 | 6:6c61186c8739 | 65 | sw_interrupt(); |
co838_gtvl2 | 6:6c61186c8739 | 66 | break; |
co838_gtvl2 | 6:6c61186c8739 | 67 | case 'f': |
co838_gtvl2 | 6:6c61186c8739 | 68 | celcius = true; |
co838_gtvl2 | 6:6c61186c8739 | 69 | sw_interrupt(); |
co838_gtvl2 | 6:6c61186c8739 | 70 | break; |
co838_gtvl2 | 6:6c61186c8739 | 71 | default: |
co838_gtvl2 | 6:6c61186c8739 | 72 | break; |
co838_gtvl2 | 5:c5d7fca4d111 | 73 | } |
co838_gtvl2 | 5:c5d7fca4d111 | 74 | } |
co838_gtvl2 | 5:c5d7fca4d111 | 75 | } |
co838_gtvl2 | 5:c5d7fca4d111 | 76 | |
co838_gtvl2 | 6:6c61186c8739 | 77 | void process_function(void) |
co838_gtvl2 | 2:5d0c209e5c61 | 78 | { |
co838_gtvl2 | 6:6c61186c8739 | 79 | tilt_led = 0.0; |
co838_gtvl2 | 6:6c61186c8739 | 80 | // IMPORTANT. Check MyTimeout.hpp for details. |
co838_gtvl2 | 6:6c61186c8739 | 81 | process_timeout.detach(); |
co838_gtvl2 | 6:6c61186c8739 | 82 | |
co838_gtvl2 | 6:6c61186c8739 | 83 | /* |
co838_gtvl2 | 6:6c61186c8739 | 84 | * Get temperature using LM75B |
co838_gtvl2 | 6:6c61186c8739 | 85 | * and display it to LCD screen |
co838_gtvl2 | 6:6c61186c8739 | 86 | */ |
co838_gtvl2 | 6:6c61186c8739 | 87 | float temperature = lm_temp.read(); |
co838_gtvl2 | 6:6c61186c8739 | 88 | temp_display.addTemp(temperature); |
co838_gtvl2 | 6:6c61186c8739 | 89 | temp_display.adjustScale(); |
co838_gtvl2 | 6:6c61186c8739 | 90 | temp_display.display(); |
co838_gtvl2 | 6:6c61186c8739 | 91 | |
co838_gtvl2 | 6:6c61186c8739 | 92 | |
co838_gtvl2 | 6:6c61186c8739 | 93 | /* |
co838_gtvl2 | 6:6c61186c8739 | 94 | * Display value to host according to unit choosed with SW2. |
co838_gtvl2 | 6:6c61186c8739 | 95 | * Could have been a ternary, but it's easier to read like this. |
co838_gtvl2 | 6:6c61186c8739 | 96 | * In production (without _DEBUG), this is the only printf executed. |
co838_gtvl2 | 6:6c61186c8739 | 97 | */ |
co838_gtvl2 | 6:6c61186c8739 | 98 | if (pc.writeable()) { |
co838_gtvl2 | 6:6c61186c8739 | 99 | if (celcius) { |
co838_gtvl2 | 6:6c61186c8739 | 100 | pc.printf("Temp: %.2f deg Celcius.\r\n", temperature); |
co838_gtvl2 | 6:6c61186c8739 | 101 | } else { |
co838_gtvl2 | 6:6c61186c8739 | 102 | pc.printf("Temp: %.2f deg Fahrenheit.\r\n", (temperature * 1.8f + 32.0f)); |
co838_gtvl2 | 6:6c61186c8739 | 103 | } |
co838_gtvl2 | 5:c5d7fca4d111 | 104 | } |
co838_gtvl2 | 2:5d0c209e5c61 | 105 | |
co838_gtvl2 | 6:6c61186c8739 | 106 | /* |
co838_gtvl2 | 6:6c61186c8739 | 107 | * Change refresh_time according to POT1's value |
co838_gtvl2 | 6:6c61186c8739 | 108 | */ |
co838_gtvl2 | 6:6c61186c8739 | 109 | refresh_time = (int) (MIN_REFRESH_TIME + ((1.0f - pot) * (MAX_REFRESH_TIME - MIN_REFRESH_TIME))); |
co838_gtvl2 | 6:6c61186c8739 | 110 | tilt_led = 1.0; |
co838_gtvl2 | 6:6c61186c8739 | 111 | } |
co838_gtvl2 | 2:5d0c209e5c61 | 112 | |
co838_gtvl2 | 6:6c61186c8739 | 113 | int main(void) |
co838_gtvl2 | 6:6c61186c8739 | 114 | { |
co838_gtvl2 | 6:6c61186c8739 | 115 | pc.baud(38400); |
co838_gtvl2 | 6:6c61186c8739 | 116 | if (pc.writeable()) { |
co838_gtvl2 | 6:6c61186c8739 | 117 | pc.printf("Hello gtvl2, from FRDM-K64F!\r\nUse POT1 to change the refresh rate, POT2 to change the scale of the graphic and SW2 or keyboard to change the unit.\r\n"); |
co838_gtvl2 | 6:6c61186c8739 | 118 | } |
co838_gtvl2 | 2:5d0c209e5c61 | 119 | |
co838_gtvl2 | 1:06713d1b69cf | 120 | /* |
co838_gtvl2 | 1:06713d1b69cf | 121 | * Thermal unit control |
co838_gtvl2 | 1:06713d1b69cf | 122 | */ |
co838_gtvl2 | 0:362773c24009 | 123 | sw2_int.mode(PullUp); |
co838_gtvl2 | 6:6c61186c8739 | 124 | sw2_int.fall(&sw_interrupt); |
co838_gtvl2 | 6:6c61186c8739 | 125 | pc.attach(&host_interrupt); |
co838_gtvl2 | 2:5d0c209e5c61 | 126 | |
co838_gtvl2 | 6:6c61186c8739 | 127 | r_led = 1.0; |
co838_gtvl2 | 6:6c61186c8739 | 128 | g_led = 1.0; |
co838_gtvl2 | 6:6c61186c8739 | 129 | b_led = 0.0; |
co838_gtvl2 | 2:5d0c209e5c61 | 130 | |
co838_gtvl2 | 6:6c61186c8739 | 131 | // Do once |
co838_gtvl2 | 6:6c61186c8739 | 132 | process_function(); |
co838_gtvl2 | 6:6c61186c8739 | 133 | wait_ms(1); |
co838_gtvl2 | 6:6c61186c8739 | 134 | // Then forever |
co838_gtvl2 | 6:6c61186c8739 | 135 | while (true) { |
co838_gtvl2 | 6:6c61186c8739 | 136 | if (!process_timeout.hasAttachment()) { |
co838_gtvl2 | 6:6c61186c8739 | 137 | #if defined _DEBUG |
co838_gtvl2 | 6:6c61186c8739 | 138 | pc.printf("Next value in %.3f seconds\r\n", refresh_time / 1000.0f); |
co838_gtvl2 | 6:6c61186c8739 | 139 | #endif |
co838_gtvl2 | 6:6c61186c8739 | 140 | process_timeout.attach_us(&process_function, (float) refresh_time * 1000.0f); |
co838_gtvl2 | 0:362773c24009 | 141 | } |
co838_gtvl2 | 6:6c61186c8739 | 142 | #if defined _DEBUG |
co838_gtvl2 | 6:6c61186c8739 | 143 | else { |
co838_gtvl2 | 6:6c61186c8739 | 144 | pc.printf("Won't attach again the timer.\r\n"); |
co838_gtvl2 | 6:6c61186c8739 | 145 | } |
co838_gtvl2 | 6:6c61186c8739 | 146 | #endif |
co838_gtvl2 | 6:6c61186c8739 | 147 | sleep(); |
co838_gtvl2 | 0:362773c24009 | 148 | } |
co838_gtvl2 | 0:362773c24009 | 149 | } |