first commit

This commit is contained in:
Jérôme Delacotte
2025-03-06 11:15:32 +01:00
commit 7b30d6e298
5276 changed files with 2108927 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
/**
* Before uploading this sketch, check and modify the following variables
* accordingly to your hardware setup:
* - syncPin, the pin listening for AC zero cross signal
* - thyristorPin, the pin connected to the thyristor
*/
#include <dimmable_light.h>
const int syncPin = 13;
const int thyristorPin = 14;
DimmableLight light(thyristorPin);
// Delay between brightness increments, in milliseconds
const int period = 50;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: first example");
Serial.print("Initializing DimmableLight library... ");
DimmableLight::setSyncPin(syncPin);
// VERY IMPORTANT: Call this method to activate the library
DimmableLight::begin();
Serial.println("Done!");
}
void loop() {
for (int i = 0; i < 256; i++) {
light.setBrightness(i);
delay(period);
}
}

View File

@@ -0,0 +1,40 @@
/**
* An extension of the first example to demonstrate how easy is controlling multiple lights.
*/
#include <dimmable_light.h>
const int syncPin = 13;
DimmableLight light1(14);
DimmableLight light2(12);
// Delay between brightness changes, in milliseconds
const int period = 1000;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: second example");
Serial.println();
Serial.print("Initializing the dimmable light class... ");
DimmableLight::setSyncPin(syncPin);
DimmableLight::begin();
Serial.println("Done!");
}
void loop() {
light1.setBrightness(0);
light2.setBrightness(255);
delay(period);
light1.setBrightness(128);
light2.setBrightness(128);
delay(period);
light1.setBrightness(255);
light2.setBrightness(0);
delay(period);
}

View File

