diff --git a/firmware/config.h b/firmware/config.h
index 1a81adb..4b4ddd5 100644
--- a/firmware/config.h
+++ b/firmware/config.h
@@ -5,14 +5,17 @@
#define light_name "Dimmable Hue Light" //default light name
-#define LIGHTS_COUNT 4 // do not modify because luminie p30 only ha 4 channel
+#define LIGHTS_COUNT 4 // do not modify because luminie p30 only has 4 channel, never set above 80
-#define EEPROM_LAST_STATE_STARTUP_ADDRESS 0 // startup behavior is used for all lights
-#define EEPROM_SCENE_ADDRESS 1 // scene is used for all of the lights
-#define EEPROM_LAST_STATE_ADDRESS 2 // the first "last state" information for the first light
-#define EEPROM_TIMING_CONTROL_ENABLED_ADDRESS 3 // the first "last state" information for the first light
-#define EEPROM_DYNAMIC_IP_ADDRESS 4
-#define EEPROM_LAST_DEFAULT_BLOCK_ADDRESS 20
-#define EEPROM_TIMING_DATA_ADDRESS (EEPROM_TIMING_CONTROL_ENABLED_ADDRESS + LIGHTS_COUNT) // Stored data date per light ELE_USED; HH; MM; CH1; CH2; CH3; CH4;
+#define EEPROM_LAST_STATE_STARTUP_ADDRESS 0 // startup behavior is used for all lights
+#define EEPROM_SCENE_ADDRESS 1 // scene is used for all of the lights
+#define EEPROM_TIMING_CONTROL_ENABLED_ADDRESS 2
+#define EEPROM_DYNAMIC_IP_ADDRESS 3
+#define EEPROM_LAST_STATE_ADDRESS 4 // the first "last state" information for the first light
+#define EEPROM_TIMING_DATA_ADDRESS (EEPROM_LAST_STATE_ADDRESS + LIGHTS_COUNT) // Stored data date per light ELE_USED; HH; MM; CH1; CH2; CH3; CH4;
-#define TC_TIME_CHECK_INTERVAL_MS 600000
+#define TIME_CHECK_INTERVAL_MS (10000UL) // 600000
+
+#define MY_NTP_SERVER "de.pool.ntp.org"
+
+#define DISABLE_WEB_CONTROL
diff --git a/firmware/firmware.ino b/firmware/firmware.ino
index 937cc3a..b07c7d9 100644
--- a/firmware/firmware.ino
+++ b/firmware/firmware.ino
@@ -35,10 +35,11 @@ IPAddress subnet_mask( 255, 255, 255, 0);
#define SCENE_NIGHTLY 2
// 10 bit PWM
-#define PWM_OFF 0 // 0V
-#define PWM_MIN 640 // 15V - minimum light amount (~1%)
-#define PWM_MAX 1023 // 24V - maximum light amount (100%)
-#define PWM_INC 4 // 24V-15V = 9V range; 9V ≙ 1024/640 = 383 counts; 383/100% = 3,83 counts (1%) / % => round up 4 counts / % (~1%)
+#define PWM_OFF 0 // 0V
+#define PWM_MIN 640 // 15V - minimum light amount (~1%)
+#define PWM_MAX 1023 // 24V - maximum light amount (100%)
+#define PWM_INC 4 // 24V-15V = 9V range; 9V ≙ 1024/640 = 383 counts; 383/100% = 3,83 counts (1%) / % => round up 4 counts / % (~1%)
+#define BRI_TO_PWM_FACTOR 4 // 0-255 uint8_t brightness data x4 is 0 to 1024
//********************************//
@@ -127,7 +128,6 @@ void lightEngine()
{
delay(6);
in_transition = false;
-
}
}
@@ -232,13 +232,13 @@ void setup()
init_webserver();
-
-
tc_init();
server.begin();
} // end of setup
+//********************************//
+
void loop()
{
server.handleClient();
@@ -250,6 +250,8 @@ void loop()
}
}
+//********************************//
+
void handleNotFound()
{
String message = "File Not Found\n\n";
@@ -268,9 +270,13 @@ void handleNotFound()
server.send(404, "text/plain", message);
}
+//********************************//
+
void init_webserver()
{
- server.on("/state", HTTP_PUT, []()
+
+#ifndef DISABLE_WEB_CONTROL
+ server.on("/state", HTTP_PUT, []()
{ // HTTP PUT request used to set a new light state
DynamicJsonDocument root(1024);
DeserializationError error = deserializeJson(root, server.arg("plain"));
@@ -360,8 +366,12 @@ void init_webserver()
server.send(200, "text/plain", output);
});
+#endif // DISABLE_WEB_CONTROL
+
server.on("/", []()
{
+
+#ifndef DISABLE_WEB_CONTROL
static float transitiontime = 4.0;
if (server.hasArg("transition"))
@@ -376,10 +386,21 @@ void init_webserver()
if (EEPROM.read(EEPROM_LAST_STATE_STARTUP_ADDRESS) != startup)
{
EEPROM.write(EEPROM_LAST_STATE_STARTUP_ADDRESS, startup);
+
+ for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
+ {
+ uint8_t tmp = (light_state[i] == true ? LIGHT_STATE_ON : LIGHT_STATE_OFF);
+ if (EEPROM.read(EEPROM_LAST_STATE_ADDRESS + i) != tmp)
+ {
+ EEPROM.write(EEPROM_LAST_STATE_ADDRESS + i, tmp);
+ }
+ }
+
EEPROM.commit();
Serial.print("Startup behavior set to "); Serial.println(EEPROM.read(EEPROM_LAST_STATE_STARTUP_ADDRESS));
}
}
+#endif // DISABLE_WEB_CONTROL
// timing controller switch handling
if (server.hasArg("tc"))
@@ -412,6 +433,8 @@ void init_webserver()
}
}
+#ifndef DISABLE_WEB_CONTROL
+
// scene switch handling
if (server.hasArg("scene"))
{
@@ -425,6 +448,18 @@ void init_webserver()
}
+ if (server.hasArg("dip"))
+ {
+ uint8_t tmp = EEPROM.read(EEPROM_DYNAMIC_IP_ADDRESS);
+ uint8_t tmp2 = (server.arg("dip") == "true" ? 1 : 0);
+ if (tmp != tmp2)
+ {
+ EEPROM.write(EEPROM_DYNAMIC_IP_ADDRESS, tmp2);
+ EEPROM.commit();
+ Serial.print("Set dynamic IP to "); Serial.println(EEPROM.read(EEPROM_DYNAMIC_IP_ADDRESS));
+ }
+ }
+
// process the received data for every light
for (int light = 0; light < LIGHTS_COUNT; light++)
{
@@ -439,24 +474,25 @@ void init_webserver()
if (server.hasArg("on" + (String)light))
{
uint8_t tmp = EEPROM.read(EEPROM_LAST_STATE_STARTUP_ADDRESS);
- if (server.arg("on" + (String)light) == "true")
+ if (server.arg("on" + (String)light) == "true" && light_state[light] == false)
{
light_state[light] = true;
if (tmp == 0 && EEPROM.read(EEPROM_LAST_STATE_ADDRESS + light) == 0)
{
EEPROM.write(EEPROM_LAST_STATE_ADDRESS + light, LIGHT_STATE_ON);
}
+ Serial.print("Light "); Serial.print(light); Serial.print(" state set to "); Serial.println(light_state[light]);
- } else {
+ } else if (server.arg("on" + (String)light) == "false" && light_state[light] == true)
+ {
light_state[light] = false;
if (tmp == 0 && EEPROM.read(EEPROM_LAST_STATE_ADDRESS + light) == 1)
{
EEPROM.write(EEPROM_LAST_STATE_ADDRESS + light, LIGHT_STATE_OFF);
}
+ Serial.print("Light "); Serial.print(light); Serial.print(" state set to "); Serial.println(light_state[light]);
}
- Serial.print("Light "); Serial.print(light); Serial.print(" state set to "); Serial.println(light_state[light]);
-
EEPROM.commit();
}
@@ -464,7 +500,6 @@ void init_webserver()
// start alerting for every light
if (server.hasArg("alert"))
{
-
if (light_state[light])
{
current_bri[light] = 0;
@@ -474,7 +509,7 @@ void init_webserver()
}
- // switch the light
+ // set the light step level
if (light_state[light])
{
step_level[light] = ((float)bri[light] - current_bri[light]) / transitiontime;
@@ -484,6 +519,8 @@ void init_webserver()
}
}
+#endif // DISABLE_WEB_CONTROL
+
if (server.hasArg("resettc"))
{ // reqrite the tc config and reboot
tc_write_default();
@@ -507,57 +544,28 @@ void init_webserver()
http_content += "";
http_content += "
";
http_content += "";
http_content += "";
http_content += "";
diff --git a/firmware/timing_control.ino b/firmware/timing_control.ino
index 85febe6..4667a8b 100644
--- a/firmware/timing_control.ino
+++ b/firmware/timing_control.ino
@@ -1,6 +1,6 @@
-
-#include
+#include
#include
+#include
#include "config.h"
@@ -22,14 +22,15 @@
#define ENSTATE_DISABLED 0
//***********************************//
+/* Globals */
-const long utcOffsetInSeconds = 3600; // Europe/Berlin (not summer time)
+uint32_t tc_last_check = 0;
+
+const long updateInterval = 60000;
+const long utcOffsetInSeconds = 3600;
-// Define NTP Client to get time
WiFiUDP ntpUDP;
-NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
-
-static uint32_t tc_last_time_check;
+NTPClient timeClient(ntpUDP, MY_NTP_SERVER, utcOffsetInSeconds, updateInterval);
struct tc_data_st {
uint8_t enstate;
@@ -61,13 +62,6 @@ uint8_t example_timer_data_block[] = {
void tc_init()
{
- while ( WiFi.status() != WL_CONNECTED )
- {
- delay ( 500 );
- Serial.print ( "." );
- }
-
- timeClient.begin();
if (tc_check_no_data_block() == true)
{
@@ -75,79 +69,42 @@ void tc_init()
tc_write_default();
}
- //Serial.println("TC: Read data block from eeprom");
+ while ( WiFi.status() != WL_CONNECTED )
+ {
+ delay (500);
+ Serial.print ( "." );
+ }
+
+ tc_last_check = millis();
+
+ timeClient.begin();
+
+ Serial.println("TC: Read data block from eeprom");
tc_readConfig();
- tc_last_time_check = millis();
}
-void tc_readConfig()
-{
- for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++)
- {
- /*Serial.print("Reading from address: "); Serial.print(EEPROM_TIMING_DATA_ADDRESS);
- Serial.print(" + (");
- Serial.print(i);
- Serial.print(" * ");
- Serial.print(LENGTH_OF_TIMER_DATA_BLOCK);
- Serial.print(") + ");
- Serial.println(TIMER_DATA_ENSTATE);*/
-
- tc_data[i].enstate = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_ENSTATE);
- tc_data[i].hh = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_HH);
- tc_data[i].mm = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_MM);
- tc_data[i].ch1 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH1);
- tc_data[i].ch2 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH2);
- tc_data[i].ch3 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH3);
- tc_data[i].ch4 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH4);
-
- /*Serial.print("data block: "); Serial.print(i);
- Serial.print(" @ ");
- Serial.println((EEPROM_TIMING_DATA_ADDRESS + (i * LENGTH_OF_TIMER_DATA_BLOCK) + TIMER_DATA_ENSTATE));
-
- Serial.print(" es: "); Serial.println(tc_data[i].enstate);
- Serial.print(" hh: "); Serial.println(tc_data[i].hh);
- Serial.print(" mm: "); Serial.println(tc_data[i].mm);
- Serial.print(" ch1: "); Serial.println(tc_data[i].ch1);
- Serial.print(" ch2: "); Serial.println(tc_data[i].ch2);
- Serial.print(" ch3: "); Serial.println(tc_data[i].ch3);
- Serial.print(" ch4: "); Serial.println(tc_data[i].ch4);*/
- }
-}
-
-void tc_updateTime()
-{
- timeClient.update();
-
- Serial.print("Local time: ");
- Serial.print(timeClient.getHours());
- Serial.print(":");
- Serial.println(timeClient.getMinutes());
-
-}
+//********************************//
void tc_update()
{
uint8_t target_data_block = 255;
- if (millis() > tc_last_time_check + TC_TIME_CHECK_INTERVAL_MS)
- {
- tc_last_time_check = millis();
- tc_updateTime();
- }
+ tc_updateTime();
if ((timeClient.getMinutes() % 10) != 0)
{
return; // only run every 10 minutes
}
- //tc_updateTime();
-
// 2. find current active time slot
for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS-1; i++)
{
- if (tc_data[i].hh == timeClient.getHours() && tc_data[i].mm == timeClient.getMinutes() && tc_data[i].enstate == ENSTATE_ENABLED)
- { // we have a new time data slot reached
+ if (tc_data[i].hh == timeClient.getHours() &&
+ tc_data[i].mm == timeClient.getMinutes() &&
+ tc_data[i].enstate == ENSTATE_ENABLED)
+ {
+ // we have a new time data slot reached
for (uint8_t j = i+1; j < NUMBER_OF_TIMER_DATA_BLOCKS; j++)
{ // search for the next enabled successor
if (tc_data[j].enstate == ENSTATE_ENABLED)
@@ -190,6 +147,60 @@ void tc_update()
}
+//********************************//
+
+void tc_updateTime()
+{
+ if (timeClient.update())
+ {
+ Serial.println("TC: Reading time from server...");
+ Serial.println(timeClient.getFormattedTime());
+
+ Serial.print("Local time: ");
+ Serial.print(timeClient.getHours());
+ Serial.print(":");
+ Serial.println(timeClient.getMinutes());
+ }
+}
+
+//********************************//
+
+void tc_readConfig()
+{
+ for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++)
+ {
+ /*Serial.print("Reading from address: "); Serial.print(EEPROM_TIMING_DATA_ADDRESS);
+ Serial.print(" + (");
+ Serial.print(i);
+ Serial.print(" * ");
+ Serial.print(LENGTH_OF_TIMER_DATA_BLOCK);
+ Serial.print(") + ");
+ Serial.println(TIMER_DATA_ENSTATE);*/
+
+ tc_data[i].enstate = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_ENSTATE);
+ tc_data[i].hh = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_HH);
+ tc_data[i].mm = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_MM);
+ tc_data[i].ch1 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH1);
+ tc_data[i].ch2 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH2);
+ tc_data[i].ch3 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH3);
+ tc_data[i].ch4 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH4);
+
+ /*Serial.print("data block: "); Serial.print(i);
+ Serial.print(" @ ");
+ Serial.println((EEPROM_TIMING_DATA_ADDRESS + (i * LENGTH_OF_TIMER_DATA_BLOCK) + TIMER_DATA_ENSTATE));
+
+ Serial.print(" es: "); Serial.println(tc_data[i].enstate);
+ Serial.print(" hh: "); Serial.println(tc_data[i].hh);
+ Serial.print(" mm: "); Serial.println(tc_data[i].mm);
+ Serial.print(" ch1: "); Serial.println(tc_data[i].ch1);
+ Serial.print(" ch2: "); Serial.println(tc_data[i].ch2);
+ Serial.print(" ch3: "); Serial.println(tc_data[i].ch3);
+ Serial.print(" ch4: "); Serial.println(tc_data[i].ch4);*/
+ }
+}
+
+//********************************//
+
void tc_write_default()
{
//Serial.print("-----\nWrite data block starting from address EEPROM_TIMING_DATA_ADDRESS = "); Serial.println(EEPROM_TIMING_DATA_ADDRESS);
@@ -205,6 +216,8 @@ void tc_write_default()
//Serial.println("-----");
}
+//********************************//
+
bool tc_check_no_data_block()
{
//Serial.print("Check data block address EEPROM_TIMING_DATA_ADDRESS = "); Serial.println(EEPROM_TIMING_DATA_ADDRESS);
@@ -217,3 +230,5 @@ bool tc_check_no_data_block()
}
return false;
}
+
+//********************************//