jled
jled copied to clipboard
How to control 15 gpio pins
Since I am not a software developer, it is difficult for me to control 15 LED strips connected to different GPIOs of ESp32. For better or worse, I managed to do this, but for a programmer, the long code below could have been much shorter.. In addition, I tried to run it with the codes under the "Controlling a group of LEDs" title in order not to introduce each led strip separately, but I could not succeed.
Stair tread lighting that has no unusual design, and has been applied in many ways. In essence, there is a sensor at both the beginning and the end of the steps. With the trigger of the sensor, the LEDs start to turn on in fade effect and sequence. As I said, the code works, I just wanted to ask how it could be cleaner to improve myself.
// https://github.com/jandelgado/jled
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <jled.h>
auto led1 = JLed(12);
auto led2 = JLed(13);
auto led3 = JLed(14);
auto led4 = JLed(25);
auto led5 = JLed(26);
auto led6 = JLed(27);
auto led7 = JLed(32);
auto led8 = JLed(33);
auto led9 = JLed(19);
auto led10 = JLed(23);
auto led11 = JLed(18);
auto led12 = JLed(5);
auto led13 = JLed(17);
auto led14 = JLed(16);
auto led15 = JLed(4);
bool flagState = false;
bool virtualState = false;
String newHostname = "Deneme";
const char* ssid = "barisea";
const char* pass = "xxx";
int ReCnctFlag; // Reconnection Flag
int ReCnctCount = 0; // Reconnection counter
bool isFirstConnect = true;
char auth[] = "xxxx";
char server[] = "192.168.1.2"; // IP for Local Cloud Server
int port = 8080;
int sensorPin = 15;
int sensorNewState;
bool upTrigger = false;
bool downTrigger = false;
int maxB = 255;
int minB = 0;
BlynkTimer timer;
WidgetRTC rtc;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
long interval = 9000;
BLYNK_WRITE(V27) {
maxB = param.asInt();
}
BLYNK_WRITE(V28) {
minB = param.asInt();
}
BLYNK_WRITE(V25) {
virtualState = param.asInt();
if (virtualState == 1 & flagState == 0) { // Run only if Switch ON and Flag set to 0
flagState = 1; // Set flag to prevent multiple occurrences.
led1.Fade(0, maxB, 200).DelayBefore(100);
led2.Fade(0, maxB, 200).DelayBefore(200);
led3.Fade(0, maxB, 200).DelayBefore(300);
led4.Fade(0, maxB, 200).DelayBefore(400);
led5.Fade(0, maxB, 200).DelayBefore(500);
led6.Fade(0, maxB, 200).DelayBefore(600);
led7.Fade(0, maxB, 200).DelayBefore(700);
led8.Fade(0, maxB, 200).DelayBefore(800);
led9.Fade(0, maxB, 200).DelayBefore(900);
led10.Fade(0, maxB, 200).DelayBefore(1000);
led11.Fade(0, maxB, 200).DelayBefore(1100);
led12.Fade(0, maxB, 200).DelayBefore(1200);
led13.Fade(0, maxB, 200).DelayBefore(1300);
led14.Fade(0, maxB, 200).DelayBefore(1400);
led15.Fade(0, maxB, 200).DelayBefore(1500);
flagState = 0; // Reset flag
downTrigger = true;
} else {
led1.Fade(200, minB, 200).DelayBefore(1500);
led2.Fade(200, minB, 200).DelayBefore(1400);
led3.Fade(200, minB, 200).DelayBefore(1300);
led4.Fade(200, minB, 200).DelayBefore(1200);
led5.Fade(200, minB, 200).DelayBefore(1100);
led6.Fade(200, minB, 200).DelayBefore(1000);
led7.Fade(200, minB, 200).DelayBefore(900);
led8.Fade(200, minB, 200).DelayBefore(800);
led9.Fade(200, minB, 200).DelayBefore(700);
led10.Fade(200, minB, 200).DelayBefore(600);
led11.Fade(200, minB, 200).DelayBefore(500);
led12.Fade(200, minB, 200).DelayBefore(400);
led13.Fade(200, minB, 200).DelayBefore(300);
led14.Fade(200, minB, 200).DelayBefore(200);
led15.Fade(200, minB, 200).DelayBefore(100);
downTrigger = false;
}
}
BLYNK_WRITE(V26) {
if (param.asInt()) {
}
}
BLYNK_CONNECTED() { //Start Blynk connection
rtc.begin();
ReCnctCount = 0;
if (isFirstConnect) {
Blynk.syncAll();
Serial.println("Blynk.synced");
isFirstConnect = false;
}
}
void setup() {
Serial.begin(115200);
WiFi.hostname(newHostname.c_str());
WiFi.begin(ssid, pass);
Blynk.config(auth, server, port);
Blynk.connect();
setSyncInterval(60);
timer.setInterval(100L, checkLights);
attachInterrupt(sensorPin, sensorButtonPressed, RISING);
}
void sensorButtonPressed() {
Serial.println("sensorButtonPressed");
int sensorNewState = digitalRead(sensorPin);
if (sensorNewState == HIGH) {
previousMillis = currentMillis;
if (downTrigger == false) {
upTrigger = true;
}
}
return;
}
void loop() {
timer.run();
currentMillis = millis();
//sensorNewState = digitalRead(sensorPin);
led1.Update();
led2.Update();
led3.Update();
led4.Update();
led5.Update();
led6.Update();
led7.Update();
led8.Update();
led9.Update();
led10.Update();
led11.Update();
led12.Update();
led13.Update();
led14.Update();
led15.Update();
if (sensorNewState == HIGH) {
}
if (upTrigger == true) {
Blynk.virtualWrite(V25, 1);
Blynk.syncVirtual(V25);
upTrigger = false;
}
if ((currentMillis - previousMillis >= interval) && (downTrigger == true)) {
Blynk.virtualWrite(V25, 0);
Blynk.syncVirtual(V25);
}
if (Blynk.connected()) { // If connected run as normal
Blynk.run();
} else if (ReCnctFlag == 0) { // If NOT connected and not already trying to reconnect, set timer to try to reconnect in 30 seconds
WiFi.disconnect();
WiFi.hostname(newHostname.c_str());
WiFi.begin(ssid, pass);
ReCnctFlag = 1; // Set reconnection Flag
Serial.println("Starting reconnection timer in 30 seconds...");
timer.setTimeout(5000L, []() { // Lambda Reconnection Timer Function
ReCnctFlag = 0; // Reset reconnection Flag
ReCnctCount++; // Increment reconnection Counter
Serial.print("Attempting reconnection #");
Serial.println(ReCnctCount);
Blynk.connect(); // Try to reconnect to the server
}); // END Timer Function
}
}
void checkLights() {
}
hi @aGGreSSiv , have a look at the multiled
example, where multiple LEDs are stored in an array . In your case you could simplify the code to (excerpts):
JLed leds[] = {
JLed(12),
JLed(13),
JLed(14),
JLed(25),
JLed(26),
JLed(27),
JLed(32),
JLed(33),
JLed(19),
JLed(23),
JLed(18),
JLed(5),
JLed(1),
JLed(16),
JLed(4)
};
auto sequence = JLedSequence(JLedSequence::eMode::PARALLEL, leds);
....
BLYNK_WRITE(V25) {
virtualState = param.asInt();
if (virtualState == 1 & flagState == 0) { // Run only if Switch ON and Flag set to 0
flagState = 1; // Set flag to prevent multiple occurrences.
auto delay = 100;
for(auto &led: leds) {
led.Fade(0, maxB, 200).DelayBefore(delay);
delay += 100;
}
flagState = 0; // Reset flag
downTrigger = true;
} else {
auto delay = 1500;
for(auto &led: leds) {
led.Fade(0, minB, 200).DelayBefore(delay);
delay -= 100;
}
downTrigger = false;
}
}
...
void loop() {
...
sequence.Update();
...
}
Thank you for the help.
I think we used the delay command for the fade effect and all of them are opened or closed in the same time. I will set up my test environment again shortly. I will try again so that each led turns on or off one after the other. I will try to do the next part to improve myself, if I fail, I will ask for help.
Maybe I didn't fully understand. led.Fade(0 part turns off all the LEDs in the array, while the transition delay to the next LED in the array?
Hello. I had a chance to test the code today. Thank you for the help. When I tried it with the hardware, I understood better.. Some of the features I wanted were asked by others, I will try them too.
Hello again. I thought I had tried the code you shared, but when I checked, it turned out that I had uploaded my old code. Now, when I try your post, whenever I press the button, the microprocessor reboots itself by giving a Kernal Panic warning. (I use lolin d32 Pro.)
attachInterrupt(sensorPin, sensorButtonPressed, RISING);
When I cancel this line and try to constantly check the button pins with a small delay in the loop, I do not get the kernal panic error, but the LEDs do not light even though I see that I pressed the button on the terminal screen.
This part is an observation about my own code:
Initially, I connected only 8 of the 15 Outputs for testing. Yesterday, I connected LEDs to the outputs of all of them and I noticed that if I try the GPIOs one by one with the sample files, there is no problem. But if I try all of them at the same time with my code I shared above, when the 1st LED is on, the 9th LED is also on. When the 2nd lights up, the 10th lights up too... and so on. I think I'm causing a problem with the number of PWM channels with my own code.
Hello again, This is the last time I tried it in its cleaned form.
#include <jled.h>
static uint8_t maxB = 255;
static uint8_t minB = 0;
JLed leds[] = {
JLed(12),
JLed(13),
JLed(14),
JLed(25),
JLed(26),
JLed(27),
JLed(32),
JLed(33),
JLed(19),
JLed(23),
JLed(18),
JLed(5),
JLed(1),
JLed(16),
JLed(4),
};
auto sequence = JLedSequence(JLedSequence::eMode::PARALLEL, leds);
int sensorPin = 15;
int sensorNewState;
void setup() {
Serial.begin(115200);
}
void loop() {
sensorNewState = digitalRead(sensorPin);
if (sensorNewState == HIGH) {
auto delay = 100;
for (auto &led : leds) {
led.Fade(0, maxB, 200).DelayBefore(delay);
delay += 100;
}
Serial.println("HIGH");
} else {
auto delay = 1500;
for (auto &led : leds) {
led.Fade(0, minB, 200).DelayBefore(delay);
delay -= 100;
}
Serial.println("LOW");
}
sequence.Update();
delay(1);
}
@aGGreSSiv , sorry for the late response, overlooked this one. I think the problem is in the loop
function, it is basically:
void loop() {
...
if (sensorNewState == HIGH) {
// set LEDs to led.Fade(0, maxB, 200).DelayBefore(delay);
} else {
// set LEDs to led.Fade(0, minB, 200).DelayBefore(delay);
}
sequence.Update();
}
So since it is an if-then-else
block, in every iteration the LEDs will be re-initialized, since in either case Fade
is called. What you actually need is to re-initialize only when the button state changes, like:
void loop() {
static int sensorLastState = -1;
...
if (sensorNewState == HIGH && sensorLastState != sensorNewState) {
sensorLastState = sensorNewState;
// set LEDs to led.Fade(0, maxB, 200).DelayBefore(delay);
} else
if (sensorNewState == LOW && sensorLastState != sensorNewState) {
{
sensorLastState = sensorNewState;
// set LEDs to led.Fade(0, minB, 200).DelayBefore(delay);
}
sequence.Update();
}
See also https://github.com/jandelgado/jled/issues/92#issuecomment-1082325999 for an example using a Button library.
Hello, It is important to me that you answered. I looked at the button example. I think I understand what you mean. I haven't replaced the circuit I made yet, I will try again according to your warning.
Thank you.
This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 5 days