@@ -0,0 +1,288 @@
/**
* In this example you can see a number of effects on indipendent lights.
* To switch among the available effects, (un)comment the proper line in the setup() function.
*
* NOTE: compiles only for ESP8266 and ESP32 because the Ticker.h dependency.
*/
#include <Ticker.h>
#include <dimmable_light.h>
const int syncPin = 13;
DimmableLight l1(5);
DimmableLight l2(4);
DimmableLight l3(14);
DimmableLight l4(12);
DimmableLight l5(15);
Ticker dim;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: third example");
Serial.println();
Serial.print("Initializing the dimmable light class... ");
DimmableLight::setSyncPin(syncPin);
DimmableLight::begin();
Serial.println("Done!");
Serial.println(String("Number of instantiated lights: ") + DimmableLight::getLightNumber());
// Uncomment one and only one among the following lines to see an effect
// doEqual();
// doEqualOnOff();
// doDimSpecificStep();
// doRangeLimit();
// doNearValues();
// doDimMixed();
// doDimSweepEqual();
// doInvertedDim();
doCircularSwipe();
}
/**
* Set particular values of brightness to every light.
*/
void doEqual() {
const float period = 3;
static int briLevels[] = { 0, 1, 2, 50, 100, 150, 254, 255 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels[brightnessStep] + "/255");
l1.setBrightness(briLevels[brightnessStep]);
l2.setBrightness(briLevels[brightnessStep]);
l3.setBrightness(briLevels[brightnessStep]);
l4.setBrightness(briLevels[brightnessStep]);
l5.setBrightness(briLevels[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels) / sizeof(briLevels[0])) { brightnessStep = 0; }
dim.once(period, doEqual);
}
/**
* Turn on and off simultaneously all the bulbs.
*/
void doEqualOnOff() {
const float period = 3;
static int briLevels[] = { 0, 255 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels[brightnessStep] + "/255");
l1.setBrightness(briLevels[brightnessStep]);
l2.setBrightness(briLevels[brightnessStep]);
l3.setBrightness(briLevels[brightnessStep]);
l4.setBrightness(briLevels[brightnessStep]);
l5.setBrightness(briLevels[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels) / sizeof(briLevels[0])) { brightnessStep = 0; }
dim.once(period, doEqualOnOff);
}
/**
* Set brightness to specific values.
*/
void doDimSpecificStep(void) {
const float period = 3;
static int briLevels1[] = { 40, 200 };
static int briLevels2[] = { 60, 160 };
static int briLevels3[] = { 80, 150 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels1[brightnessStep] + " and "
+ briLevels2[brightnessStep] + " and " + briLevels3[brightnessStep] + " /255");
l1.setBrightness(briLevels1[brightnessStep]);
l2.setBrightness(briLevels2[brightnessStep]);
l3.setBrightness(briLevels3[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels1) / sizeof(briLevels1[0])) { brightnessStep = 0; }
dim.once(period, doDimSpecificStep);
}
/**
* Test a mixture between on, off and middle brightness.
*/
void doRangeLimit(void) {
const float period = 5;
static int briLevels1[] = { 0, 255 };
static int briLevels2[] = { 255, 0 };
static int briLevels3[] = { 100, 100 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels1[brightnessStep] + " and "
+ briLevels2[brightnessStep] + " and " + briLevels3[brightnessStep] + " /255");
l1.setBrightness(briLevels1[brightnessStep]);
l2.setBrightness(briLevels2[brightnessStep]);
l3.setBrightness(briLevels3[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels1) / sizeof(briLevels1[0])) { brightnessStep = 0; }
dim.once(period, doRangeLimit);
}
/**
* Test your eyes sensitivity by switching between near values. Will you see any difference?
*/
void doNearValues(void) {
const float period = 4;
static int briLevels1[] = { 70, 70 };
static int briLevels2[] = { 71, 71 };
static int briLevels3[] = { 72, 73 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels1[brightnessStep] + " and "
+ briLevels2[brightnessStep] + " and " + briLevels3[brightnessStep] + " /255");
l1.setBrightness(briLevels1[brightnessStep]);
l2.setBrightness(briLevels2[brightnessStep]);
l3.setBrightness(briLevels3[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels1) / sizeof(briLevels1[0])) { brightnessStep = 0; }
dim.once(period, doNearValues);
}
/**
* The 1st the 5th are turned off, the 3rd is fixed to half brightness, and the 2nd and 4th sweep
* in the opposite direction w.r.t. each other.
*/
void doDimMixed(void) {
const float period = 0.05;
static uint8_t brightnessStep = 1;
static bool up = true;
l1.setBrightness(brightnessStep);
int b2 = 105;
l2.setBrightness(b2);
int b3 = -((int)brightnessStep - 255);
l3.setBrightness(b3);
Serial.println(String("Dimming at: ") + brightnessStep + " " + b2 + " " + b3 + "/255");
if (brightnessStep == 255 && up) {
up = false;
} else if (brightnessStep == 0 && !up) {
up = true;
} else {
if (up) {
brightnessStep++;
} else {
brightnessStep--;
}
// Jump some steps...
// if(brightnessStep==6){
// brightnessStep=249;
// }
}
dim.once(period, doDimMixed);
}
/**
* All the lights simultaneously fade in and out.
*/
void doDimSweepEqual(void) {
const float period = 0.05;
static uint8_t brightnessStep = 1;
static bool up = true;
l1.setBrightness(brightnessStep);
l2.setBrightness(brightnessStep);
l3.setBrightness(brightnessStep);
l4.setBrightness(brightnessStep);
l5.setBrightness(brightnessStep);
Serial.println(String("Dimming at: ") + brightnessStep + "/255");
if (brightnessStep == 255 && up) {
up = false;
} else if (brightnessStep == 0 && !up) {
up = true;
} else {
if (up) {
brightnessStep++;
} else {
brightnessStep--;
}
}
dim.once(period, doDimSweepEqual);
}
/**
* The group formed by even bulbs sweep in the opposite direction w.r.t. the odd group.
*/
void doInvertedDim(void) {
const float period = 0.05;
static uint8_t brightnessStep = 1;
static bool up = true;
int oppositeBrightness = -((int)brightnessStep - 255);
l1.setBrightness(brightnessStep);
l2.setBrightness(oppositeBrightness);
l3.setBrightness(brightnessStep);
l4.setBrightness(oppositeBrightness);
l5.setBrightness(brightnessStep);
Serial.println(String("Dimming at: ") + brightnessStep + " " + oppositeBrightness + "/255");
if (brightnessStep == 255 && up) {
up = false;
} else if (brightnessStep == 0 && !up) {
up = true;
} else {
if (up) {
brightnessStep++;
} else {
brightnessStep--;
}
}
dim.once(period, doInvertedDim);
}
/**
* Turn on the light with (255/nLights) steps offset between consecutive lights.
*/
void doCircularSwipe(void) {
const float period = 0.01;
static uint16_t brightnessStep = 255;
// Alternatively, you can use the function conversionPow(..) instead conversion(..)
l1.setBrightness(triangularFunction(module(brightnessStep + 0, 512)));
l2.setBrightness(triangularFunction(module(brightnessStep + 51 * 1, 512)));
l3.setBrightness(triangularFunction(module(brightnessStep + 51 * 2, 512)));
l4.setBrightness(triangularFunction(module(brightnessStep + 51 * 3, 512)));
l5.setBrightness(triangularFunction(module(brightnessStep + 51 * 4, 512)));
brightnessStep++;
if (brightnessStep == 512) { brightnessStep = 0; }
dim.once(period, doCircularSwipe);
}
/**
* Return the module of a non-negative number (optimized).
*/
unsigned int module(unsigned int value, unsigned int max) {
if (value < max) { return value; }
return value % max;
}
/**
* Given a number in range [0; 512), return a triangular function [0;255].
*/
uint8_t triangularFunction(uint16_t value) {
int simmetricValue = 0;
if (value <= 255) { simmetricValue = value; }
if (value >= 256 && value <= 511) { simmetricValue = -value + 511; }
return simmetricValue;
}
/**
* Given a number in range [0; 512), return a "pow-ed" triangular function [0;255].
*/
uint8_t conversionPow(uint16_t value) {
int simmetricValue = 0;
if (value >= 256 && value <= 511) { simmetricValue = -value + 511; }
if (value <= 255) { simmetricValue = value; }
if (simmetricValue < 150) { return 0; }
int y = pow(simmetricValue - 150, 1.2);
if (y > 255) { return 255; }
return y;
}
void loop() {}

