Hi all, I have small problem with my project, I build an animated light for outdoor usage,
the main point is to make animation running smooth without lag or freezing, but when reading the message from CTBot and NTPClient, the animation stop around 0.5-3s depend on the network.
this is the simple code:
#include <ESP8266WiFi.h>
#include <FastLED.h>
#include <NTPClient.h>
#include <CTBot.h>
#include <WiFiUdp.h>
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
#define NUM_LEDS 30
#define LED_PIN 14
CTBot myBot;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "id.pool.ntp.org");
const char* ssid = "-";
const char* password = "-";
String token = "-";
CRGB leds[NUM_LEDS];
CRGBPalette16 currentPalette;
TBlendType currentBlending;
unsigned long previousMillis = 0;
unsigned long lastUpdate = 0;
int brightness = 250;
int interval = 10000;
void setup() {
Serial.begin(115200);
Serial.println("");
Serial.println("Booting..");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( brightness );
myBot.wifiConnect(ssid, password);
myBot.setTelegramToken(token);
if (myBot.testConnection())
Serial.println("\ntestConnection OK");
else
Serial.println("\ntestConnection NOK");
timeClient.begin();
timeClient.setTimeOffset(25200); // GMt +7 (7*60*60)
timeClient.update();
setupRandomPallete();
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - lastUpdate > interval) {
checkTime();
handleMessageBot();
}
if (currentMillis - previousMillis > 30) {
previousMillis = currentMillis;
static uint8_t startIndex = 0;
startIndex = startIndex + 1; /* motion speed */
fillLedWithColor(startIndex);
FastLED.show();
}
}
void fillLedWithColor( uint8_t colorIndex) {
for( int i = 0; i < NUM_LEDS; ++i) {
leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 3;
}
}
void checkTime() {
timeClient.update();
// then set the led on when night time
}
void handleMessageBot() {
TBMessage msg;
// if there is an incoming message...
if (myBot.getNewMessage(msg)) {
Serial.print("p ID: ");
Serial.println(msg.sender.id);
Serial.print("group ID: ");
Serial.println(msg.group.id);
Serial.print("msg: ");
Serial.println(msg.text);
}
}
void setupRandomPallete() {
for( int i = 0; i < 16; ++i) {
currentPalette[i] = CHSV( random8(), 255, random8());
}
}
this is just the main code that I use in the project.
my question is how to make the CTBot and NTPClient working without delay.? or waiting.?
notes: I already try change the interval above 50s, this make the animation less lag. But the CTBot only read 1 message per request, so when I send 5 message I need to wait (50s x 5) before the update take effect. and well this is temporary solution for now.
You don't need to keep running NTP to do that, the time library tracks time continuously, and you can obtain the local or UTC time just by making the right calls. NTP should only be invoked to set or synchronize the system time. So, if it's just an animated light, probably once an hour or once a day.
The issue you are having is that you have a direct relation between the framerate & update speed.
That means that any time the processor gets held up, and therefore the test for elapsed time may be postponed.
if (currentMillis - previousMillis > 30) {
what you should do is to calculate the position of the animation. Do not test for elapsed time. rather calculate
The animation may still get held but by the calls to checkTime() & handleMessageBot(), but the calculation of the animation will result in the correct position, not slowing the animation down. There may be frames missing, but the timing remains correct.
Keep in mind that these 2 libraries are fundamentally incompatible. The wifi library relies on interrupts and FastLED.show() disables them for the duration of the transmission,
To transmit the signal that drives the LED's timing needs to be fairly precise, and FastLED is using what is known as a 'bit-banged method' to transmit this signal. Basically the pin is put HIGH for a certain period and then LOW, and the intervals decide if that means a bit is set HIGH or LOW.
If this timing process is interrupted and timing is no longer precise, the result will be glitches. So to prevent that from happening, interrupts are turned of for the duration of the transmission.
The wifi connection depends on a responsive device, network requests need immediate replies. Interrupts are triggered and if these interrupts are not acted upon, you will lose you wifi connection.
You use just 14 leds, so your interrupt block is only short, but in my method the framerate will increase automatically if there are no requests, so you may lose wifi quite quickly.
You will lose wifi eventually with your current sketch. It may take 10 minutes, it may take a day.
Just that ! But you lose what you want though, you want WiFi and control LEDs.
I use neopixelbus to control neopixels. It's default DMA mode is excellent but has restrictions on the PIN that you can use which is GPIO 3 only. This is unfortunately also the UART RX pin, but if needed you can use the alternate pair. (13 & 15)
I ran into this WiFi issue myself 5 yrs ago, and this is the solution.
There are a few methods available that use the UART (there is also a method in neopixelbus) as an output as well, which will provide a stable WiFi connection as well, but are just not quite as reliable in their WS2812 signal in my experience.
PJRC also has a couple DMA-based libraries for these types of LEDs that run on the Teensy family. This One creates a class that inherits from CPixelLEDController so that it hooks seamlessly into FastLED.
And, of course, you could always switch to APA102-type LEDs.
That may be a few frames, consider a 100ms block in processing will lose you 3 frames. There is no real 2 ways about it though, but if you are seriously attached to those frames you could try
which will just let the processor catch up. but will show the frames. Won't make much difference visually since there is almost no time between showing of those delayed frames.
Well yes ! of course, if you lose wifi connection (basically you lose sync between the wifi part of the ESP & the main processing.) Then OTA will also not work since it depends on WiFi working properly.