WS2812B LED strip and ESP8266 shows wrong colors

Posted on
  • Hi! I finally got Espruino running on my ESP8266 12-E NodeMCU, but I'm having some issues talking to my strip correctly. When I was controlling my strip using Arduino and C before, I hooked up the data pin to RX, which worked just fine. Now I'm (apparently) supposed to hook it up to D2, or any of the pins near it, but the colors are all wrong.

    When I do something like:

    require("neopixel").write(NodeMCU.D2, [255, 0, 0]);
    

    The first LED shines 70% yellow 30% green, if I do [0, 255, 0] it's 90% white 10% purple, and if I do [0, 0, 255] it's 80% white 20% blue (something like that).

    It's not red, green, or blue as it's supposed to be. Any clue why?

    Oh, and I also tried this:

    require("ESP8266").neopixelWrite(NodeMCU­.D2, [255,0,0]);
    

    but that yields the same result.


    EDIT: I found this code in another post, which actually works fine:

    E.setClock(80);
    var i = 0;
    var esp8266 = require("ESP8266");
    function colorLeds(red, green, blue) {
      var data = [];
      for (var i=0; i<3; i++) {
        data.push(green);
        data.push(red);
        data.push(blue);
      }
      console.log(data);
      esp8266.neopixelWrite(NodeMCU.D2, data);
    }
    setInterval(function() {
      i++;
      if ((i % 3) === 0) {
          colorLeds(255,0,0);
      } else if ((i%3) === 1) {
          colorLeds(0,255,0);
      } else {
          colorLeds(0,0, 255);
      }
    }, 1000);
    

    BUT! If I simply comment out the setInterval() and just write colorLeds(255, 0, 0) they all shine with a purple hue. What on earth???

  • Turns out I have to run the code twice. The first time I run it, it doesn't make the colors just right, but the second time I run it, the colors are fine.

    Oh well.

  • Ahh, thanks for letting us know! More than likely it's the state of the pin at boot that is the issue. Probably just calling esp8266.neopixelWrite(NodeMCU.D2, [0,0,0]); at startup would be enough.

  • Just FYI in the new 1v95, the neopixel module is not part of esp8266, usage is like any other Espruino platform:

    // flash an 8 LED neopixel array in a rainbow pattern
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    
    var rgb = new Uint8ClampedArray(led_count * 3);
    var pos = 0;
    
    function getPattern() {
      pos++;
      for (var i=0;i<rgb.length;) {
        rgb[i++] = (1 + Math.sin((i+pos)*0.1324)) * 127;
        rgb[i++] = (1 + Math.sin((i+pos)*0.1654)) * 127;
        rgb[i++] = (1 + Math.sin((i+pos)*0.1)) * 127;
      }
      return rgb;
    }
    setInterval(function() {
      require("neopixel").write(neoPin, getPattern());
    }, 100);
    
  • @user85573, if by chance you have the setup, could you do some timing on these variations of the code and post the results?

    Variation 1(a))

    // V1a - flash an 8 LED neopixel array in a rainbow pattern
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    var rgb = new Uint8ClampedArray(led_count * 3);
    var pos = 0;
    function getPattern() {
      pos++;
      for (var i=0;i<rgb.length;) {
        rgb[i++] = (1 + Math.sin((i+pos)*0.1324)) * 127;
        rgb[i++] = (1 + Math.sin((i+pos)*0.1654)) * 127;
        rgb[i++] = (1 + Math.sin((i+pos)*0.1)) * 127;
      }
      return rgb;
    }
    setInterval(function() {
      var t0 = getTime();
      require("neopixel").write(neoPin, getPattern());
      console.log(getTime() - t0);
    }, 200); // may need to change to allow console to write
    

    Variation 2(a))

    // V2a - flash an 8 LED neopixel array in a rainbow pattern
    var neo = require("neopixel");
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    var rgb = new Uint8ClampedArray(led_count * 3);
    var len = rgb.length;
    var m = 127;
    var r = 0.1324*m;
    var g = 0.1654*m;
    var b = 0.1*m;
    var pos = 0;
    function getPattern() {
      pos++;
      for (var i=0; i<len;) {
        rgb[i++] = m + Math.sin((i+pos)*r;
        rgb[i++] = m + Math.sin((i+pos)*g;
        rgb[i++] = m + Math.sin((i+pos)*b;
      }
      return rgb;
    }
    function bow() {
      var t0 = getTime();
      neo.write(neoPin, getPattern());
      console.log(getTime() - t0);
    }
    
    function onInit() {
      setInterval(bow,200); // may need to change to allow console to write
    }
    
    setTimeout(onInit, 1000);
    

    And as begin curious what the calculation vs communication times are:

    // V1b - flash an 8 LED neopixel array in a rainbow pattern
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    var rgb = new Uint8ClampedArray(led_count * 3);
    var pos = 0;
    function getPattern() {
      var t0 = getTime();
      pos++;
      for (var i=0;i<rgb.length;) {
        rgb[i++] = (1 + Math.sin((i+pos)*0.1324)) * 127;
        rgb[i++] = (1 + Math.sin((i+pos)*0.1654)) * 127;
        rgb[i++] = (1 + Math.sin((i+pos)*0.1)) * 127;
      }
      console.log(getTime() - t0);
      return rgb;
    }
    setInterval(function() {
      var t0 = getTime();
      require("neopixel").write(neoPin, getPattern());
    }, 200); // may need to change to allow console to write
    

    and

    // V2b - flash an 8 LED neopixel array in a rainbow pattern
    var neo = require("neopixel");
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    var rgb = new Uint8ClampedArray(led_count * 3);
    var len = rgb.length;
    var m = 127;
    var r = 0.1324*m;
    var g = 0.1654*m;
    var b = 0.1*m;
    var pos = 0;
    function getPattern() {
      pos++;
      for (var i=0; i<len;) {
        rgb[i++] = m + Math.sin((i+pos)*r;
        rgb[i++] = m + Math.sin((i+pos)*g;
        rgb[i++] = m + Math.sin((i+pos)*b;
      }
      console.log(getTime() - t0);
      return rgb;
    }
    function bow() {
      neo.write(neoPin, getPattern());
    }
    
    function onInit() {
      setInterval(bow,200); // may need to change to allow console to write
    }
    
    setTimeout(onInit, 1000);
    

    The results may shed some light on how coding in Espruino can matter for execution speed.

    (The different start-up is not part of the timings. It just makes sure that the upload is not interfering)

  • This is the reason you have to run a extra neopixel.write() command:

    Every time you upload with reset some extra pinMode commands are included:

    >reset()
    =undefined
     _____                 _
    |   __|___ ___ ___ _ _|_|___ ___
    |   __|_ -| . |  _| | | |   | . |
    |_____|___|  _|_| |___|_|_|_|___|
              |_| http://espruino.com
     1v95.3493 Copyright 2017 G.Williams
    Espruino is Open Source. Our work is supported
    only by sales of official boards and donations:
    http://espruino.com/Donate
    Flash map 4MB:1024/1024, manuf 0xe0 chip 0x4016
    >dump()
    pinMode(D0, "input_pullup", true);
    pinMode(D4, "input_pullup", true);
    pinMode(D5, "input_pullup", true);
    pinMode(D12, "input_pullup", true);
    pinMode(D13, "input_pullup", true);
    pinMode(D14, "input_pullup", true);
    pinMode(D15, "input_pullup", true);
    =undefined
    
    

    This is very helpful, because you always start with the same defined pinMode for all pins.

    I suggest to include a pinMode() for pins you use different.

    var neo = require("neopixel");
    var neoPin = NodeMCU.D4;  // D2
    pinMode(neoPin,'output');
    neo.write(neoPin, [25, 0, 0]);  // 255 is to bright for me :)
    

    1 Attachment

    • IMG_7975.jpg
  • v1(a)
    0.030798
    0.030268
    0.030341
    0.03037
    0.030436
    0.030451
    0.030515
    0.030617
    0.03060900000
    0.030679
    0.03064899999
    0.030679
    0.03073700000
    0.030856
    0.030821
    0.030756
    0.030841
    0.030878
    0.03080600000
    0.03079500000
    0.03083700000
    0.030755
    0.030751
    0.030744
    0.03070499999
    0.030687

    v2(a)
    0.023461
    0.02335299999
    0.02293
    0.02335500000
    0.02342099999
    0.02307199999
    0.023368
    0.02320199999
    0.02309100000
    0.02331900000
    0.02320100000
    0.02319399999
    0.02319899999
    0.02302300000
    0.02329700000
    0.023054
    0.022922
    0.023505
    0.02313600000
    0.02292699999
    0.023507
    0.02306500000
    0.02308200000
    0.02353299999

    v2(b)
    0.03001599999
    0.030012
    0.03011499999
    0.03015499999
    0.03018
    0.03026499999
    0.03029300000
    0.03027200000
    0.030347
    0.03035300000
    0.03045099999
    0.030484
    0.03047499999
    0.03058799999
    0.03059
    0.03054
    0.03057
    0.030644
    0.03053399999
    0.03054
    0.030553
    0.030486

    v2(c)
    0.02292799999
    0.02256799999
    0.02212799999
    0.02253500000
    0.02267299999
    0.02225899999
    0.02259800000
    0.02252500000
    0.02243099999
    0.02248499999
    0.02235399999
    0.02252299999
    0.02236899999
    0.02222599999
    0.02252699999
    0.02229300000
    0.02217800000
    0.02258200000

    v2 variants needed some remediation on var t0, along with parens

    // V2b - flash an 8 LED neopixel array in a rainbow pattern
    var neo = require("neopixel");
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    var rgb = new Uint8ClampedArray(led_count * 3);
    var len = rgb.length;
    var m = 127;
    var r = 0.1324*m;
    var g = 0.1654*m;
    var b = 0.1*m;
    var pos = 0;
    var t0;
    function getPattern() {
      pos++;
      for (var i=0; i<len;) {
        rgb[i++] = m + Math.sin((i+pos)*r);
        rgb[i++] = m + Math.sin((i+pos)*g);
        rgb[i++] = m + Math.sin((i+pos)*b);
      }
      console.log(getTime() - t0);
      return rgb;
    }
    function bow() {
      t0 = getTime();
      neo.write(neoPin, getPattern());
    }
    function onInit() {
      setInterval(bow,200); // may need to change to allow console to write
    }
    setTimeout(onInit, 1000);
    
  • @user85573, thank you very much for you effort... (and mending the t0... copy/paste shoving code around tripped me... and still is. May be does not matter because the times as captured by you show already a nice difference...) My intensions for timing instrumentation are never to include console out... but I missed that part too. The correct code for 2(b) would be more along these lines:

    Variation 2(b))

    // V2b - flash an 8 LED neopixel array in a rainbow pattern
    var neo = require("neopixel");
    var led_count = 8;
    var neoPin = NodeMCU.D4;
    var rgb = new Uint8ClampedArray(led_count * 3);
    var len = rgb.length;
    var m = 127;
    var r = 0.1324*m;
    var g = 0.1654*m;
    var b = 0.1*m;
    var pos = 0;
    function getPattern() {
      var t0 = getTime();
      pos++;
      for (var i=0; i<len;) {
        rgb[i++] = m + Math.sin((i+pos)*r;
        rgb[i++] = m + Math.sin((i+pos)*g;
        rgb[i++] = m + Math.sin((i+pos)*b;
      }
      console.log(getTime() - t0);
      return rgb;
    }
    function bow() {
      neo.write(neoPin, getPattern());
    }
    function onInit() {
      setInterval(bow,200); // may need to change to allow console to write
    }
    setTimeout(onInit, 1000);
    

    I was missing line 13 completely and line 20 I should have made to read:

    t0 = getTime() - t0;
    console.log(t0);
    

    But anyway, thanks for timing it for me.

    Conclusion is that doing some optimization to prevent (source code) interpreter to do some things all over again saved about 20..25%. The numbers also show that the write is practically neglectable compared to the trigonometric calculations.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

WS2812B LED strip and ESP8266 shows wrong colors

Posted by Avatar for MortenMoulder @MortenMoulder

Actions