View File

@@ -0,0 +1,68 @@
/**
* A simple example to show the usage of DimmableLightManager class.
* This class helps you to give a name to each light, and using it
* to control a light.
*/
#include <dimmable_light_manager.h>
const int N = 3;
#if defined(ARDUINO_ARCH_ESP8266)
const int syncPin = 13;
const int pins[N] = { 5, 4, 14 };
#elif defined(ARDUINO_ARCH_ESP32)
const int syncPin = 23;
const int pins[N] = { 4, 16, 17 };
#elif defined(ARDUINO_ARCH_AVR)
const int syncPin = 2;
const int pins[N] = { 3, 4, 5 };
#elif defined(ARDUINO_ARCH_SAMD)
const int syncPin = 2;
const int pins[N] = { 3, 4, 5 };
#elif (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
const int syncPin = 2;
const int pins[N] = { 3, 4, 5 };
#endif
DimmableLightManager dlm;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: fourth example");
Serial.println("Initializing the dimmable light class... ");
// Add all the lights you need
for (int i = 0; i < N; i++) {
if (dlm.add(String("light") + (i + 1), pins[i])) {
Serial.println(String(" ") + (i + 1) + "-th light added correctly");
} else {
Serial.println(" Light isn't added, probably this name was already used...");
}
}
DimmableLight::setSyncPin(syncPin);
DimmableLightManager::begin();
Serial.println("Done!");
}
void loop() {
for (int b = 0; b < 255; b += 10) {
for (int i = 0; i < dlm.getCount(); i++) {
std::pair<String, DimmableLight*> p = dlm.get();
String lightName = p.first;
DimmableLight* dimLight = p.second;
// Altervatively, you can require to the manager a specific light
// DimmableLight* dimLight = dlm.get("light1");
Serial.println(String("Setting --") + lightName + "-- to brightness: " + b);
dimLight->setBrightness(b);
}
delay(500);
}
Serial.println();
}

View File

@@ -0,0 +1,102 @@
/**
* This advanced example shows how to use the DimmableLightManager
* combined with Ticker class.
*
* In this case the friendly names are "light1", "light2" and so on...
* Once your setup is ready (light, thyristor, wemos flashed with this sketch),
* you should see a very simple effect: all the light will fade from
* dark to maximum brightness simultaneously.
*
* NOTE: compiles only for ESP8266 and ESP32 because the Ticker.h dependency
*/
#include <Ticker.h>
#include <dimmable_light_manager.h>
#define N 5
const int syncPin = 13;
int pins[N] = { 5, 4, 14, 12, 15 };
// This param modifies the effect speed. The value is the period between a
// brightness value and the next one, in seconds
const float period = 0.05;
Ticker dim;
DimmableLightManager dlm;
void doRaise(void) {
static uint8_t brightnessStep = 0;
for (int i = 0; i < dlm.getCount(); i++) {
DimmableLight* dimLight = dlm.get().second;
dimLight->setBrightness(brightnessStep);
}
if (brightnessStep == 255) {
brightnessStep = 0;
dim.attach(period, doLower);
} else {
brightnessStep++;
}
}
void doLower(void) {
static uint8_t brightnessStep = 255;
for (int i = 0; i < dlm.getCount(); i++) {
DimmableLight* dimLight = dlm.get().second;
dimLight->setBrightness(brightnessStep);
}
if (brightnessStep == 0) {
brightnessStep = 255;
dim.attach(period, doRaise);
} else {
brightnessStep--;
}
}
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: fifth example");
Serial.println("Initializing the dimmable light class... ");
// Add all the lights you need
for (int i = 0; i < N; i++) {
if (dlm.add(String("light") + (i + 1), pins[i])) {
Serial.println(String(" ") + (i + 1) + "-th light added correctly");
} else {
Serial.println(" Light isn't added, probably this name was already used...");
}
}
DimmableLight::setSyncPin(syncPin);
DimmableLightManager::begin();
Serial.println("Done!");
// This line starts the effect. In the meanwhile,
// you can continue to execution your own code (thanks to Ticker library)
dim.attach(period, doRaise);
}
void loop() {
// Print the light name and its actual brightness
for (int i = 0; i < dlm.getCount(); i++) {
std::pair<String, DimmableLight*> p = dlm.get();
DimmableLight* dimLight = p.second;
// Altervatively, you can require to the manager a specific light
// DimmableLight* dimLight = dlm.get("light1");
Serial.println(String(p.first) + " brightness:" + dimLight->getBrightness());
}
Serial.println();
delay(500);
}

View File

@@ -0,0 +1,163 @@
/**
* This examples provides some effects to test and demonstrate the potentiality of DimmableLight.
* Once you can uploaded this sketch, you can select one effect through the serial port. Just
* type the code's effect (values among ["e0"-"e12"]) and "stop" to stop the current effect.
* Remember to select CRLF line ending in Arduino IDE serial console.
*
* NOTE: install https://github.com/kroimon/Arduino-SerialCommand
*/
#include "effect.h"
#include <SerialCommand.h>
SerialCommand serialCmd;
int effectSelected = -1;
void unrecognized(const char* message) {
Serial.println(String(message) + ": command not recognized");
serialCmd.clearBuffer();
}
void stopEffect() {
offAllLights();
effectSelected = -1;
effect = nullptr;
}
void selectEffect(unsigned char effectId) {
if (effectSelected != effectId) {
effectSelected = effectId;
switch (effectSelected) {
case 0:
Serial.println("##New Effect Selected## Equal");
doEqual();
break;
case 1:
Serial.println("##New Effect Selected## Equal On Off");
doEqualOnOff();
break;
case 2:
Serial.println("##New Effect Selected## Dim Specific Step");
doDimSpecificStep();
break;
case 3:
Serial.println("##New Effect Selected## Range Limit");
doRangeLimit();
break;
case 4:
Serial.println("##New Effect Selected## Near Values");
doNearValues();
break;
case 5:
Serial.println("##New Effect Selected## Dim Mixed");
doDimMixed();
break;
case 6:
Serial.println("##New Effect Selected## Dim Sweep Equal");
doDimSweepEqual();
break;
case 7:
Serial.println("##New Effect Selected## On Off Sweep");
doOnOffSweep();
break;
case 8:
Serial.println("##New Effect Selected## Inverted Dim");
doInvertedDim();
break;
case 9:
Serial.println("##New Effect Selected## Circular Swipe");
doCircularSwipe();
break;
case 10:
Serial.println("##New Effect Selected## Random Bri");
doRandomBri();
break;
case 11:
Serial.println("##New Effect Selected## Random Bri Peephole");
doRandomBriPeephole();
break;
case 12:
Serial.println("##New Effect Selected## Random Push Extreme Values");
doRandomPushExtremeValues();
break;
case 13:
Serial.println("##New Effect Selected## Circular Swipe Regular");
doCircularSwipeRegular();
break;
default: Serial.println("Effect ID not implemented");
}
}
}
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: sixth example");
initLights();
serialCmd.addCommand("stop", []() {
stopEffect();
});
serialCmd.addCommand("e0", []() {
selectEffect(0);
});
serialCmd.addCommand("e1", []() {
selectEffect(1);
});
serialCmd.addCommand("e2", []() {
selectEffect(2);
});
serialCmd.addCommand("e3", []() {
selectEffect(3);
});
serialCmd.addCommand("e4", []() {
selectEffect(4);
});
serialCmd.addCommand("e5", []() {
selectEffect(5);
});
serialCmd.addCommand("e6", []() {
selectEffect(6);
});
serialCmd.addCommand("e7", []() {
selectEffect(7);
});
serialCmd.addCommand("e8", []() {
selectEffect(8);
});
serialCmd.addCommand("e9", []() {
selectEffect(9);
});
serialCmd.addCommand("e10", []() {
selectEffect(10);
});
serialCmd.addCommand("e11", []() {
selectEffect(11);
});
serialCmd.addCommand("e12", []() {
selectEffect(12);
});
serialCmd.addCommand("e13", []() {
selectEffect(13);
});
serialCmd.setDefaultHandler(unrecognized);
Serial.println("Select one effect ranging between e0 and e13");
}
void loop() {
serialCmd.readSerial();
uint32_t now = millis();
if (effectSelected == -1) {
delay(20);
} else if (now - lastCall > period) {
if (effect != nullptr) effect();
}
}

