• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь Помогите!! Wemos d1 mini. "цифровые глюки" на светодиодной ленте WS2812B

OneDrag1

New member
Сергей_Ф, nikolz,
Перепроверил всё и сейчас с уверенностью могу сказать, что глюки ленты есть в любом случае, даже в демо скетче ленты. Видимо я их не замечал до этого или их было меньше и реже, они произвольно скачут, за что дико извиняюсь...

По моей ситуации подробно и наглядно:
Есть основной блок "мастер" он полностью беспроводной и питается от 18650. У него есть кнопка и микрофон. Он ищет лампу, как только соединение есть передает инфомацию о полученном звуке с микрофона (это касается только первого режима работы) При нажатии на нем кнопки переключается на другой порядковый режим подсветки, а всего 5 режимов(1-цветной эквалайзер, 2-статичный приглушенный красный свет, 3- медленное переливание разных цветов, 4 приглушенный белый с рандомными искорками, 5-переливающаяся радуга). По идее это весь алгоритм основного блока "мастер". ниже его схема и код:
У меня собрано как по схеме но без модуля зарядки.
Мастер.jpg
sound reactive controller.jpg

---------------------------------------------
Есть лампа (пока что у меня это просто метроая полоса со светодиодами) "слейв". При включении она сразу переходит в режим поиска "мастера"(горит зеленый диод) как только он находит и соединение успешно создано(загорается синий диод) Считывает какой режим из 5 ему проигрывать по указанию "мастера", если это 1, то начинает принимать сигнал с микрофона "мастера" воспроизводя "case 1" из своего кода, если это режим 2 то "case 2" из своего кода и т.д.
Схема ниже, и как меня собрано:
IMG_0345.JPG sound reactive lamp.jpg

Вот видео как оно всё у меня по итогу работает:
Как видно особенно на 2 режиме(приглушенный красный свет) идут те самые "цифровые глюки".
----------------------------
Но если я добавлю диод между "+5v" БП и "+" ленты глюков становится гораздо меньше, сам диод и видео ниже:
IMG_0350.JPG

Прошу прощения за качество, и тряску... записывал на телефон.
 

OneDrag1

New member
Код "Мастера"
Код:
#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include "reactive_common.h"

#define READ_PIN 0
#define BUTTON_PIN D1

#define NUMBER_OF_CLIENTS 1

const int checkDelay = 5000;
const int buttonDoubleTapDelay = 200;
const int numOpModes = 5;

unsigned long lastChecked;
unsigned long buttonChecked;
bool buttonClicked = false;
bool queueDouble = false;
bool clickTrigger;
bool doubleTapped;
WiFiUDP UDP;

struct led_command {
  uint8_t opmode;
  uint32_t data;
};

bool heartbeats[NUMBER_OF_CLIENTS];

static int opMode = 1;

void setup()
{
  pinMode(READ_PIN, INPUT);
  pinMode(BUTTON_PIN, INPUT );

  /* WiFi Part */
  Serial.begin(115200);
  Serial.println();
  Serial.print("Setting soft-AP ... ");
  WiFi.persistent(false);
  WiFi.mode(WIFI_AP);
  WiFi.softAP("sound_reactive", "123456789");
  Serial.print("Soft-AP IP address = ");
  Serial.println(WiFi.softAPIP());
  UDP.begin(7171); 
  resetHeartBeats();
  waitForConnections();
  lastChecked = millis();
  buttonChecked = 0;
}


void loop()
{
  uint32_t analogRaw;
  buttonCheck();
  if (millis() - lastChecked > checkDelay) {
    if (!checkHeartBeats()) {
      waitForConnections();
    }
    lastChecked = millis();
  }

  switch (opMode) {
    case 1:
      analogRaw = analogRead(READ_PIN);
      if (analogRaw <= 3)
        break;
      sendLedData(analogRaw, opMode);
      break;
    case 2:
      sendLedData(0, opMode);
      delay(10);
      break;
    case 3:
      sendLedData(0, opMode);
      delay(10);
      break;
    case 4:
      sendLedData(0, opMode);
      delay(10);
      break;
    case 5:
      sendLedData(0, opMode);
      delay(10);
      break;
  }
  delay(4);
}

