psieg / Lightpack

Lightpack and Prismatik open repository
GNU General Public License v3.0
1.56k stars 188 forks source link

Using an ESP8266 (WemosD1mini) and WS2801 led strip works - but stops working after reboot #294

Open JorinL opened 4 years ago

JorinL commented 4 years ago

Hey there,

I used Ambibox with my ESP8266 (WemosD1mini) and WS2801 led strip and wanted to change to your much better Prismatik version. It works well till I reboot my machine.

After that the Strip wont light up and the strip does not longer get used by Prismatik. I have to reflash it with Arduino IDE to make it work again. Ambibox started in that situation just starts the ambilight.

Probably missing magic word or something? Or a thing of timing? Would like to get that fixed - you Prismatik is so much better. :-D

EDIT - adding infos

Thanks for your work.

zomfg commented 4 years ago

What happens if you powercycle the ESP instead of reflashing?

JorinL commented 4 years ago

Oh sorry! Could have written that info ;-)

Powercycle the ESP or using the reset switch don't bring it to live again.

My ESP sketch:

#include "FastLED.h"
#define ANALOG_MODE_AVERAGE  0
#define ANALOG_MODE_LAST_LED 1
#define FASTLED_ESP8266_D1_PIN_ORDER
#include <ArduinoOTA.h>

/**************************************
   S E T U P
   set following values to your needs
 **************************************/

#define INITIAL_LED_TEST_ENABLED true
#define INITIAL_LED_TEST_BRIGHTNESS 32  // 0..255
#define INITIAL_LED_TEST_TIME_MS 2000  // 10..

// Number of leds in your strip. set to "1" and ANALOG_OUTPUT_ENABLED to "true" to activate analog only
// As of 26/1/2017:
// 582 leaves ZERO bytes free and this
// 410 is ok
// tested with 500 leds and is fine (despite the warning)
#define MAX_LEDS 43

// type of your led controller, possible values, see below
//#define LED_TYPE APA102
#define LED_TYPE WS2801

// 3 wire (pwm): NEOPIXEL BTM1829 TM1812 TM1809 TM1804 TM1803 UCS1903 UCS1903B UCS1904 UCS2903 WS2812 WS2852
//               S2812B SK6812 SK6822 APA106 PL9823 WS2811 WS2813 APA104 WS2811_40 GW6205 GW6205_40 LPD1886 LPD1886_8BIT 
// 4 wire (spi): LPD8806 WS2801 WS2803 SM16716 P9813 APA102 SK9822 DOTSTAR

// For 3 wire led stripes line Neopixel/Ws2812, which have a data line, ground, and power, you just need to define DATA_PIN.
// For led chipsets that are SPI based (four wires - data, clock, ground, and power), both defines DATA_PIN and CLOCK_PIN are needed

// DATA_PIN, or DATA_PIN, CLOCK_PIN
//#define LED_PINS 6        // 3 wire leds
#define LED_PINS D3, D2  // 4 wire leds

#define COLOR_ORDER RBG  // colororder of the stripe, set RGB in hyperion

#define OFF_TIMEOUT 0    // ms to switch off after no data was received, set 0 to deactivate

// analog rgb uni color led stripe - using of hyperion smoothing is recommended
// ATTENTION  this pin config is default for atmega328 based arduinos, others might work to
//            if you have flickering analog leds this might be caused by unsynced pwm signals
//            try other pins is more or less the only thing that helps
#define ANALOG_OUTPUT_ENABLED false
#define ANALOG_MODE           ANALOG_MODE_LAST_LED  // use ANALOG_MODE_AVERAGE or ANALOG_MODE_LAST_LED
#define ANALOG_GROUND_PIN     8                     // additional ground pin to make wiring a bit easier
#define ANALOG_RED_PIN        9
#define ANALOG_GREEN_PIN      10
#define ANALOG_BLUE_PIN       11

// overall color adjustments
#define ANALOG_BRIGHTNESS_RED   255              // maximum brightness for analog 0-255
#define ANALOG_BRIGHTNESS_GREEN 255              // maximum brightness for analog 0-255
#define ANALOG_BRIGHTNESS_BLUE  255              // maximum brightness for analog 0-255

#define BRIGHTNESS 255                      // maximum brightness 0-255
#define DITHER_MODE BINARY_DITHER           // BINARY_DITHER or DISABLE_DITHER
#define COLOR_TEMPERATURE CRGB(255,255,255) // RGB value describing the color temperature
#define COLOR_CORRECTION  TypicalSMD5050
//#define COLOR_CORRECTION  TypicalLEDStrip   // predefined fastled color correction
//#define COLOR_CORRECTION  CRGB(255,255,255) // or RGB value describing the color correction

// Baudrate, higher rate allows faster refresh rate and more LEDs
//#define serialRate 460800      // use 115200 for ftdi based boards
#define serialRate 115200     // use 115200 for ftdi based boards
//#define serialRate 500000         // use 115200 for ftdi based boards