View File

@@ -0,0 +1,432 @@
#include "effect.h"
void (*effect)() = nullptr;
// The period between a call and the next one in millisecond
uint16_t period = 0;
uint32_t lastCall = 0;
// A complicated way to define objects to allow the testing of different
// classes on different microcontrollers
#if defined(RAW_VALUES)
extern DimmableLight
#elif defined(LINEARIZED_VALUES)
extern DimmableLightLinearized
#endif
#if defined(ESP8266)
// Remember that GPIO0 (D3) and GPIO2 (D4) are "critical" since they control the boot phase.
// I have to disconnect them to make it boot when using Krida's dimmers. If you want to
// use those pins without disconnecting and connecting the wires, you need additional circuitry to
// "protect" them.
lights[N_LIGHTS] = { { 5 }, { 4 }, { 14 }, { 12 }, { 15 }, { 16 }, { 0 }, { 2 } };
#elif defined(ESP32)
lights[N_LIGHTS] = { { 4 }, { 16 }, { 17 }, { 5 }, { 18 }, { 19 }, { 21 }, { 22 } };
#elif defined(AVR) // Arduino
lights[N_LIGHTS] = { { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 10 } };
#elif defined(ARDUINO_ARCH_SAMD)
lights[N_LIGHTS] = { { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 10 } };
#elif (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
lights[N_LIGHTS] = { { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 10 } };
#endif
/**
* Set particular values of brightness to every light.
*/
void doEqual() {
const unsigned int period = 3000;
static const uint8_t briLevels[] = { 0, 1, 2, 50, 100, 150, 254, 255 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels[brightnessStep] + "/255");
for (int i = 0; i < N_LIGHTS; i++) { lights[i].setBrightness(briLevels[brightnessStep]); }
brightnessStep++;
if (brightnessStep == sizeof(briLevels) / sizeof(briLevels[0])) { brightnessStep = 0; }
::period = period;
lastCall = millis();
effect = doEqual;
}
/**
* Turn on and off simultaneously all the bulbs.
*/
void doEqualOnOff() {
const unsigned int period = 3000;
static int briLevels[] = { 0, 255 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels[brightnessStep] + "/255");
for (int i = 0; i < N_LIGHTS; i++) { lights[i].setBrightness(briLevels[brightnessStep]); }
brightnessStep++;
if (brightnessStep == sizeof(briLevels) / sizeof(briLevels[0])) { brightnessStep = 0; }
::period = period;
lastCall = millis();
effect = doEqualOnOff;
}
/**
* Set brightness to specific values.
*/
void doDimSpecificStep(void) {
const unsigned int period = 3000;
static const uint8_t briLevels1[] = { 40, 200 };
static const uint8_t briLevels2[] = { 60, 160 };
static const uint8_t briLevels3[] = { 80, 130 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels1[brightnessStep] + " and "
+ briLevels2[brightnessStep] + " and " + briLevels3[brightnessStep] + " /255");
lights[1].setBrightness(briLevels1[brightnessStep]);
lights[2].setBrightness(briLevels2[brightnessStep]);
lights[3].setBrightness(briLevels3[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels1) / sizeof(briLevels1[0])) { brightnessStep = 0; }
::period = period;
lastCall = millis();
effect = doDimSpecificStep;
}
/**
* Test a mixture between on, off and middle brightness.
*/
void doRangeLimit(void) {
const unsigned int period = 5000;
static const uint8_t briLevels1[] = { 0, 255 };
static const uint8_t briLevels2[] = { 255, 0 };
static const uint8_t briLevels3[] = { 100, 100 };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevels1[brightnessStep] + " and "
+ briLevels2[brightnessStep] + " and " + briLevels3[brightnessStep] + " /255");
lights[1].setBrightness(briLevels1[brightnessStep]);
lights[2].setBrightness(briLevels2[brightnessStep]);
lights[3].setBrightness(briLevels3[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevels1) / sizeof(briLevels1[0])) { brightnessStep = 0; }
::period = period;
lastCall = millis();
effect = doRangeLimit;
}
/**
* Test your eyes sensitivity by switching between near values. Will you see any difference?
*/
void doNearValues(void) {
const unsigned int period = 3000;
static const uint8_t avg = 80;
static const uint8_t diff = 2;
static const uint8_t briLevelsLamp1[] = { avg - diff, avg };
static const uint8_t briLevelsLamp2[] = { avg, avg + diff };
static const uint8_t briLevelsLamp3[] = { avg + diff, avg - diff };
static uint8_t brightnessStep = 0;
Serial.println(String("Dimming at: ") + briLevelsLamp1[brightnessStep] + " and "
+ briLevelsLamp2[brightnessStep] + " and " + briLevelsLamp3[brightnessStep] + " /255");
lights[1].setBrightness(briLevelsLamp1[brightnessStep]);
lights[2].setBrightness(briLevelsLamp2[brightnessStep]);
lights[3].setBrightness(briLevelsLamp3[brightnessStep]);
brightnessStep++;
if (brightnessStep == sizeof(briLevelsLamp1) / sizeof(briLevelsLamp1[0])) { brightnessStep = 0; }
::period = period;
lastCall = millis();
effect = doNearValues;
}
/**
* The 1st the 5th are turned off, the 3rd is fixed to half brightness, and the 2nd and 4th sweep
* in the opposite direction w.r.t. each other.
*/
void doDimMixed(void) {
const unsigned int period = 50;
static uint8_t brightnessStep = 1;
static bool up = true;
lights[1].setBrightness(brightnessStep);
int b2 = 105;
lights[2].setBrightness(b2);
int b3 = -((int)brightnessStep - 255);
lights[3].setBrightness(b3);
Serial.println(String("Dimming at: ") + brightnessStep + " " + b2 + " " + b3 + "/255");
if (brightnessStep == 255 && up) {
up = false;
} else if (brightnessStep == 0 && !up) {
up = true;
} else {
if (up) {
brightnessStep++;
} else {
brightnessStep--;
}
// Jump some steps...
// if(brightnessStep==6){
// brightnessStep=249;
// }
}
::period = period;
lastCall = millis();
effect = doDimMixed;
}
/**
* All the lights simultaneously fade in and out.
*/
void doDimSweepEqual(void) {
const unsigned int period = 50;
static uint8_t brightnessStep = 1;
static bool up = true;
for (int i = 0; i < N_LIGHTS; i++) { lights[i].setBrightness(brightnessStep); }
Serial.println(String("Dimming at: ") + brightnessStep + "/255");
if (brightnessStep == 255 && up) {
up = false;
} else if (brightnessStep == 0 && !up) {
up = true;
} else {
if (up) {
brightnessStep++;
} else {
brightnessStep--;
}
}
::period = period;
lastCall = millis();
effect = doDimSweepEqual;
}
void doOnOffSweep() {
const unsigned int period = 700;
static int16_t step = 0;
for (int i = 0; i < N_LIGHTS; i++) {
if (step == i) {
lights[i].setBrightness(255);
} else {
lights[i].setBrightness(0);
}
}
step++;
if (step == N_LIGHTS) { step = 0; }
::period = period;
lastCall = millis();
effect = doOnOffSweep;
}
/**
* The group formed by even bulbs sweep in the opposite direction w.r.t. the odd group.
*/
void doInvertedDim(void) {
const unsigned int period = 50;
static uint8_t brightnessStep = 1;
static bool up = true;
int oppositeBrightness = -((int)brightnessStep - 255);
Serial.println(String("Dimming at: ") + brightnessStep + " " + oppositeBrightness + "/255");
for (int i = 0; i < N_LIGHTS; i++) {
if (i % 2 == 0) {
lights[i].setBrightness(brightnessStep);
} else {
lights[i].setBrightness(oppositeBrightness);
}
}
if (brightnessStep == 255 && up) {
up = false;
} else if (brightnessStep == 0 && !up) {
up = true;
} else {
if (up) {
brightnessStep++;
} else {
brightnessStep--;
}
}
::period = period;
lastCall = millis();
effect = doInvertedDim;
}
/**
* Return the module of a non-negative number (optimized).
*/
unsigned int module(unsigned int value, unsigned int max) {
if (value < max) { return value; }
return value % max;
}
/**
* Given a number in range [0; 512), return a triangular function [0;255], if value is not in this
* range, return 0.
*/
uint8_t triangularFunction(uint16_t value) {
int simmetricValue = 0;
if (value <= 255) { simmetricValue = value; }
if (value >= 256 && value <= 511) { simmetricValue = -value + 511; }
return simmetricValue;
}
/**
* Given a number in range [0; 512), return a "pow-ed" triangular function [0;255].
*/
uint8_t conversionPow(uint16_t value) {
int simmetricValue = 0;
if (value >= 256 && value <= 511) { simmetricValue = -value + 511; }
if (value <= 255) { simmetricValue = value; }
if (simmetricValue < 150) { return 0; }
int y = pow(simmetricValue - 150, 1.2);
if (y > 255) { return 255; }
return y;
}
/**
* Turn on the light with (255/nLights) steps offset between consecutive lights.
*/
void doCircularSwipe(void) {
const unsigned int period = 50;
static uint16_t brightnessStep = 255;
// Alternatively, you can use the function conversionPow(..) instead conversion(..)
for (int i = 0; i < N_LIGHTS; i++) {
int brightness = triangularFunction(module(brightnessStep + 32 * i, 512));
lights[i].setBrightness(brightness);
}
brightnessStep++;
if (brightnessStep == 512) { brightnessStep = 0; }
::period = period;
lastCall = millis();
effect = doCircularSwipe;
}
void doRandomBri() {
const unsigned int period = 700;
for (int i = 0; i < N_LIGHTS; i++) {
int bri = random(0, 256);
lights[i].setBrightness(bri);
}
::period = period;
lastCall = millis();
effect = doRandomBri;
}
/**
* The variance of random number is restricted around the mean value step after step
*/
void doRandomBriPeephole() {
const unsigned int period = 700;
const uint16_t briStep = 10;
const uint16_t totStep = 16;
static uint16_t iteration = 0;
for (int i = 0; i < N_LIGHTS; i++) {
int bri;
// The last 2 step are set to the same brightness
if (iteration >= totStep - 3) {
bri = 127;
} else {
bri = random(0 + briStep * iteration, 256 - briStep * iteration);
}
Serial.print(String(bri) + " ");
lights[i].setBrightness(bri);
}
Serial.println();
iteration++;
if (iteration == totStep) { iteration = 0; }
::period = period;
lastCall = millis();
effect = doRandomBriPeephole;
}
/**
* The variance of random number is restricted around the mean value step after step
*/
void doRandomPushExtremeValues() {
const unsigned int period = 1000;
const uint16_t briStep = 10;
for (int i = 0; i < N_LIGHTS; i++) {
int bri = random(0, briStep * 2 + 1);
if (bri < briStep) {
bri = bri;
} else {
bri = 255 - (briStep * 2 - bri);
}
Serial.print(String(bri) + " ");
lights[i].setBrightness(bri);
}
Serial.println();
::period = period;
lastCall = millis();
effect = doRandomPushExtremeValues;
}
/**
* Perform a brightness sweep all over the lights with a delay between each light of DELAY steps.
* This effect is perfectly smooth and simmetric w.r.t. doCircularSwipe().
*/
void doCircularSwipeRegular(void) {
const unsigned int period = 40;
const int HALF_PERIOD = 255;
const int DELAY = 96;
static int brightnessStep = 0;
for (int i = 0; i < N_LIGHTS; i++) {
unsigned int x = brightnessStep - DELAY * i < 0 ? 0 : brightnessStep - DELAY * i;
unsigned int brightness = triangularFunction(module(x, DELAY * N_LIGHTS));
lights[i].setBrightness(brightness);
}
brightnessStep++;
// Avoid any long-term overflow
if (brightnessStep >= HALF_PERIOD + 2 * DELAY * N_LIGHTS) {
brightnessStep = HALF_PERIOD + DELAY * N_LIGHTS;
}
::period = period;
lastCall = millis();
effect = doCircularSwipeRegular;
}
void offAllLights() {
for (int i = 0; i < N_LIGHTS; i++) { lights[i].setBrightness(0); }
}
void initLights() {
Serial.print("Initializing the dimmable light class... ");
#if defined(RAW_VALUES)
DimmableLight::setSyncPin(syncPin);
DimmableLight::begin();
#elif defined(LINEARIZED_VALUES)
DimmableLightLinearized::setSyncPin(syncPin);
DimmableLightLinearized::begin();
#endif
Serial.println("Done!");
#if defined(RAW_VALUES)
Serial.println(String("Number of instantiated lights: ") + DimmableLight::getLightNumber());
#elif defined(LINEARIZED_VALUES)
Serial.println(String("Number of instantiated lights: ") + DimmableLightLinearized::getLightNumber());
#endif
}

