Results 1 to 4 of 4

Thread: Wemos D1 R2 (ESP8266) and Teensy 3.2 Pixel Controller

  1. #1
    Join Date
    Jul 2013
    Posts
    109
    Post Thanks / Like

    Default Wemos D1 R2 (ESP8266) and Teensy 3.2 Pixel Controller

    I've been doing some testing with a Wemos D1 R2 and Teensy 3.2 for pixel control. I've been successful in driving 16 universes of E1.31 from Vixen 3. The Wemos receives the E1.31 data over WiFi and sends it to the Teensy over serial at 3,000,000 baud. The Teensy drives the pixels. I am using 12 volt WS2811 pixels using FastLED and the OctoWS2811 parallel output. That's a total of 2,728 pixels. The parallel output gives you 8 output pins and all the pixel data is written out simultaneously. I am getting a consistent 20 FPS.

    I'd be happy to share the code if anyone is interested.

  2. Likes Jack Stevens liked this post
  3. #2
    Join Date
    Dec 2014
    Location
    Florida
    Posts
    895
    Post Thanks / Like

    Default Re: Wemos D1 R2 (ESP8266) and Teensy 3.2 Pixel Controller

    Protip: Always just post your code for people to look at. Don't just post to ask if interested. If interested, we'll just look at it! If not we wont.

    I imagine there's a bit more latency with this scheme. First the ESP has to receive, buffer and start transmitting the pixel data. At 3M baud it would take 50ms to blast out 2,728 pixels worth of data. Then afterwords the Teensy would have to start outputting the pixel data. Even if you start transmitting the pixel data before the serial finishes the entire frame, the last of the pixel data is still at least 50ms delayed.

    So I imagine the scheme is at least one frame delayed from sACN reception till it hit the last pixel, or a little more. I'd be interested to see how you solved that, if you did.

    The Falcon controllers are a similar multi-processor scheme. a uController receives the data and passes it to an FPGA to drive the pixels. They reduced latency by using a wide parallel bus to transfer the data.
    www.billporter.info
    2014 Christmas: 1 Channel; a new house and a crazy plan.
    2015 Halloween: 2500 Channels; 3 songs. Christmas: 4500 Channels; 6 songs. Custom Wifi Pixel/Renard Controllers
    2016 Halloween: 6500 Channels; 4 songs. Christmas: 11,000 Channels; 4 songs.

  4. #3
    Join Date
    Jul 2013
    Posts
    109
    Post Thanks / Like

    Default Re: Wemos D1 R2 (ESP8266) and Teensy 3.2 Pixel Controller

    I have not done anything to account for latency but if there is any I can't notice it. The music and pixel output is perfectly synced.

    Here is the code running on the Wemos:

    Code:
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    
    const int BUFFER_SIZE = 638;
    unsigned char PacketBuffer[BUFFER_SIZE]; //buffer to hold incoming packet data
    
    //WiFi Setup
    char ssid[] = "******";
    char pass[] = "******";
    IPAddress local_ip(192, 168, 1, 5);
    IPAddress gateway(192, 168, 1, 1);
    IPAddress subnet(255, 255, 255, 0);
    const int E131Port = 5568;
    WiFiUDP Eudp; //UDP socket for Unicast E1.31
    
    void setup()
    {
      Serial.begin(3000000);
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, pass); //Connect to Network
      WiFi.config(local_ip, gateway, subnet); //Set static IP information
      while (WiFi.status() != WL_CONNECTED)  //wait until we are connected
      {
        delay(500);
        Serial.println("Connecting");
      }
      Eudp.begin(E131Port); //Open E1.31 port
      pinMode(2, OUTPUT);
      digitalWrite(2, HIGH);
      Serial.println("Setup Complete");
    }
    
    void loop()
    {
      digitalWrite(2, HIGH);
    //Make sure we are still connected to the AP each time through the loop.
    if(WiFi.status() != WL_CONNECTED)
    {
      ESP.restart(); //restart the board 
    }
    
      /* Start by checking to see if a packet is available on the E1.31 port */
      int packetSize = Eudp.parsePacket(); //parse packet
      
      if (packetSize)
      {
        Eudp.read(PacketBuffer, BUFFER_SIZE); //read packet into buffer
        int count = checkE131Headers(PacketBuffer, BUFFER_SIZE); //pass data to see if it is E1.31
        if (count) //if it comes back genuine
        {
          digitalWrite(2, LOW);
          //Serial.print(PacketBuffer[114]);
          Serial.write("SAC"); //packet header 
          Serial.write(PacketBuffer, BUFFER_SIZE); //write packet to serial port 
          Serial.flush(); //flush transmit buffer at end of for loop
        }
      }
    } //end loop
    
    int checkE131Headers(unsigned char* messagein, int messagelength) 
    {
      if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) 
      {  
          int ChannelCount = messagein[123] * 256 + messagein[124]; // number of values plus start code
          return ChannelCount -1; //Return how many values are in the packet.
      }
      return 0;
    }
    Here is the code running on the Teensy 3.2:
    Code:
    #define USE_OCTOWS2811
    #include<OctoWS2811.h>
    #include <FastLED.h>
    
    void POST();
    void E131Received();
    
    //General Definitions
    const int ledpin = 13; //LED on board for monitoring
    const int BUFFER_SIZE = 638; //size of data buffer to hold E1.31 and ArtNet data
    const int E131_ADDRESS_OFFSET = 125; //byte 126 of the E1.31 packet contains channel 1 value
    const int E131_START_CODE = 0; 
    const int E131StartUniverse = 1; //First E1.31 universe
    const int E131UniverseCount = 16; //Total number of E1.31 universes being received
    int E131CurrentUniverse;  //Current universe we are processing 
    int StartLED = 0;
    const int NumLEDsPerUniverse = 170;
    int EndLED;
    
    // buffers for receiving data
    unsigned char DataBuffer[BUFFER_SIZE]; //buffer to hold incoming E1.31 and ArtNet Data
    unsigned char Header[3]; //header buffer
    
    
    //FastLED Parallel Output using OctoWS2811 on Teensy 
    //Ports: 2,14,7,8,6,20,21,5
    const int NUM_LEDS_PER_STRIP = 341;
    const int NUM_STRIPS = 8;
    CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
    const int NUM_LEDS = NUM_STRIPS * NUM_LEDS_PER_STRIP;
    const int ChannelWidth = 3; //each pixel needs 3 channels for control
    int Channel = 1; //current channel being used 
    
    
    void setup() 
    {
    pinMode(ledpin, OUTPUT);  //pin 13 to let us know if we are receiving any data
    digitalWrite(ledpin, LOW); //turn LED off
    Serial.begin(250000); //USB serial port for monitoring/debugging
    Serial1.begin(3000000); //ESP8266 serial connection
    LEDS.addLeds<OCTOWS2811, RGB>(leds, NUM_LEDS_PER_STRIP); //OctoWS2811 output on Teensy 3.2 
    LEDS.setCorrection(TypicalLEDStrip); //color correction 
    LEDS.setBrightness(255); //full brightness 
    delay(3000);
    POST(); //Run power on self test function each time board boots 
    Serial.println("Setup Completed");
    }
    
    void loop() 
    {
    //Reads serial data and determines what kind of data it is then processes it 
    if (Serial1.available() > 0) 
    {
    Serial1.readBytes(Header,3); //read 3 bytes at a time 
    if(Header[0] == 'S' && Header[1] == 'A' && Header[2] == 'C') //check for E1.31 Header
    {
      Serial1.readBytes(DataBuffer,BUFFER_SIZE); //read data into buffer 
      digitalWrite(ledpin, HIGH); //turn LED pin on for debugging 
      E131Received();
    }
    }
    
    else
    {
      digitalWrite(ledpin, LOW); 
    }
    
    }
    
    void POST() 
    {
       LEDS.showColor(CRGB(255, 0, 0)); //turn all pixels on red
       delay(1000);
       LEDS.showColor(CRGB(0, 255, 0)); //turn all pixels on green
       delay(1000);
       LEDS.showColor(CRGB(0, 0, 255)); //turn all pixels on blue
       delay(1000);
       FastLED.clear(); //clear pixels
       FastLED.show();
       Serial.println("POST Completed");
    }
    
    void E131Received() 
    {
      if(DataBuffer[114] >= E131StartUniverse && DataBuffer[114] <= E131UniverseCount) //first make sure the universe received is one we want to process
      {
    
      if(DataBuffer[114] == E131StartUniverse) //if current universe is the first in the series, reset all values
      {
        StartLED = 0;
        EndLED = NumLEDsPerUniverse;
        E131CurrentUniverse = E131StartUniverse;
      }
      
    if(DataBuffer[114] == E131CurrentUniverse && DataBuffer[108] == 100 && DataBuffer[115] == 114 && DataBuffer[116] == 11 && DataBuffer[118] == 161) //data integrity checks 
    {
          Channel = 1; //reset channel assignment to 1 each time through loop.
          for(int i = StartLED; i < EndLED; i++) //set values for 170 pixels. Max number per universe. 
          {
          leds[i] = CRGB(DataBuffer[E131_ADDRESS_OFFSET + Channel], DataBuffer[E131_ADDRESS_OFFSET + (Channel +1)], DataBuffer[E131_ADDRESS_OFFSET + (Channel + 2)]);
          Channel += ChannelWidth; //increase last channel number by channel width
          }
    }    
          if(DataBuffer[114] == E131UniverseCount) //we've processed all universes now send data to pixels 
          {
          FastLED.show();
          Serial.print("FPS: ");
          Serial.println(FastLED.getFPS());
          }
          else //not all universes have been received. Move on to the next one. 
          {
            StartLED += NumLEDsPerUniverse; //increase by 170
            EndLED += NumLEDsPerUniverse; //increase by 170
            E131CurrentUniverse++; //increase by 1 
          }
    }
    } //end function

  5. #4
    Join Date
    Apr 2015
    Posts
    31
    Post Thanks / Like

    Default Re: Wemos D1 R2 (ESP8266) and Teensy 3.2 Pixel Controller

    HI, I am also playing with Wemos D1 (Pro Mini with ext antenna), and I have managed to get 32 universes of ArtNet read in and then output to 5440 WS Pixel LEDs, running at a 25Hz refresh, using Jinx! as a PC application
    My Wemos is chattering away at 160MHz for this and it has been a serious task to get all my ducks in a row so as not to cause resets overruns etc etc
    I am sending 4 universes out of each output, and there are 8 outputs,. which just leaves one pin left for an indicator

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •