Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed DS18B20 TextLCD
Diff: main.cpp
- Revision:
- 0:55c37ea095b0
- Child:
- 1:f8a4796e766e
diff -r 000000000000 -r 55c37ea095b0 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,344 @@
+#include "mbed.h"
+#include "TextLCD.h"
+#include <atomic_flag.h>
+#include <string>
+#include <cstdio>
+#include <cassert>
+#include <cstdarg>
+#include <DS1820.h>
+#include <DebounceIn.h>
+#include <limits>
+#include <flash.h>
+#include <cassert>
+
+static DigitalOut led_on_board(PC_13);
+
+/* str --------------------------------------------- */
+
+void str_remove(char *str, const char *reject) {
+ while (1) {
+ const size_t s = strcspn(str, reject);
+ str += s;
+ if (str[0] == '\0') {
+ break;
+ }
+ memmove(str, str + 1, strlen(str + 1) + 1);
+ }
+}
+
+void str_pad_suffix(char *str, size_t len, char c) {
+ if (strlen(str) < len) {
+ memset(str + strlen(str), c, len - strlen(str));
+ }
+ str[len] = '\0';
+}
+
+char *str_filename(const char *file) {
+ return (char*)(strrchr(file, '/') ? strrchr(file, '/') + 1 : file);
+}
+
+/* lcd ------------------------------------------------- */
+
+static TextLCD& lcd() {
+ static TextLCD lcd(PB_15, PA_10, PB_3, PB_4, PB_5, PB_6, TextLCD::LCD16x2); // rs, e, d4-d7
+ // static TextLCD lcd(PA_0, PA_1, PA_2, PA_3, PA_4, PA_5, TextLCD::LCD16x2); // rs, e, d4-d7
+ return lcd;
+}
+
+void lcd_cls() {
+ lcd().cls();
+}
+
+void lcd_vprintln(const char *fmt, va_list va) {
+ char buf[20] = {0};
+ const size_t len = vsnprintf(buf, sizeof(buf), fmt, va);
+ str_remove(buf, "\r\n");
+ str_pad_suffix(buf, 16, ' ');
+ lcd().printf(buf);
+}
+
+__attribute__((__format__(__printf__, 1, 2)))
+void lcd_println(const char *fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ lcd_vprintln(fmt, va);
+ va_end(va);
+}
+
+extern "C" {
+ void d(const char *fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ lcd_vprintln(fmt, va);
+ va_end(va);
+ wait(1);
+ }
+}
+
+/* system --------------------------------------------- */
+
+extern "C" void abort() {
+ for (int i = 0; i < 20 * 5; ++i) {
+ led_on_board = !led_on_board;
+ wait(0.05);
+ }
+ NVIC_SystemReset();
+}
+
+extern "C" void __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
+ lcd_println("ASSERT %d", line);
+ lcd_println("%s", str_filename(file));
+ abort();
+}
+
+
+/* ds18b20 --------------------------------------------- */
+
+/**
+ * @return
+ * 0 - no errors ('temp' contains the temperature measured)
+ * 1 - sensor not present ('temp' is not updated)
+ * 2 - CRC error ('temp' is not updated)
+ */
+static int ds18b20_temp(float& temperature_f_C) {
+ static DS1820 probe('B', PB_1);
+ static Timer t;
+ static bool running = false;
+
+ // start the conversion if not running
+ if (running == false) {
+ running = true;
+ probe.startConversion();
+ t.start();
+ }
+
+ // wait for conversion end
+ const unsigned ms = t.read_ms();
+ const unsigned conversion_time_ms = 800;
+ if (ms < conversion_time_ms) {
+ wait((conversion_time_ms - ms) / 1000.0);
+ }
+
+ // read temperature from buffer
+ temperature_f_C = -1000;
+ const uint8_t err = probe.read(temperature_f_C);
+
+ // restart new conversion
+ probe.startConversion();
+ t.reset();
+
+ return err;
+}
+
+/* output -------------------------------------------- */
+
+static DigitalOut output(PC_14);
+
+/* state --------------------------------------------- */
+
+struct state {
+ volatile int high; // in Celcius
+ volatile int low; // in Celcius
+ volatile bool inverted;
+
+ state() : high(30), low(20) {}
+
+ struct data {
+ static const int data_version = 0x11;
+ int version;
+ int high;
+ int low;
+ bool inverted : 1;
+ bool current : 1;
+ data() : version(data_version) {}
+ data(const state& s, const DigitalOut& o) :
+ version(data_version),
+ high(s.high),
+ low(s.low),
+ inverted(s.inverted),
+ current(output)
+ {}
+ void put(state& s, DigitalOut& o) {
+ s.high = high;
+ s.low = low;
+ s.inverted = inverted;
+ o = current;
+ }
+ };
+
+ static bool _low_high_valid(int high, int low) {
+ return -99 < high && high < 99 &&
+ -99 < low && low < 99 &&
+ low < high &&
+ low != high;
+ }
+
+ void save() {
+ const struct data d(*this, output);
+ flash::write(d);
+ }
+
+ void restore() {
+ struct data d;
+ const int e = flash::read(d);
+ if (e) {
+ lcd_println("New flash %d", e);
+ wait(1);
+ return;
+ }
+ if (!_low_high_valid(d.high, d.low)) {
+ lcd_println("Invalid flash vals");
+ lcd_println("%d %d", d.high, d.low);
+ wait(1);
+ return;
+ }
+ lcd_println("Flash load %d %d", d.high, d.low);
+ wait(1);
+ d.put(*this, output);
+ }
+
+ void high_inc() { _inc_it(high, low); }
+ void high_dec() { _dec_it(high, low); }
+ void low_inc() { _inc_it(low, high); }
+ void low_dec() { _dec_it(low, high); }
+ void invert_invert() {
+ inverted = !inverted;
+ save();
+ }
+
+private:
+ void _inc_it(volatile int &val, volatile int &other) {
+ if (val + 1 == other) return;
+ if (val >= 99) return;
+ val++;
+ save();
+ }
+ void _dec_it(volatile int &val, volatile int &other) {
+ if (val - 1 == other) return;
+ if (val <= -99) return;
+ val--;
+ save();
+ }
+};
+
+static state state;
+
+
+/* buttons -------------------------------------------- */
+
+static DebounceIn button_h_inc(PA_6, PullDown);
+static DebounceIn button_h_dec(PA_5, PullDown);
+static DebounceIn button_l_inc(PA_4, PullDown);
+static DebounceIn button_l_dec(PA_3, PullDown);
+static DebounceIn button_inv(PA_2, PullDown);
+static DebounceIn button_refresh(PA_1, PullDown);
+
+static void button_h_inc_pressed() { state.high_inc(); }
+static void button_h_dec_pressed() { state.high_dec(); }
+static void button_l_inc_pressed() { state.low_inc(); }
+static void button_l_dec_pressed() { state.low_dec(); }
+static void button_inv_pressed() {
+ output = !output;
+ state.invert_invert();
+}
+
+static void button_init() {
+ const unsigned debounce_timeout_us = 200 * 1000;
+ button_h_inc.fall(button_h_inc_pressed, debounce_timeout_us);
+ button_h_dec.fall(button_h_dec_pressed, debounce_timeout_us);
+ button_l_inc.fall(button_l_inc_pressed, debounce_timeout_us);
+ button_l_dec.fall(button_l_dec_pressed, debounce_timeout_us);
+ button_inv.fall(button_inv_pressed, debounce_timeout_us * 2);
+}
+
+
+static void button_check() {
+ while(1) {
+ DebounceIn *arr[6] = {
+ &button_h_inc,
+ &button_h_dec,
+ &button_l_inc,
+ &button_l_dec,
+ &button_inv,
+ &button_refresh
+ };
+ lcd_println("%d %d %d %d %d %d\n",
+ arr[0]->read(),
+ arr[1]->read(),
+ arr[2]->read(),
+ arr[3]->read(),
+ arr[4]->read(),
+ arr[5]->read());
+ lcd_println("");
+ }
+}
+
+/* main --------------------------- */
+
+static void setup() {
+ // wait for voltage stability
+ wait(1);
+ // some info
+ lcd_cls();
+ lcd_println("Hello!");
+ lcd_println("clock=%ld", SystemCoreClock);
+ wait(1);
+ lcd_cls();
+ state.restore();
+ button_init();
+}
+
+static void loop() {
+ static bool alive;
+ alive = !alive;
+
+ float temperature_f_C = 0;
+ const int ds18b20_err = ds18b20_temp(temperature_f_C);
+
+ lcd_cls();
+
+ char temperature_s[8] = "ERROR";
+ if (ds18b20_err == 0) {
+ const int temperature_dC = temperature_f_C * 10;
+ const int temperature_C = temperature_f_C;
+
+ if (temperature_C < -100 || temperature_C > 100) {
+ snprintf(temperature_s, sizeof(temperature_s), "INVAL");
+ } else {
+
+ if (!output ^ state.inverted) {
+ if (temperature_C > state.high) {
+ output = 1 ^ state.inverted;
+ }
+ } else {
+ if (temperature_C < state.low) {
+ output = 0 ^ state.inverted;
+ }
+ }
+
+ snprintf(temperature_s, sizeof(temperature_s), "%3d.%d'C", temperature_C, temperature_dC % 10);
+ }
+ }
+
+ led_on_board = output;
+
+ lcd_println("%-7s %3s %3s",
+ temperature_s,
+ state.inverted ? "INV" : "NOR",
+ output ? "ON" : "OFF"
+ );
+ lcd_println("H=%2d'C L=%2d'C %c%c",
+ state.high,
+ state.low,
+ !alive ? '\xff' : ' ',
+ alive ? '\xff' : ' '
+ );
+}
+
+int main() {
+ setup();
+ while (1) {
+ loop();
+ }
+ return 0;
+}