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: EthernetInterface HTTPClient NTPClient mbed-rtos mbed
Revision 0:53f05303850a, committed 2012-12-31
- Comitter:
- wkinkeldei
- Date:
- Mon Dec 31 12:08:24 2012 +0000
- Child:
- 1:9e88b2508768
- Commit message:
- first working version with all needed features implemented: measure, display, post
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetInterface.lib Mon Dec 31 12:08:24 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/EthernetInterface/#a0ee3ae75cfa
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient.lib Mon Dec 31 12:08:24 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/HTTPClient/#1f743885e7de
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient.lib Mon Dec 31 12:08:24 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/NTPClient/#881559865a93
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/collector_proxy.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,34 @@
+#include "collector_proxy.h"
+#include "HTTPClient.h"
+
+#include <cstring>
+
+CollectorProxy::CollectorProxy(char *url) :base_url(url) {
+}
+
+int CollectorProxy::send_measure(char *path_part, int value) {
+ HTTPClient http;
+ HTTPMap data;
+ char str[512];
+ HTTPText in_text(str, 512);
+
+ char url[200];
+ strcpy(url, base_url);
+ strcat(url, "/");
+ strcat(url, path_part);
+
+ char value_buffer[10];
+ sprintf(value_buffer, "%d", value);
+ data.put("value", value_buffer);
+
+ int ret = http.post(url, data, &in_text);
+
+ if (!ret) {
+ // printf("Executed POST successfully - read %d characters\n", strlen(str));
+ // printf("Result: %s\n", str);
+ return 1;
+ } else {
+ // printf("Error - ret = %d - HTTP return code = %d\n", ret, http.getHTTPResponseCode());
+ return 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/collector_proxy.h Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,16 @@
+#ifndef COLLECTOR_PROXY_H
+#define COLLECTOR_PROXY_H
+
+#include "mbed.h"
+#include "HTTPClient.h"
+
+class CollectorProxy {
+public:
+ CollectorProxy(char *url);
+ int send_measure(char *path_part, int value); // result 1:OK, 0:fail
+
+private:
+ char *base_url;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,158 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "EthernetInterface.h"
+
+#include <list>
+
+#include "sparkfun.h"
+#include "ntp_proxy.h"
+#include "collector_proxy.h"
+#include "sensor.h"
+#include "temperature_sensor.h"
+
+SparkFun display(p28);
+list<Sensor *> sensors;
+
+void wait_minutes(int m = 1) {
+ while (m-- > 0)
+ Thread::wait(1000 * 60);
+}
+
+void wait_seconds(int s = 1) {
+ while (s-- > 0)
+ Thread::wait(1000);
+}
+
+/*
+ ntp Thread: poll NTP Server every 3 hours
+*/
+void ntp_thread(void const *args) {
+ NtpProxy ntp;
+
+ while (true) {
+ display.show_ntp_status('t');
+ if (ntp.set_time()) {
+ // successful: wait 3 hours
+ display.show_ntp_status('T');
+ wait_minutes(180);
+ } else {
+ // failure: retry after 5 minutes
+ display.show_ntp_status('?');
+ wait_minutes(5);
+ }
+ }
+}
+
+/*
+ display Thread: show a sensor every 2 seconds and current time
+*/
+void display_thread(void const *args) {
+ char buffer[20];
+ int last_minute = -1;
+ time_t seconds;
+ struct tm *t;
+ list<Sensor *>::iterator it = sensors.begin();
+
+ while (true) {
+ // display next sensor's measure (if any)
+ if (it != sensors.end()) display.show_sensor_measure((*it)->get_name(), (*it)->last_measure());
+ it++;
+ if (it == sensors.end()) it = sensors.begin();
+
+ // display time if minute is different from displayed value
+ seconds = time(NULL) + 3600; // FIXME: time-zone calculations wanted -- toggle switch?
+ t = localtime(&seconds);
+ if (last_minute != t->tm_min) {
+ last_minute = t->tm_min;
+ strftime(buffer, 20, "%H:%M", t);
+ display.show_time_text(buffer);
+ }
+
+ wait_seconds(2);
+ }
+}
+
+/*
+ measure Thread: read all sensors every 10 seconds
+*/
+void measure_thread(void const *args) {
+ while (true) {
+ list<Sensor *>::iterator it;
+ int nr = 0;
+ for (it = sensors.begin(); it != sensors.end(); it++) {
+ display.show_current_sensor((*it)->get_kind(), nr, '<');
+
+ (*it)->prepare_measure();
+ display.show_current_status('>');
+ (*it)->measure();
+ display.show_current_status('='); // oder '?' falls falsch
+
+ wait_seconds(1);
+
+ nr++;
+ }
+ display.clear_current_sensor();
+
+ wait_seconds(10); // FIXME: increase to 60 seconds
+ }
+}
+
+/*
+ send Thread: post measures to Statistics Collector every 15 minutes
+*/
+void send_thread(void const *args) {
+ CollectorProxy collector("http://kinkeldei-net.de:81/sensor");
+
+ while (true) {
+ // 10 minute delay with feedback in the last 9 minutes
+ for (int i=10; i>=0; i--) {
+ display.show_network_status(i > 9 ? ' ' : '0' + i);
+ wait_minutes(1);
+ }
+
+ list<Sensor *>::iterator it;
+ for (it = sensors.begin(); it != sensors.end(); it++) {
+ display.show_network_status('P');
+ int ret = collector.send_measure((*it)->get_url_part(), (*it)->get_value());
+
+ display.show_network_status(ret ? 'O' : 'E');
+ wait_seconds(2);
+ }
+ }
+}
+
+/*
+ main Thread: initialize and flash a LED
+*/
+int main() {
+ display.print_init_message();
+
+ // ConfigReader c('config.ini');
+ // c.read_config();
+
+ sensors.push_back((Sensor *) new TemperatureSensor(p21, "erlangen/temperatur/demo", "demo"));
+
+ /*
+ sensors.push_back((Sensor *) new TemperatureSensor(p21, "trainmeusel/temperatur/heizung", "heizung"));
+ sensors.push_back((Sensor *) new TemperatureSensor(p22, "trainmeusel/temperatur/keller", "keller"));
+ sensors.push_back((Sensor *) new TemperatureSensor(p23, "trainmeusel/temperatur/flur", "flur"));
+ sensors.push_back((Sensor *) new TemperatureSensor(p24, "trainmeusel/temperatur/aussen", "aussen"));
+ */
+
+ // must come from configreader later, then remove:
+ EthernetInterface eth;
+ eth.init("192.168.2.175", "255.255.255.0", "192.168.2.1");
+ eth.connect();
+
+ Thread t1(ntp_thread);
+ Thread t2(display_thread);
+ Thread t3(measure_thread);
+ Thread t4(send_thread);
+
+ // a periodical flash should indicate "we are alive"
+ DigitalOut led(LED1);
+ while (true) {
+ led = !led;
+ wait_seconds(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Mon Dec 31 12:08:24 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#88a1a9c26ae3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Dec 31 12:08:24 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/49c296715c73 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ntp_proxy.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,10 @@
+#include "ntp_proxy.h"
+
+NtpProxy::NtpProxy(void) {
+ ntp_client = new NTPClient();
+}
+
+int NtpProxy::set_time(void) {
+ NTPResult r = ntp_client->setTime("time.apple.com");
+ return r == NTP_OK;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ntp_proxy.h Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,16 @@
+#ifndef NTP_PROXY_H
+#define NTP_PROXY_H
+
+#include "mbed.h"
+#include "NTPClient.h"
+
+class NtpProxy {
+ NTPClient *ntp_client;
+
+public:
+ NtpProxy(void);
+
+ int set_time(void);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/one_wire.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,114 @@
+#include "one_wire.h"
+
+/* "borrowed" from snatch59: OneWireCRC and simplified for my needs */
+
+const int timing[] = {6, 64, 60, 10, 9, 55, 0, 480, 70, 410};
+
+OneWire::OneWire(PinName pin) : port(pin) {
+}
+
+int OneWire::reset() {
+ int result = 0; // sample presence pulse result
+
+ wait_us(timing[6]);
+ port.output();
+ port = 0;
+ wait_us(timing[7]);
+ port.input();
+ wait_us(timing[8]);
+ result = !(port & 0x01);
+ wait_us(timing[9]);
+
+ return result;
+}
+
+void OneWire::write_bit(int bit) {
+ bit = bit & 0x01;
+
+ if (bit) {
+ // Write '1' bit
+ port.output();
+ port = 0;
+ wait_us(timing[0]);
+ port.input();
+ wait_us(timing[1]);
+ } else {
+ // Write '0' bit
+ port.output();
+ port = 0;
+ wait_us(timing[2]);
+ port.input();
+ wait_us(timing[3]);
+ }
+}
+
+int OneWire::read_bit() {
+ int result;
+
+ port.output();
+ port = 0;
+ wait_us(timing[0]);
+ port.input();
+ wait_us(timing[4]);
+ result = port & 0x01;
+ wait_us(timing[5]);
+
+ return result;
+}
+
+void OneWire::write_byte(int data) {
+ // Loop to write each bit in the byte, LS-bit first
+ for (int loop = 0; loop < 8; loop++) {
+ write_bit(data & 0x01);
+
+ // shift the data byte for the next bit
+ data >>= 1;
+ }
+}
+
+int OneWire::read_byte() {
+ int result = 0;
+
+ for (int loop = 0; loop < 8; loop++) {
+ // shift the result to get it ready for the next bit
+ result >>= 1;
+
+ // if result is one, then set MS bit
+ if (read_bit()) result |= 0x80;
+ }
+
+ return result;
+}
+
+void OneWire::block(char* data, int data_len) {
+ for (int loop = 0; loop < data_len; loop++) {
+ data[loop] = read_byte(); // original: touchByte(data[loop]);
+ }
+}
+
+void OneWire::prepare_read() {
+ reset();
+ write_byte(SKIP_ROM);
+ write_byte(CONVERT);
+
+ // switch on parasite power while waiting.
+ port.output();
+ port = 1;
+}
+
+int OneWire::read_temperature() {
+ char data[9];
+ short *raw_temp = (short *) data;
+ int temperature = -99;
+
+ reset();
+ write_byte(SKIP_ROM);
+ write_byte(READSCRATCH);
+ block(data, 9);
+
+ if (data[5] == 255 && data[7] == 16) {
+ temperature = *raw_temp >> 4;
+ }
+
+ return temperature;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/one_wire.h Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,40 @@
+#ifndef _ONE_WIRE_H
+#define _ONE_WIRE_H
+
+#include "mbed.h"
+
+// One Wire command codes
+#define OVERDRIVE_SKIP 0x3C
+// ROM commands
+#define SEARCH_ROM 0xF0
+#define READ_ROM 0x33
+#define MATCH_ROM 0x55
+#define SKIP_ROM 0xCC
+#define ALARM_SEARCH 0xEC
+// Functions Commnds
+#define CONVERT 0x44
+#define WRITESCRATCH 0x4E
+#define READSCRATCH 0xBE
+#define COPYSCRATCH 0x48
+#define RECALLE2 0xB8
+#define READPOWERSUPPLY 0xB4
+
+class OneWire {
+private:
+ DigitalInOut port;
+
+public:
+ OneWire(PinName pin);
+ int reset();
+ void write_bit(int bit);
+ int read_bit();
+ void write_byte(int data);
+ int read_byte();
+ void block(char* data, int data_len);
+
+ // high level functions: prepare(), delay(1000ms), read()
+ void prepare_read();
+ int read_temperature();
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sensor.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,41 @@
+#include "sensor.h"
+
+Sensor::Sensor(char kind, PinName pin, char *url_part, char *name) : kind(kind), pin(pin), url_part(url_part), name(name) {
+ cleanup_measure();
+}
+
+void Sensor::set_value(int v) {
+ value = v;
+}
+
+int Sensor::get_value(void) {
+ return value;
+}
+
+char Sensor:: get_kind(void) {
+ return kind;
+}
+
+int Sensor::get_pin(void) {
+ return pin;
+}
+
+char *Sensor::get_url_part(void) {
+ return url_part;
+}
+
+char *Sensor::get_name(void) {
+ return name;
+}
+
+void Sensor::prepare_measure(void) {}
+
+void Sensor::measure(void) {}
+
+void Sensor::cleanup_measure(void) {
+ value = 0;
+}
+
+char *Sensor::last_measure(void) {
+ return NULL;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sensor.h Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,32 @@
+#ifndef SENSOR_H
+#define SENSOR_H
+
+#include "mbed.h"
+
+class Sensor {
+public:
+ // T26: buero/temperatur Buero
+ Sensor(char kind, PinName pin, char *url_part, char *name);
+
+ void set_value(int v);
+ int get_value(void);
+
+ char get_kind(void);
+ int get_pin(void);
+ char *get_url_part(void);
+ char *get_name(void);
+
+ virtual void prepare_measure(void);
+ virtual void measure(void);
+ virtual void cleanup_measure(void);
+ virtual char *last_measure(void);
+
+protected:
+ char kind;
+ PinName pin;
+ char *url_part;
+ char *name;
+ int value;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sparkfun.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,102 @@
+#include "sparkfun.h"
+#include "rtos.h"
+
+/*
+ 1234567890ABCDEF
+ [Buero 52°C]
+ [T26> P N x 11:42]
+ ^ ^ ^ ^ ^ ^
+ | | | | | |
+ | | | | | |
+ | | | | | +-- 27: Uhrzeit "hh:mm" / Datum "Mar03" / Uptime " 42d"
+ | | | | |
+ | | | | +-- 25: Reserve
+ | | | |
+ | | | +-- 23: NTP Status: t=lesen, T=ok, ?=error
+ | | |
+ | | +-- 21: Netz: P)ost O)k E)rror [1-9] = in x Minuten gehts los
+ | |
+ | +-- 19: < senden, > lesen, = fertig, ? fehler
+ |
+ +-- 16: gerade/zuletzt gemessener Sensor
+
+*/
+
+SparkFun::SparkFun(PinName tx) : Serial(tx, NC) {
+ baud(9600);
+}
+
+void SparkFun::clear(void) {
+ control_sequence(0x01);
+}
+
+void SparkFun::set_cursor_position(int pos) {
+ if (pos >= 16) {
+ pos = 64 + pos - 16;
+ }
+ control_sequence(0x80 + pos);
+}
+
+void SparkFun::control_sequence(char c) {
+ putc(0xfe);
+ putc(c);
+}
+
+void SparkFun::print_init_message(void) {
+ clear();
+
+ set_cursor_position(0);
+ puts("TempSensor");
+
+ // will get overridden very soon.
+ // set_cursor_position(16);
+ // puts("init");
+}
+
+void SparkFun::show_sensor_measure(char *name, char *measure) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(0);
+ printf("%-12s%4s", name, measure);
+}
+
+void SparkFun::clear_current_sensor(void) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(16);
+ puts(" ");
+}
+
+void SparkFun::show_current_sensor(char kind, int nr, char status) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(16);
+ printf("%c%02d%c", kind, nr, status);
+}
+
+void SparkFun::show_current_status(char status) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(19);
+ putc(status);
+}
+
+void SparkFun::show_network_status(char status) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(21);
+ putc(status);
+}
+
+void SparkFun::show_ntp_status(char status) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(23);
+ putc(status);
+}
+
+void SparkFun::show_spare_status(char status) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(25);
+ putc(status);
+}
+
+void SparkFun::show_time_text(char *text) {
+ Thread::wait(50); // time for 48 characters.
+ set_cursor_position(27);
+ printf("%-5s", text);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sparkfun.h Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,27 @@
+#ifndef SPARKFUN_H
+#define SPARKFUN_H
+
+#include "mbed.h"
+
+class SparkFun : public Serial {
+public:
+ SparkFun(PinName tx);
+
+ // low level functions
+ void clear(void);
+ void set_cursor_position(int pos);
+ void control_sequence(char c);
+
+ // high level functions
+ void print_init_message(void);
+ void show_sensor_measure(char *name, char *measure);
+ void clear_current_sensor(void);
+ void show_current_sensor(char kind, int nr, char status = ' ');
+ void show_current_status(char status);
+ void show_network_status(char status);
+ void show_ntp_status(char status);
+ void show_spare_status(char status);
+ void show_time_text(char *text);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/temperature_sensor.cpp Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,20 @@
+#include "temperature_sensor.h"
+#include "rtos.h"
+
+TemperatureSensor::TemperatureSensor(PinName pin, char *url_part, char *name) : Sensor('T', pin, url_part, name), one_wire(pin) {
+}
+
+void TemperatureSensor::prepare_measure(void) {
+ one_wire.prepare_read();
+ Thread::wait(1000);
+}
+
+void TemperatureSensor::measure(void) {
+ value = one_wire.read_temperature();
+}
+
+char *TemperatureSensor::last_measure(void) {
+ sprintf(buffer, "%d\337C", value);
+
+ return buffer;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/temperature_sensor.h Mon Dec 31 12:08:24 2012 +0000
@@ -0,0 +1,20 @@
+#ifndef TEMPERATURE_SENSOR_H
+#define TEMPERATURE_SENSOR_H
+
+#include "sensor.h"
+#include "one_wire.h"
+
+class TemperatureSensor : public Sensor {
+public:
+ TemperatureSensor(PinName pin, char *url_part, char *name);
+
+ virtual void prepare_measure(void);
+ virtual void measure(void);
+ virtual char *last_measure(void);
+
+protected:
+ OneWire one_wire;
+ char buffer[10];
+};
+
+#endif