void sendLedData(uint32_t data, uint8_t op_mode) 
{
 struct led_command send_data;
 send_data.opmode = op_mode; 
 send_data.data = data; 
 for (int i = 0; i < NUMBER_OF_CLIENTS; i++) 
 {
    IPAddress ip(192,168,4,2 + i);
    UDP.beginPacket(ip, 7001); 
    UDP.write((char*)&send_data,sizeof(struct led_command));
    UDP.endPacket();
 }
}

void waitForConnections() {
  while(true) {
      readHeartBeat();
      if (checkHeartBeats()) {
        return;
      }
      delay(checkDelay);
      resetHeartBeats();
  }
}

void resetHeartBeats() {
  for (int i = 0; i < NUMBER_OF_CLIENTS; i++) {
   heartbeats[i] = false;
  }
}

void readHeartBeat() {
  struct heartbeat_message hbm;
 while(true) {
  int packetSize = UDP.parsePacket();
  if (!packetSize) {
    break;
  }
  UDP.read((char *)&hbm, sizeof(struct heartbeat_message));
  if (hbm.client_id > NUMBER_OF_CLIENTS) {
    Serial.println("Error: invalid client_id received");
    continue;
  }
  heartbeats[hbm.client_id - 1] = true;
 }
}

bool checkHeartBeats() {
  for (int i = 0; i < NUMBER_OF_CLIENTS; i++) {
   if (!heartbeats[i]) {
    return false;
   }
  }
  resetHeartBeats();
  return true;
}


void buttonCheck()
{
  int but = digitalRead(BUTTON_PIN);
  if (but == 0) {
    if (millis() - buttonChecked < buttonDoubleTapDelay && buttonClicked == false ) {
      doubleClicked();
      doubleTapped = true;
    }
    clickTrigger = true;
    buttonClicked = true; 
    buttonChecked = millis();
  }

  else if (but == 1) {
    if (millis() - buttonChecked > buttonDoubleTapDelay && clickTrigger) {
      if (!doubleTapped) {
        clicked();
      }
      clickTrigger = false;
      doubleTapped = false;
    }
    buttonClicked = false;
  }
}

void clicked() {
  if (opMode == numOpModes)
    opMode = 1;
  else
    opMode++;
  Serial.printf("Setting opmode %d \n", opMode);
}

void doubleClicked() {

}
 

OneDrag1

New member
Код "Слейв"
Код:
#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include "reactive_common.h"


#define FASTLED_INTERRUPT_RETRY_COUNT 0 
#define FASTLED_ALLOW_INTERRUPTS 0

#define LED_PIN 2
#define NUM_LEDS 61

#define MIC_LOW 0
#define MIC_HIGH 644

#define SAMPLE_SIZE 20
#define LONG_TERM_SAMPLES 250
#define BUFFER_DEVIATION 400
#define BUFFER_SIZE 3

#define LAMP_ID 1
WiFiUDP UDP;


int ihue = 255;                //-HUE (0-255)
int thissat = 100;           //-FX LOOPS DELAY VAR
int thisdelay = 35;          //-FX LOOPS DELAY VAR
float tcount = 0.0;          //-INC VAR FOR SIN LOOPS
int lcount = 1;              //-ANOTHER COUNTING VAR
int idex = 1;                //-LED INDEX (0 to NUM_LEDS-1
int thishue = 1;             //-FX LOOPS DELAY VAR
int bouncedirection = 1;     //-SWITCH FOR COLOR BOUNCE (0-1)
int isat = 0;                //-SATURATION (0-255)


const char *ssid = "sound_reactive"; // The SSID (name) of the Wi-Fi network you want to connect to
const char *password = "123456789";  // The password of the Wi-Fi network

CRGB leds[NUM_LEDS];

struct averageCounter *samples;
struct averageCounter *longTermSamples;
struct averageCounter* sanityBuffer;

float globalHue;
float globalBrightness = 255;
int hueOffset = 120;
float fadeScale = 1.3;
float hueIncrement = 0.7;

struct led_command {
  uint8_t opmode;
  uint32_t data;
};

unsigned long lastReceived = 0;
unsigned long lastHeartBeatSent;
const int heartBeatInterval = 100;
bool fade = false;

