Compare commits
6 commits
60334d3109
...
ba5a888e32
Author | SHA1 | Date | |
---|---|---|---|
|
ba5a888e32 | ||
|
32bc51caaa | ||
|
30d00827f9 | ||
|
e62d85fbd6 | ||
|
cc88a0de0b | ||
|
bdf6765687 |
7 changed files with 60 additions and 28 deletions
18
README.md
18
README.md
|
@ -1,14 +1,16 @@
|
||||||
This project is based on: https://github.com/mariusmotea/diyHue/tree/master/Lights/Arduino/Generic_Dimmable_Light
|
This project is based on: https://github.com/mariusmotea/diyHue/tree/master/Lights/Arduino/Generic_Dimmable_Light
|
||||||
|
|
||||||
Most of the code was generated by ChatGPT.
|
Reef2Reef forum thread: https://www.reef2reef.com/threads/for-lumini-lominie-pixie-30-p30-hers-how-to-add-ramp-up-down-and-timer-with-memory-quite-cheaply.935409/
|
||||||
|
|
||||||
|
Most of the code was generated by ChatGPT and adapted by myself.
|
||||||
|
|
||||||
The controller I use is a old NodeMCU v1.0, which is connected to 4x D4184 MOS breakout boards. See NodeMCU pins table beyond.
|
The controller I use is a old NodeMCU v1.0, which is connected to 4x D4184 MOS breakout boards. See NodeMCU pins table beyond.
|
||||||
The cable I use is a https://amzn.eu/d/0jigRCh. I cut it in half and attached it to the MOS boards.
|
The cable I use is a https://amzn.eu/d/0jigRCh. I cut it in half and attached it to the MOS boards.
|
||||||
|
|
||||||
The NodeMCU‘s power supply is a 7805, it‘s output is connected to the Vin pin.
|
The NodeMCU‘s power supply is a 7805, it‘s output is connected to the Vin pin of the NodeMCU.
|
||||||
The input of the 7805 is connected to the 24V of the DC power plug.
|
The input of the 7805 is connected to the 24V of the DC power plug.
|
||||||
|
|
||||||
NodeMCU pins:
|
NodeMCU pin connections to the cable wires:
|
||||||
|
|
||||||
| |ch1|ch2|ch3|ch4|
|
| |ch1|ch2|ch3|ch4|
|
||||||
|--|--|--|--|--|
|
|--|--|--|--|--|
|
||||||
|
@ -20,11 +22,21 @@ NodeMCU pins:
|
||||||
The HTML content is pushed to the NodeMCU separetely by using the ESP8266 Sketch Data Upload plugin of the old Arduino IDE (not "Arduino IDE").
|
The HTML content is pushed to the NodeMCU separetely by using the ESP8266 Sketch Data Upload plugin of the old Arduino IDE (not "Arduino IDE").
|
||||||
|
|
||||||
After the firmware is written the first time to the NodeMCU.
|
After the firmware is written the first time to the NodeMCU.
|
||||||
|
|
||||||
|
In case there is no data folder available in the firmware folder create it.
|
||||||
|
Open a unix style commandline with a bash and step unto the data folder. Run the script
|
||||||
|
|
||||||
|
$ bash ../../tools/html_gen_files.sh
|
||||||
|
|
||||||
|
This generates all of the required files and places them into the data folder.
|
||||||
|
|
||||||
The EEPROM's default values are set to default.
|
The EEPROM's default values are set to default.
|
||||||
All except of the timing control data block.
|
All except of the timing control data block.
|
||||||
|
|
||||||
You have to click at the link "reset timing control data" on the webinterface.
|
You have to click at the link "reset timing control data" on the webinterface.
|
||||||
|
|
||||||
|
The IP address is set to dynamic (DHCP) after initial flash of the NodeMCU.
|
||||||
|
|
||||||
Sample schematics (no NodeMCU pins defined in there)
|
Sample schematics (no NodeMCU pins defined in there)
|
||||||
|
|
||||||
![Sample schematics](pic/schematics.png)
|
![Sample schematics](pic/schematics.png)
|
||||||
|
|
Binary file not shown.
BIN
firmware/20230515_firmware.spiffs.bin
Normal file
BIN
firmware/20230515_firmware.spiffs.bin
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 MiB |
Binary file not shown.
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#define DEVELOPMENT
|
#define DEVELOPMENT
|
||||||
|
|
||||||
#define LIGHT_NAME_STR "Dimmable Hue Light" // default light name
|
#define LIGHT_NAME_STR "Lumini/Lominie Pixie30/P30 light control" // default light name
|
||||||
|
|
||||||
#define LIGHTS_COUNT 4 // do not modify because luminie p30 only has 4 channel, never set above 80
|
#define LIGHTS_COUNT 4 // do not modify because luminie p30 only has 4 channel, never set above 80
|
||||||
|
|
||||||
|
|
|
@ -64,10 +64,9 @@ void lightEngine()
|
||||||
//Serial.println("Reached target bri[" + (String)i + "] = " + (String)bri[i]);
|
//Serial.println("Reached target bri[" + (String)i + "] = " + (String)bri[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t tmp_pwm = calcPWM(current_bri[i]);
|
current_pwm[i] = calcPWM(current_bri[i]);
|
||||||
current_pwm[i] = tmp_pwm;
|
|
||||||
//Serial.println("lon: pin" + (String)i + " = PWM(" + (String)tmp_pwm + ")");
|
//Serial.println("lon: pin" + (String)i + " = PWM(" + (String)tmp_pwm + ")");
|
||||||
analogWrite(pins[i], tmp_pwm);
|
analogWrite(pins[i], current_pwm[i]);
|
||||||
}
|
}
|
||||||
} else { // light state is off
|
} else { // light state is off
|
||||||
|
|
||||||
|
@ -82,10 +81,9 @@ void lightEngine()
|
||||||
//Serial.println("Reached target bri[" + (String)i + "] = " + (String)bri[i]);
|
//Serial.println("Reached target bri[" + (String)i + "] = " + (String)bri[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t tmp_pwm = calcPWM(current_bri[i]);
|
current_pwm[i] = calcPWM(current_bri[i]);
|
||||||
current_pwm[i] = tmp_pwm;
|
|
||||||
//Serial.println("loff: pin" + (String)i + " = PWM(" + (String)tmp_pwm + ")");
|
//Serial.println("loff: pin" + (String)i + " = PWM(" + (String)tmp_pwm + ")");
|
||||||
analogWrite(pins[i], tmp_pwm);
|
analogWrite(pins[i], current_pwm[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,12 +142,13 @@ void tc_update_loop()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((timeClient.getMinutes() % 10) != 0 || last_min_check == timeClient.getMinutes()) // && tc_testOngoing == false
|
if ((minute() % 10) != 0 || last_min_check == minute()) // && tc_testOngoing == false
|
||||||
{
|
{
|
||||||
last_min_check = timeClient.getMinutes();
|
|
||||||
return; // only run every 10 minutes
|
return; // only run every 10 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_min_check = minute();
|
||||||
|
|
||||||
tc_update_main();
|
tc_update_main();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,12 +163,18 @@ void tc_update_main()
|
||||||
|
|
||||||
tc_updateTime();
|
tc_updateTime();
|
||||||
|
|
||||||
|
// calculate the current time as minutes
|
||||||
|
uint16_t time_now = (((uint16_t)hour()) * 60) + minute();
|
||||||
|
|
||||||
// search for the current active time slot
|
// search for the current active time slot
|
||||||
for (int i = NUMBER_OF_TIMER_DATA_BLOCKS-1; i >= 0 && target_data_block == 255; --i)
|
for (int i = NUMBER_OF_TIMER_DATA_BLOCKS-1; i >= 0 && target_data_block == 255; --i)
|
||||||
{
|
{
|
||||||
//Serial.println((String)i + " - " + (String)tc_data[i].hh + ":" + (String)tc_data[i].mm);
|
//Serial.println((String)i + " - " + (String)tc_data[i].hh + ":" + (String)tc_data[i].mm);
|
||||||
|
|
||||||
if (((tc_data[i].hh * 60) + tc_data[i].mm) <= ((hour() * 60) + minute()))
|
// calculate the time of the data block to minutes
|
||||||
|
uint16_t time_tc_data = (((uint16_t)tc_data[i].hh) * 60) + tc_data[i].mm;
|
||||||
|
|
||||||
|
if (time_now >= time_tc_data)
|
||||||
{
|
{
|
||||||
target_data_block = i+1; // found the next block to load
|
target_data_block = i+1; // found the next block to load
|
||||||
//Serial.println((String)i + " => " + target_data_block);
|
//Serial.println((String)i + " => " + target_data_block);
|
||||||
|
@ -179,14 +186,13 @@ void tc_update_main()
|
||||||
// no new predecessor or successor found, start over
|
// no new predecessor or successor found, start over
|
||||||
current_target_data_block = 255;
|
current_target_data_block = 255;
|
||||||
|
|
||||||
Serial.println("No predecessor or successor found, start over...");
|
Serial.println("No predecessor or successor found.");
|
||||||
|
|
||||||
// disable the lights
|
// disable the lights
|
||||||
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
||||||
{
|
{
|
||||||
bri[i] = 0;
|
bri[i] = 0;
|
||||||
current_bri[i] = 0;
|
current_bri[i] = 1; // set it to a value to force the light engine to fix the current brightness
|
||||||
current_pwm[i] = 0;
|
|
||||||
transitiontime[i] = default_transitiontime;
|
transitiontime[i] = default_transitiontime;
|
||||||
process_lightdata(i, transitiontime[i]);
|
process_lightdata(i, transitiontime[i]);
|
||||||
}
|
}
|
||||||
|
@ -212,8 +218,7 @@ void tc_update_main()
|
||||||
{
|
{
|
||||||
light_state[i] = false;
|
light_state[i] = false;
|
||||||
bri[i] = 0;
|
bri[i] = 0;
|
||||||
current_bri[i] = 0;
|
current_bri[i] = 1; // set it to a value to force the light engine to fix the current brightness
|
||||||
current_pwm[i] = 0;
|
|
||||||
transitiontime[i] = default_transitiontime;
|
transitiontime[i] = default_transitiontime;
|
||||||
process_lightdata(i, transitiontime[i]);
|
process_lightdata(i, transitiontime[i]);
|
||||||
}
|
}
|
||||||
|
@ -249,21 +254,23 @@ void tc_update_main()
|
||||||
bri[1] = tc_data[target_data_block].ch2;
|
bri[1] = tc_data[target_data_block].ch2;
|
||||||
bri[2] = tc_data[target_data_block].ch3;
|
bri[2] = tc_data[target_data_block].ch3;
|
||||||
bri[3] = tc_data[target_data_block].ch4;
|
bri[3] = tc_data[target_data_block].ch4;
|
||||||
|
|
||||||
|
// make sure that the current brightness is correct
|
||||||
if (tc_data[target_data_block-1].ch1 != current_bri[0])
|
if (tc_data[target_data_block-1].ch1 != current_bri[0])
|
||||||
{
|
{
|
||||||
current_bri[0] = tc_data[target_data_block-1].ch1 + ((tc_data[target_data_block].ch1 == 0) ? 1 : -1);
|
current_bri[0] = tc_data[target_data_block-1].ch1;
|
||||||
}
|
}
|
||||||
if (tc_data[target_data_block-1].ch2 != current_bri[1])
|
if (tc_data[target_data_block-1].ch2 != current_bri[1])
|
||||||
{
|
{
|
||||||
current_bri[1] = tc_data[target_data_block-1].ch2 + ((tc_data[target_data_block].ch2 == 0) ? 1 : -1);
|
current_bri[1] = tc_data[target_data_block-1].ch2;
|
||||||
}
|
}
|
||||||
if (tc_data[target_data_block-1].ch3 != current_bri[2])
|
if (tc_data[target_data_block-1].ch3 != current_bri[2])
|
||||||
{
|
{
|
||||||
current_bri[2] = tc_data[target_data_block-1].ch3 + ((tc_data[target_data_block].ch3 == 0) ? 1 : -1);
|
current_bri[2] = tc_data[target_data_block-1].ch3;
|
||||||
}
|
}
|
||||||
if (tc_data[target_data_block-1].ch4 != current_bri[3])
|
if (tc_data[target_data_block-1].ch4 != current_bri[3])
|
||||||
{
|
{
|
||||||
current_bri[3] = tc_data[target_data_block-1].ch4 + ((tc_data[target_data_block].ch4 == 0) ? 1 : -1);
|
current_bri[3] = tc_data[target_data_block-1].ch4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
||||||
|
@ -283,24 +290,34 @@ void tc_update_main()
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the transition time
|
// set the transition time
|
||||||
int t_time = 0;
|
int t_time = default_transitiontime;
|
||||||
if (target_data_block > 0)
|
if (target_data_block > 0)
|
||||||
{
|
{
|
||||||
// hours as seconds from now on to the next enabled block
|
// hours as seconds from now on to the next enabled block
|
||||||
t_time = ((uint16_t)tc_data[target_data_block].hh * 60 * 60) - ((uint16_t)hour() * 60 * 60);
|
t_time = ((uint32_t)tc_data[target_data_block].hh * 60 * 60) - ((uint32_t)hour() * 60 * 60);
|
||||||
// add the left over seconds to the next enabled block
|
// add the left over seconds to the next enabled block
|
||||||
t_time += ((uint16_t)tc_data[target_data_block].mm * 60) - ((uint16_t)minute() * 60);
|
t_time += ((uint16_t)tc_data[target_data_block].mm * 60) - ((uint16_t)minute() * 60);
|
||||||
|
|
||||||
|
if (t_time <= 0)
|
||||||
|
{
|
||||||
|
t_time = 1; // 0 could lead to a division by zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
||||||
|
{
|
||||||
|
transitiontime[i] = t_time;
|
||||||
}
|
}
|
||||||
transitiontime[0] = t_time;
|
|
||||||
transitiontime[1] = t_time;
|
|
||||||
transitiontime[2] = t_time;
|
|
||||||
transitiontime[3] = t_time;
|
|
||||||
|
|
||||||
// calculate the step level
|
// calculate the step level
|
||||||
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
||||||
{
|
{
|
||||||
process_lightdata(i, transitiontime[i]);
|
process_lightdata(i, transitiontime[i]);
|
||||||
|
|
||||||
|
// set the PWM for the channel
|
||||||
|
current_pwm[i] = calcPWM(current_bri[i]);
|
||||||
|
//Serial.println("lon: pin" + (String)i + " = PWM(" + (String)tmp_pwm + ")");
|
||||||
|
analogWrite(pins[i], current_pwm[i]);
|
||||||
|
|
||||||
Serial.println("transitiontime[" + (String)i + "] = " + (String)transitiontime[i]);
|
Serial.println("transitiontime[" + (String)i + "] = " + (String)transitiontime[i]);
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
||||||
|
@ -528,6 +545,11 @@ void tc_jsonDataBlocksToEEPROM(String json_data_string)
|
||||||
|
|
||||||
}
|
}
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
|
|
||||||
|
// reset the prograss in the timing control engine
|
||||||
|
tc_reset();
|
||||||
|
// call the function which reads out the new set data
|
||||||
|
tc_update_main();
|
||||||
}
|
}
|
||||||
|
|
||||||
//********************************//
|
//********************************//
|
||||||
|
|
Loading…
Reference in a new issue