/**************************************
   A D A L I G H T   C O D E
   no user changes needed
 **************************************/

// Adalight sends a "Magic Word" (defined in /etc/boblight.conf) before sending the pixel data
uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i;

unsigned long endTime;

// Define the array of leds
CRGB leds[MAX_LEDS];

// set rgb to analog led stripe
void showAnalogRGB(const CRGB& led) {
  if (ANALOG_OUTPUT_ENABLED) {
    byte r = map(led.r, 0,255,0,ANALOG_BRIGHTNESS_RED);
    byte g = map(led.g, 0,255,0,ANALOG_BRIGHTNESS_GREEN);
    byte b = map(led.b, 0,255,0,ANALOG_BRIGHTNESS_BLUE);
    analogWrite(ANALOG_RED_PIN  , r);
    analogWrite(ANALOG_GREEN_PIN, g);
    analogWrite(ANALOG_BLUE_PIN , b);
  }
}

// set color to all leds
void showColor(const CRGB& led) {
  #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false
  LEDS.showColor(led);
  #endif
  showAnalogRGB(led);
}

// switch of digital and analog leds
void switchOff() {
  #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false
  memset(leds, 0, MAX_LEDS * sizeof(struct CRGB));
  FastLED.show();
  #endif
  showAnalogRGB(leds[0]);
}

// function to check if serial data is available
// if timeout occured leds switch of, if configured
bool checkIncommingData() {
  boolean dataAvailable = true;
  while (!Serial.available()) {
    if ( OFF_TIMEOUT > 0 && endTime < millis()) {
      switchOff();
      dataAvailable = false;
      endTime = millis() + OFF_TIMEOUT;
    }
  }

  return dataAvailable;
}

// main function that setups and runs the code
void setup() {
  WiFi.forceSleepBegin();
  Serial.begin(serialRate);

  // analog output
  if (ANALOG_OUTPUT_ENABLED) {
    // additional ground pin to make wiring a bit easier
    pinMode(ANALOG_GROUND_PIN, OUTPUT);
    digitalWrite(ANALOG_GROUND_PIN, LOW);
    pinMode(ANALOG_BLUE_PIN , OUTPUT);
    pinMode(ANALOG_RED_PIN  , OUTPUT);
    pinMode(ANALOG_GREEN_PIN, OUTPUT);
  }

  int ledCount = MAX_LEDS;
  if (ANALOG_MODE == ANALOG_MODE_LAST_LED) {
    ledCount--;
  }

  #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false
    FastLED.addLeds<LED_TYPE, LED_PINS, COLOR_ORDER>(leds, ledCount);
  #endif

  // color adjustments
  FastLED.setBrightness ( BRIGHTNESS );
  FastLED.setTemperature( COLOR_TEMPERATURE );
  FastLED.setCorrection ( COLOR_CORRECTION );
  FastLED.setDither     ( DITHER_MODE );

  // initial RGB flash
  #if INITIAL_LED_TEST_ENABLED == true
  for (int v=0;v<INITIAL_LED_TEST_BRIGHTNESS;v++)
  {
    showColor(CRGB(v,v,v));  
    delay(INITIAL_LED_TEST_TIME_MS/2/INITIAL_LED_TEST_BRIGHTNESS);
  }

  for (int v=0;v<INITIAL_LED_TEST_BRIGHTNESS;v++)
  {
    showColor(CRGB(v,v,v));  
    delay(INITIAL_LED_TEST_TIME_MS/2/INITIAL_LED_TEST_BRIGHTNESS);
  }
  #endif
  showColor(CRGB(0, 0, 0));

  Serial.print("Ada\n"); // Send "Magic Word" string to host

  boolean transmissionSuccess;
  unsigned long sum_r, sum_g, sum_b;

  // loop() is avoided as even that small bit of function overhead
  // has a measurable impact on this code's overall throughput.
  for(;;) {
    // wait for first byte of Magic Word
    for (i = 0; i < sizeof prefix; ++i) {
      // If next byte is not in Magic Word, the start over
      if (!checkIncommingData() || prefix[i] != Serial.read()) {
        i = 0;
      }
    }

    // Hi, Lo, Checksum
    if (!checkIncommingData()) continue;
    hi = Serial.read();
    if (!checkIncommingData()) continue;
    lo = Serial.read();
    if (!checkIncommingData()) continue;
    chk = Serial.read();

    // if checksum does not match go back to wait
    if (chk != (hi ^ lo ^ 0x55)) continue;

    memset(leds, 0, MAX_LEDS * sizeof(struct CRGB));
    transmissionSuccess = true;
    sum_r = 0;
    sum_g = 0;
    sum_b = 0;

    int num_leds = min ( MAX_LEDS, (hi<<8) + lo + 1 );

    // read the transmission data and set LED values
    for (int idx = 0; idx < num_leds; idx++) {
      byte r, g, b;
      if (!checkIncommingData()) {
        transmissionSuccess = false;
        break;
      }
      r = Serial.read();
      if (!checkIncommingData()) {
        transmissionSuccess = false;
        break;
      }
      g = Serial.read();
      if (!checkIncommingData()) {
        transmissionSuccess = false;
        break;
      }
      b = Serial.read();
      leds[idx].r = r;
      leds[idx].g = g;
      leds[idx].b = b;
      #if ANALOG_OUTPUT_ENABLED == true && ANALOG_MODE == ANALOG_MODE_AVERAGE
          sum_r += r;
          sum_g += g;
          sum_b += b;
      #endif
    }

    // shows new values
    if (transmissionSuccess) {
      endTime = millis() + OFF_TIMEOUT;
      #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false
      FastLED.show();
      #endif

      #if ANALOG_OUTPUT_ENABLED == true
        #if ANALOG_MODE == ANALOG_MODE_LAST_LED
          showAnalogRGB(leds[MAX_LEDS-1]);
        #else
          showAnalogRGB(CRGB(sum_r/MAX_LEDS, sum_g/MAX_LEDS, sum_b/MAX_LEDS));
         #endif
      #endif
    }
  }
} // end of setup