struct led_command cmd;
void connectToWifi();

void one_color_all(int cred, int cgrn, int cblu) {       //-SET ALL LEDS TO ONE COLOR
  for (int i = 0 ; i < NUM_LEDS; i++ ) {
    leds[i].setRGB( cred, cgrn, cblu);
  }
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
  leds[Pixel].r = red;
  leds[Pixel].g = green;
  leds[Pixel].b = blue;
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

void setup()
{
  globalHue = 0;
  samples = new averageCounter(SAMPLE_SIZE);
  longTermSamples = new averageCounter(LONG_TERM_SAMPLES);
  sanityBuffer    = new averageCounter(BUFFER_SIZE);

  while(sanityBuffer->setSample(250) == true) {}
  while (longTermSamples->setSample(200) == true) {}

  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);

  Serial.begin(115200); // Start the Serial communication to send messages to the computer
  delay(10);
  Serial.println('\n');

  WiFi.begin(ssid, password); // Connect to the network
 Serial.print("Connecting to ");
 Serial.print(ssid);
 Serial.println(" ...");

  connectToWifi();
  sendHeartBeat();
  UDP.begin(7001);
}

void sendHeartBeat() {
    struct heartbeat_message hbm;
    hbm.client_id = LAMP_ID;
    hbm.chk = 77777;
  Serial.println("Sending heartbeat");
    IPAddress ip(192,168,4,1);
    UDP.beginPacket(ip, 7171); 
    int ret = UDP.write((char*)&hbm,sizeof(hbm));
  printf("Returned: %d, also sizeof hbm: %d \n", ret, sizeof(hbm));
    UDP.endPacket();
    lastHeartBeatSent = millis();
}

void loop()
{
  if (millis() - lastHeartBeatSent > heartBeatInterval) {
    sendHeartBeat();
  }



  int packetSize = UDP.parsePacket();
  if (packetSize)
  {
    UDP.read((char *)&cmd, sizeof(struct led_command));
    lastReceived = millis();
  }

  if(millis() - lastReceived >= 5000)
  {
    connectToWifi();
  }
   
  int opMode = cmd.opmode;
  int analogRaw = cmd.data;

  switch (opMode) {
    case 1:
      fade = false;
      soundReactive(analogRaw);
      break;

    case 2:
      fade = false;
      allWhite();
      break;

    case 3:
      chillFade();
      break;

    case 4: SnowSparkle(0x10, 0x10, 0x10, thisdelay, random(100, 1000)); break;

    case 5: new_rainbow_loop(); break;
  }

}

void allWhite() {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB(30, 0, 0);
  }
  delay(5);
  FastLED.show();
}


void SnowSparkle(byte red, byte green, byte blue, int SparkleDelay, int SpeedDelay) {
  setAll(red, green, blue);

  int Pixel = random(NUM_LEDS);
  setPixel(Pixel, 0xff, 0xff, 0xff);
  FastLED.show();
  delay(SparkleDelay);
  setPixel(Pixel, red, green, blue);
  FastLED.show();
  delay(SpeedDelay);
}


void new_rainbow_loop() {                      //-m88-RAINBOW FADE FROM FAST_SPI2
  ihue -= 1;
  fill_rainbow( leds, NUM_LEDS, ihue );
  LEDS.show();
  delay(thisdelay);
}


void chillFade() {
  static int fadeVal = 0;
  static int counter = 0;
  static int from[3] = {0, 234, 255};
  static int to[3]   = {255, 0, 214};
  static int i, j;
  static double dsteps = 500.0;
  static double s1, s2, s3, tmp1, tmp2, tmp3;
  static bool reverse = false;
  if (fade == false) {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB(from[0], from[1], from[2]);
    }
    s1 = double((to[0] - from[0])) / dsteps; 
    s2 = double((to[1] - from[1])) / dsteps; 
    s3 = double((to[2] - from[2])) / dsteps; 
    tmp1 = from[0], tmp2 = from[1], tmp3 = from[2];
    fade = true;
  }

  if (!reverse) 
  {
    tmp1 += s1;
    tmp2 += s2; 
    tmp3 += s3; 
  }
  else 
  {
    tmp1 -= s1;
    tmp2 -= s2; 
    tmp3 -= s3; 
  }

  for (j = 0; j < NUM_LEDS; j++)
    leds[j] = CRGB((int)round(tmp1), (int)round(tmp2), (int)round(tmp3)); 
  FastLED.show(); 
  delay(5);

  counter++;
  if (counter == (int)dsteps) {
    reverse = !reverse;
    tmp1 = to[0], tmp2 = to[1], tmp3 = to[2];
    counter = 0;
  }
}