View File

@@ -0,0 +1,55 @@
// Select ONLY ONE between these 2 options
#define RAW_VALUES
//#define LINEARIZED_VALUES
#if defined(RAW_VALUES)
#include <dimmable_light.h>
#elif defined(LINEARIZED_VALUES)
#include <dimmable_light_linearized.h>
#endif
#include <stdint.h>
const int N_LIGHTS = 8;
#if defined(ESP8266)
const int syncPin = 13;
#elif defined(ESP32)
const int syncPin = 23;
#elif defined(AVR)
const int syncPin = 2;
#elif defined(ARDUINO_ARCH_SAMD)
const int syncPin = 2;
#elif (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
const int syncPin = 2;
#endif
#if defined(RAW_VALUES)
extern DimmableLight lights[];
#elif defined(LINEARIZED_VALUES)
extern DimmableLightLinearized lights[];
#endif
extern void (*effect)();
// The period between a call and the next one in millisecond
extern uint16_t period;
extern uint32_t lastCall;
void doEqual();
void doEqualOnOff();
void doDimSpecificStep();
void doRangeLimit();
void doNearValues();
void doDimMixed();
void doDimSweepEqual();
void doOnOffSweep();
void doInvertedDim();
void doCircularSwipe();
void doRandomBri();
void doRandomBriPeephole();
void doRandomPushExtremeValues();
void doCircularSwipeRegular();
void offAllLights();
void initLights();