void loop() {
  // Not used. See note in setup() function.
}
JorinL commented 4 years ago

Mh did not find any solution yet :-/

JorinL commented 4 years ago

Found out, that if I read out the serial output from the esp - and then start prismatik - it works. Like the esp sends something and gets blocked by that....?!

zomfg commented 4 years ago

Ah yes ESPs show some log on boot looks like there are ways around it https://forum.arduino.cc/index.php?topic=535687.0

JorinL commented 4 years ago

There is no answer inside that thread - he asks on the last page again - "how to - must be possible!?"

Also I found out that opening the port is enough to let Prismatik work again - could it be that there is a not that nice way used to opening the port?

I just opened the serial monitor - got nothing - quit it and opened Prismatik -> works.

zomfg commented 4 years ago

Try setting Prismatik logs to max in and checking them while testing

JorinL commented 4 years ago

I' dont really see an ERROR in the Log. :-/ beside:

10:32:14:360 Debug: Start main event loop: lightpackApp.exec();
10:32:14:405 Debug: void __cdecl SettingsWindow::ledDeviceCallSuccess(bool) false 1 LedDeviceManager(0x23605766850)
10:32:14:405 Debug: void __cdecl SettingsWindow::updateTrayAndActionStates(void)
10:32:14:409 Debug: void __cdecl SettingsWindow::ledDeviceCallSuccess(bool) Backlight::StatusDeviceError
10:32:14:409 Debug: void __cdecl SettingsWindow::ledDeviceCallSuccess(bool) false -1 LedDeviceManager(0x23605766850)
10:32:14:409 Debug: void __cdecl SettingsWindow::ledDeviceCallSuccess(bool) Backlight::StatusDeviceError

Prismatik.0.log

JorinL commented 4 years ago

Any Ideas on that log? :-)

Would be so cool if it works.

zomfg commented 4 years ago

I ran your sketch on a D1, I changed it a bit to use 3pins (ws2812) With the board plugged in and Prismatik pre-configured, when I launch Prismatik it instantly works. I can quit/relaunch Prismatik, it still works without touching the board. When I reboot, as soon as I launch Prismatik it works without touching the board. At no point I need to reflash it.

The only thing that breaks: if I unplug/replug the usb while Prismatik is running, it won't pick it up. But as soon as Prismatik restarts it's all good.

JorinL commented 4 years ago

Mh ok - strange.

I have an external 5v power supply on the strip - usb is powering the wemos d1. I can test one thing - the 5V power is starting after the USB power... evtl thats a problem.

JorinL commented 4 years ago

Mh no change...

From reflashing I went to just reading out the com port... That was enough - so it is no reflash needed.

But I can start Ambi Box it works directly O_o I don't get it.

*Edit - so no change of power or usb port does anything.

As soon as I open Arduino IDE -> Serial Monitor (without anything viewable in the monitor) on the COM of the Adalight. Close it and open Prismatik -> Works.

Reboot: Open Prismatik -> Nothing turns on - but Symbol says lights should be on. Close Prismatik -> Arduino IDE -> Serial Monitor (without anything viewable in the monitor) - close it Open Prismatik -> works.

Opening the com port with putty does not fix it.

JorinL commented 4 years ago

I have a workaround for me:

I reset the ESP8266 with esptool - then it works.

Arduino IDE and Pyhthon installed it works with one line for me:

python %homepath%\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\tools\esptool\esptool.py --port COM1 run

Or as full batch:

TASKKILL /IM Prismatik.exe /F /T
python %homepath%\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\tools\esptool\esptool.py --port COM1 run
timeout 3
start "" "C:\Program Files\Prismatik\Prismatik.exe"
exit