void soundReactive(int analogRaw) {

 int sanityValue = sanityBuffer->computeAverage();
 if (!(abs(analogRaw - sanityValue) > BUFFER_DEVIATION)) {
    sanityBuffer->setSample(analogRaw);
 }
  analogRaw = fscale(MIC_LOW, MIC_HIGH, MIC_LOW, MIC_HIGH, analogRaw, 0.4);

  if (samples->setSample(analogRaw))
    return;
   
  uint16_t longTermAverage = longTermSamples->computeAverage();
  uint16_t useVal = samples->computeAverage();
  longTermSamples->setSample(useVal);

  int diff = (useVal - longTermAverage);
  if (diff > 5)
  {
    if (globalHue < 235)
    {
      globalHue += hueIncrement;
    }
  }
  else if (diff < -5)
  {
    if (globalHue > 2)
    {
      globalHue -= hueIncrement;
    }
  }


  int curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)useVal, 0);
  //int curshow = map(useVal, MIC_LOW, MIC_HIGH, 0, NUM_LEDS)

  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (i < curshow)
    {
      leds[i] = CHSV(globalHue + hueOffset + (i * 2), 255, 255);
    }
    else
    {
      leds[i] = CRGB(leds[i].r / fadeScale, leds[i].g / fadeScale, leds[i].b / fadeScale);
    }
   
  }
  delay(5);
  FastLED.show(); 
}

void connectToWifi() {
   WiFi.mode(WIFI_STA);
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i] = CHSV(0, 0, 0);
  }
  leds[0] = CRGB(0, 255, 0);
  FastLED.show();

  int i = 0;
  while (WiFi.status() != WL_CONNECTED)
  { // Wait for the Wi-Fi to connect
    delay(1000);
    Serial.print(++i);
    Serial.print(' ');
  }
  Serial.println('\n');
  Serial.println("Connection established!");
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer
  leds[0] = CRGB(0, 0, 255);
  FastLED.show();
  lastReceived = millis();
}
float fscale(float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve)
{

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;

  // condition curve parameter
  // limit range

  if (curve > 10)
    curve = 10;
  if (curve < -10)
    curve = -10;

  curve = (curve * -.1);  // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
  curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function

  // Check for out of range inputValues
  if (inputValue < originalMin)
  {
    inputValue = originalMin;
  }
  if (inputValue > originalMax)
  {
    inputValue = originalMax;
  }

  // Zero Refference the values
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin)
  {
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd;
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float

  // Check for originalMin > originalMax  - the math for all other cases i.e. negative numbers seems to work out fine
  if (originalMin > originalMax)
  {
    return 0;
  }

  if (invFlag == 0)
  {
    rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
  }
  else // invert the ranges
  {
    rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
  }

  return rangedValue;
}
 

nikolz

Well-known member
предположу что у вас происходит просадка блока питания при импульсах.
чтобы это проверить
надо поставить диод и после него очень большой кондер хорошо бы суперкондер.
или взять очень мощный блок питания.
---------------
попробуйте посмотреть как меняется потребляемый ток
 

Сергей_Ф

Moderator
Команда форума
@OneDrag1 как я помню, мне не удалось добиться работы с FastLed на esp.
Попробуйте NeoPixelBus_by_Makuna в режиме
NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod>
у меня работало устойчиво.
Хотя новые версии Adafruit NeoPixel должны работать "из коробки". Тоже проверьте.
И запитайте ecp slave от отдельного источника питания. Поставьте резистор 100Ом, как уже сказали на сигнальную линию.
 

nikolz