View File

@@ -0,0 +1,38 @@
/**
* The main parameters to configure this sketch accordingly to your hardware setup are:
* - syncPin, that is the pin listening to AC zero cross signal
* - light, the pin which is connected to the thyristor
*/
#include <dimmable_light_linearized.h>
const int syncPin = 13;
const int thyristorPin = 14;
DimmableLightLinearized light(thyristorPin);
// Delay between a brightness changement in millisecond
const int period = 50;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: first example");
Serial.print("Initializing the dimmable light class... ");
DimmableLightLinearized::setSyncPin(syncPin);
// VERY IMPORTANT: Call this method to start internal light routine
DimmableLightLinearized::begin();
Serial.println("Done!");
}
void loop() {
for (int i = 0; i < 256; i++) {
light.setBrightness(i);
delay(period);
}
delay(2000);
}

View File

@@ -0,0 +1,67 @@
/**
* This examples shows how to dinamically set the network frequency,
* so your device can adapt to 50Hz or 60Hz without changing firmware.
*
* You just need to activate the library, then wait a while to sample
* the actual frequency and then set the correct frequency. Since the
* detected value may be imprecise due to noise, it is up to you
* to implement the logic to chose the proper frequency. The frequency
* is calculated with a moving average (by default on the last 5 values)
* and it is continuosly updated.
*
* NOTE: you have to select NETWORK_FREQ_RUNTIME and MONITOR_FREQUENCY
* #defines in thyristor.h
*/
#include <dimmable_light.h>
const int syncPin = 13;
const int thyristorPin = 14;
DimmableLight light(thyristorPin);
// Delay between brightness increments, in milliseconds
const int period = 50;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println();
Serial.println("Dimmable Light for Arduino: setting network frequency automatically");
Serial.print("Initializing DimmableLight library... ");
DimmableLight::setSyncPin(syncPin);
// VERY IMPORTANT: Call this method to activate the library
DimmableLight::begin();
// A small delay to get some samples
delay(50);
float f = DimmableLight::getDetectedFrequency();
int frequency = round(f);
if (frequency == 50) {
Serial.print("Setting frequency to 50Hz... ");
DimmableLight::setFrequency(50);
Serial.println("Done!");
} else if (frequency == 60) {
Serial.print("Setting frequency to 60Hz... ");
DimmableLight::setFrequency(60);
Serial.println("Done!");
} else {
Serial.println(String("Unknown frequency detected: ") + f);
while (1)
;
}
Serial.println("Light dimming...");
}
void loop() {
for (int i = 0; i < 256; i++) {
light.setBrightness(i);
delay(period);
}
// Remember that the frequency is continuously updated
Serial.println(String("Updated frequency: ") + DimmableLight::getDetectedFrequency());
}