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: TextLCD nRF24L01P mbed
Diff: main.cpp
- Revision:
- 10:3417715786be
- Parent:
- 9:53da36425601
- Child:
- 11:c94b9db597e9
--- a/main.cpp Tue Jan 17 21:42:42 2017 +0000
+++ b/main.cpp Sun Jan 22 20:03:32 2017 +0000
@@ -1,10 +1,13 @@
#include "mbed.h"
-#include "rtos.h"
+//#include "rtos.h"
#include "TextLCD.h"
#include "custom-chars.h"
#include "melodies.h"
#include "nRF24L01P.h"
#include <string>
+#include <vector>
+
+time_t next_alarm = 0;
// Host PC Communication channels
Serial pc(USBTX, USBRX); // tx, rx
@@ -13,7 +16,18 @@
TextLCD_I2C lcd(&i2c_lcd, 0x4E, TextLCD::LCD16x2); // I2C exp: I2C bus, PCF8574 Slaveaddress, LCD Type
//Light sensor
+#define LIGHT_INTERVAL 2
AnalogIn light_sensor(A1);
+double light_sum;
+int light_samples;
+time_t next_light = 0;
+//Mutex light_mutex;
+
+void lightSensor(){
+ light_sum += light_sensor;
+ light_samples++;
+ next_light = time(NULL) + LIGHT_INTERVAL;
+}
//2.4 GHz radio
#define RX_ADDRESS ((unsigned long long) 0xABCDEF00)
@@ -56,25 +70,55 @@
radio.enable();
};
-//TODO: I don't think it needs to be in a separate thread,
-//we probably can just put it into the main loop.
-void radio_recv(void const* args){
- char rxData[TRANSFER_SIZE+1];
- while (1) {
- int rx_bytes=0;
+bool movement_detected = false;
+
+std::vector<std::string> last_wireless_data;
+time_t last_wireless_time;
- if(radio.readable(NRF24L01P_PIPE_P1)){
- rx_bytes = radio.read(NRF24L01P_PIPE_P1, rxData, TRANSFER_SIZE);
- rxData[TRANSFER_SIZE] = '\0';
- pc.printf("Received %d >>%s<<\r\n",rx_bytes, rxData);
- }
+void processWirelessData(char* data_string){
+ std::string s = data_string;
+ std::vector<std::string> data;
+ size_t pos = 0;
+ std::string token;
+ std::string delimiter = "&";
+
+ while ((pos = s.find(delimiter)) != std::string::npos) {
+ token = s.substr(0, pos);
+ data.push_back(token);
+ s.erase(0, pos + delimiter.length());
+ }
+
+ last_wireless_data = data;
+ last_wireless_time = time(NULL);
+
+ if (data.size() >= 3){
+ double min = atof(data[0].c_str());
+ double max = atof(data[1].c_str());
+ double avg = atof(data[2].c_str());
+ if (max > 0.3 && avg > 0.1)
+ movement_detected = true;
+ else
+ movement_detected = false;
}
}
-//Display
-void backlightTimeout(void const *arg);
-RtosTimer backlightTimer(&backlightTimeout, osTimerPeriodic, (void*)0);
+void radio_recv(){
+ char rxData[TRANSFER_SIZE+1];
+ int rx_bytes=0;
+
+ if(radio.readable(NRF24L01P_PIPE_P1)){
+ rx_bytes = radio.read(NRF24L01P_PIPE_P1, rxData, TRANSFER_SIZE);
+ rxData[TRANSFER_SIZE] = '\0';
+ pc.printf("Received %d >>%s<<\r\n",rx_bytes, rxData);
+ processWirelessData(rxData);
+ }
+}
+
+//Handling display
+void backlightTimeout();
+//RtosTimer backlightTimer(&backlightTimeout, osTimerPeriodic, (void*)0);
+Timeout backlightTimer;
class Display{
public:
@@ -88,7 +132,7 @@
char time_str[9];
char date_str[9];
- static const int backlightTime = 5000;
+ static const float backlightTime = 5.000;
int backlightState;
Display()
{
@@ -113,15 +157,23 @@
void backlightOn(){
lcd.setBacklight(TextLCD::LightOn);
backlightState = 1;
- backlightTimer.start(backlightTime);
+ backlightTimer.attach(&backlightTimeout, backlightTime);
+
}
void update(){
//Top row of display
char ico1 = ' ';
- char ico2 = wireless_in_progress ? (frame % 2 ? C_WLC : ' ' ) : ' ';
- char ico3 = C_ALRM;
- int ah=85, am=84;
+ char ico2 = sync_in_progress ? (frame % 2 ? C_WIFI : ' ' ) : ' ';
+ char ico3 = ' ';
+ char alarm_time[6];
+ if (next_alarm != 0){
+ ico3 = C_ALRM;
+ strftime(alarm_time, 6, "%H:%M", localtime(&next_alarm));
+ }
+ else {
+ strcpy(alarm_time, " ");
+ }
time_t seconds_now = time(NULL);
if (seconds_now != seconds) {
@@ -131,12 +183,15 @@
}
lcd.locate(0,0); //Put in top row
- lcd.printf("%s%c%c%c%02d:%02d",time_str,ico1,ico2,ico3,ah,am);
+ lcd.printf("%s%c%c%c%s",time_str,ico1,ico2,ico3,alarm_time);
lcd.locate(0,1); //Put in bottom row
if (sync_in_progress) {
lcd.printf("Synchronizacja..");
}
+ if (alarm_on){
+ lcd.printf("Wstawaj! ");
+ }
else {
if (frame % 60 < 30) {
lcd.printf("SmartAlarm+ Pro ");
@@ -166,7 +221,7 @@
userButtonReleased = 1;
}
-void backlightTimeout(void const *arg){
+void backlightTimeout(){
backlightTimedOut = 1;
}
@@ -178,13 +233,15 @@
bool readInProgress = false;
int currentReadIndex = 0;
-void wifiCallback() {
+void wifiCallback() {
char c = wifi.getc();
+
if (c == '*') {
readInProgress = !readInProgress;
wifiData[currentReadIndex] = '\0';
currentReadIndex = 0;
- wifiDataReady = true;
+ if (readInProgress == false)
+ wifiDataReady = true;
} else if (readInProgress) {
wifiData[currentReadIndex++] = c;
}
@@ -208,6 +265,7 @@
while (!wifiDataReady && t <= timeout){
wait(0.01f);
}
+
pc.printf("http GET trying #%d\r\n", retry);
if (wifiDataReady)
break;
@@ -217,108 +275,141 @@
//Synchronization
time_t next_sync = 0;
+time_t last_sync = 0;
bool sync_in_progress = false;
-time_t next_alarm = (time_t)-1; //TODO: bardzo brzydki hack
time_t getNextSync(){
//TODO: zmiennej czasu nie powinno sie chyba tak modyfikowac
- return time (NULL) + 123;
+ return time (NULL) + 23;
}
-//Reads are blocking now, so we need to put it into a different thread
-void syncThreadFunction(void const* args){
+int syncFunction(){
+ disp.sync_in_progress = 1;
+ last_sync = time(NULL);
std::string time_string = httpGETWithRetry("GET "
"/time/current/ "
"HTTP/1.1\r\n"
- "Host: 10.1.8.202:8080\r\n\r\n", 5.0, 5);
+ "Host: 10.1.8.202:8080\r\n\r\n", 2.0, 5);
if (time_string == ""){
- lcd.locate(0,1);
- lcd.printf("Blad synchroniz."); //TODO: to nie bedzie dzialac, trzeba przekazac te dane do obiektu disp
+ //TODO: błąd synchronizacji
}
else {
set_time(atoi(time_string.c_str()));
}
time_string = httpGETWithRetry("GET "
- "/alarm/latest/ "
+ "/alarm/get/nearest/id/5881e409e93a2218d42fe888 "
"HTTP/1.1\r\n"
- "Host: 10.1.8.202:8080\r\n\r\n", 5.0, 5); //TODO: Jaki endpoint do alarmow?
+ "Host: 10.1.8.202:8080\r\n\r\n", 2.0, 5);
if (time_string == ""){
- lcd.locate(0,1);
- lcd.printf("Blad synchroniz.");
}
else {
next_alarm = atoi(time_string.c_str());
}
+ time_t now;
+ time(&now);
+ char time_str[50];
+ strftime(time_str, 50, "%FT%TZ", gmtime(&now));
+
+ //Get light sensor data
+ double light_sensor_avg;
+ light_sensor_avg = light_samples == 0 ? 0 : light_sum / light_samples ;
+ light_sum = 0;
+ light_samples = 0;
+
+ wifi.printf("POST "
+ "/alarm/get/nearest/id/5881e409e93a2218d42fe888 "
+ "HTTP/1.1\r\n"
+ "Host: 10.1.8.202:8080\r\n\r\n"
+ "{"
+ "\"date\":\"%s\""
+ "\"value\":%f"
+ "\"device_id\":\"5881e409e93a2218d42fe888\""
+ "\"type\":\"light\""
+ "}\r\n\r\n", time_str, light_sensor_avg);
next_sync = getNextSync();
- sync_in_progress = false;
+ return 0;
}
//Alarm
-PwmOut sound(D2);
+PwmOut sound(D13);
bool alarm_playing = false;
bool alarm_stopped = false;
-//We probably could do sound playback with timers and whatnot
-//but why when we have THREADS!
-void alarmThreadFunction(void const* args){
- //TODO: opcja wyboru dzwonka? whatever, i tak tego nie dokonczymy
- const int* freq = axelf_freq;
- const int* per = axelf_per;
- float bpm = 100.0f; //tempo
- alarm_stopped = false;
- while (!alarm_stopped){
- float base_period = 0.5f;
- float base_time = bpm / 60.0f;
- for (int i = 0; i < 100; i++){ //TODO: no bounds checking, -1 sentinel at the end required
- if (per[i] == -1)
- break;
- if (freq[i] != 0) {
- sound.period(base_period/freq[i]);
- sound = 0.5f;
- }
- else {
- sound = 0.0f;
- }
- wait(base_time/per[i]);
- }
+const int* freq = axelf_freq;
+const int* per = axelf_per;
+int next_note = 0;
+
+void play_next_note();
+Timeout next_note_timeout;
+
+void start_alarm(){
+ disp.alarm_on = 1;
+ alarm_playing = true;
+ next_note = 0;
+ next_note_timeout.attach(&play_next_note, 0.01);
+}
+
+void stop_alarm(){
+ next_alarm = 0;
+ alarm_playing = false;
+ disp.alarm_on = 0;
+ sound = 0.0f;
+}
+
+//TODO: won't work if melody contains -1 per at the beginning, has to have at least one note
+void play_next_note(){
+ if (!alarm_playing)
+ return;
+
+ const float bpm = 100.0f; //tempo
+ const float base_period = 0.5f;
+ const float base_time = bpm / 60.0f;
+
+ if (per[next_note] <= 0)
+ next_note = 0;
+
+ if (freq[next_note] != 0) {
+ sound.period(base_period/freq[next_note]);
+ sound = 0.5f;
+ }
+ else {
sound = 0.0f;
}
- alarm_playing = false;
+
+ next_note++;
+ next_note_timeout.attach(&play_next_note, base_time/per[next_note]);
}
-Ticker display_update_ticker;
int main() {
- set_time(1256729737); //DEBUG: Set RTC time to Wed, 28 Oct 2009 11:35:37
+ wifi.baud(115200);
+ wifi.attach(&wifiCallback);
//Initialization
disp.backlightOn();
button.rise(&userButtonPress);
button.fall(&userButtonRelease);
- wifi.baud(115200);
- wifi.attach(&wifiCallback);
-
pc.printf("Waiting for time\r\n");
std::string time_string = httpGETWithRetry("GET "
"/time/current/ "
"HTTP/1.1\r\n"
- "Host: 10.1.8.202:8080\r\n\r\n", 5.0, 5);
+ "Host: 10.4.8.136:8080\r\n\r\n", 5.0, 5);
- pc.printf("Get time returned >>%s<<", time_string.c_str());
+ pc.printf("Get time returned >>%s<< %d\r\n", time_string.c_str());
if (time_string == ""){
lcd.locate(0,1); //Put in top row
lcd.printf("Blad synchroniz.");
wait(1);
+ set_time(1256729737); //DEBUG: Set RTC time to Wed, 28 Oct 2009 11:35:37
}
else {
set_time(atoi(time_string.c_str()));
}
initRadio(6, NRF24L01P_TX_PWR_ZERO_DB, NRF24L01P_DATARATE_250_KBPS);
- Thread radio_thread(radio_recv);
while (1){
pc.printf("ok\r\n");
@@ -335,9 +426,13 @@
userButtonTimer.stop();
if (userButtonTimer.read_ms() > userButtonLongPress){
pc.printf("User button long pressed");
- //disp.backlightOff(); //that was just debug code anyway
+ disp.backlightOff(); //that was just debug code anyway
if (alarm_playing){
- alarm_stopped = true;
+ stop_alarm();
+ }
+ else {
+ //Force synchronization
+ next_sync = time(NULL);
}
}
else {
@@ -352,22 +447,35 @@
disp.backlightOff();
}
+ if (time(NULL) >= next_light){
+ lightSensor();
+ }
+
//Synchronize with server
- if (time(NULL) >= next_sync && !sync_in_progress){
- sync_in_progress = true;
- Thread sync_thread(syncThreadFunction);
+ if (time(NULL) >= next_sync){
+ disp.sync_in_progress = 1;
+ disp.update();
+ syncFunction();
+ disp.sync_in_progress = 0;
+ disp.update();
}
//Check if alarm should be played
- if (time(NULL) >= next_alarm && !alarm_playing){
- alarm_playing = true;
- Thread alarm_thread(alarmThreadFunction);
+ if (next_alarm != 0 && !alarm_playing){
+ if (time(NULL) >= next_alarm-(15*60) ){ //Hardcoded to 15 minutes before set time
+ if (movement_detected || time(NULL) >= next_alarm){
+ start_alarm();
+ }
+ }
}
+ //Try to receive from radio
+ radio_recv();
+
//Updating display
disp.update();
- Thread::wait(100);
+ wait_ms(100);
};
}