Well-known member
относительно программы
я бы переписал как многозадачную с прерываниями на Си
будет быстрее работать и не тратить время на пустые циклы.
кроме того вы используете режим AP
но можно через роутер в режиме станций работать.
позволяет более гибко управлять режимом ESP
 

=AK=

New member
Любой. На нем совсем мизерная мощность рассеивается.
мкФ я так понимаю это емкость а на сколько вольт конденсатор?
Если он подключен к шине питания 3.3В, значит, должен выдерживать 3.3 В плюс какой-то разумный допуск. Больше 3.6В на ESP все равно подавать нельзя, может сдохнуть, на этом фоне сдохнувший кондер уже никого интересовать не будет. То есть, на как минимум на 4В или больше.
 

nikolz

Well-known member
попробуйте включить только штуки три LED
если проблема в питании то помехи исчезнут.
 

OneDrag1

New member
@OneDrag1 как я помню, мне не удалось добиться работы с FastLed на esp.
Попробуйте NeoPixelBus_by_Makuna в режиме
NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod>
у меня работало устойчиво.
Хотя новые версии Adafruit NeoPixel должны работать "из коробки". Тоже проверьте.
И запитайте ecp slave от отдельного источника питания. Поставьте резистор 100Ом, как уже сказали на сигнальную линию.
Доберусь до дома, установлю библиотеку Adafruit NeoPixel, я тоже слышал что она на порядок быстрее работает
Приобрету кондеры и резисторы.. буду побывать. Спасибо!
 

OneDrag1

New member
Любой. На нем совсем мизерная мощность рассеивается.

Если он подключен к шине питания 3.3В, значит, должен выдерживать 3.3 В плюс какой-то разумный допуск. Больше 3.6В на ESP все равно подавать нельзя, может сдохнуть, на этом фоне сдохнувший кондер уже никого интересовать не будет. То есть, на как минимум на 4В или больше.
Спасибо за разъяснения, будем пробывать
 

OneDrag1

New member
nikolz,
относительно программы
я бы переписал как многозадачную с прерываниями на Си
Ну.. для меня это пока очень тёмный лес((

попробуйте включить только штуки три LED
если проблема в питании то помехи исчезнут.
Всм? Прям 3 светодиода на ленте? Доберусь до дома скоро, по пробую
 

tretyakov_sa

Moderator
Команда форума
Все это происходит от программного wifi на esp. Прочитайте вот это:
FastLED/FastLED
Adafruit NeoPixel работает без артефактов, но вы будите получать отвал wifi и Hardware Watchdog или Exception. Похоже это тот случай когда требуется отдельный МК для работы с лентой.
 

Сергей_Ф

Moderator
Команда форума
@tretyakov_sa ну не все так катастрофично. У меня работает в нескольких проектах с интенсивным обменом по wifi.
 

OneDrag1

New member
@OneDrag1 может все таки лента? У меня работает.
Кольца на 24 диода уж точно.
Спецально залил демо скетч скетч на Ардуино нано воспроизводит хорошо без глюков, стабильно... на ленту не грешу
А на ESP помогает выпрямительный диод Шотке.. и то лечит но не полностью.. может какие то его аналоги этого диода есть? может они помогут еще лучше?
Попробуйте NeoPixelBus_by_Makuna в режиме
NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod>
Библиотеку "NeoPixelBus_by_Makuna" я поставлю... а что значит "в режиме
NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod>" не знаю как
И более что меня пугает, даже если этот LED движок будет идеально работать с ESP, даже не представляю как им заменить глючащий Fast.LED в своем проекте
 

tretyakov_sa

Moderator
Команда форума
@OneDrag1 может все таки лента? У меня работает.
Кольца на 24 диода уж точно.
Мы заливали один и тот же бинарник и испытывали в разных местах с различными роутерами. На одном роутере все работает сутками. На двух других обваливается через 40-60 минут. Там где это происходило поставили 12 одинаковых устройств с лентами и все глючило как и с одним устройством. Затем заменили роутер другим и глюки пропали. В библиотеке Adafruit_NeoPixel отключили прерывания, глюков связанных с роутерами не стало. Любые роутеры и любые прошивки работали. Но появились артефакты на лентах. Если отключить wifi совсем все работает как часы.
 
Сверху Снизу