Page 1 of 4 123 ... LastLast
Results 1 to 10 of 39

Thread: Project to use a pixelstick type device as a FPP remote.

  1. #1
    Join Date
    Dec 2011
    Location
    UK S80 postcode
    Posts
    1,271
    Post Thanks / Like

    Default Project to use a pixelstick type device as a FPP remote.

    Hi, if you are wondering why an old thread has come to life after nearly 18 months. I was contacted with a view to playing a .FSEQ file on an ESPixelstick, this thread had the basis of the code needed but goes a little beyond as it also synchronises with FPP and uses an SD card to store the files. The new posts at this time are using parts of this post to create a standalone player (scrapped the FFP – for now) and used SPIFFS instead of an SD card.

    Hi, this is a work in progress code that with a change of ESP8266 enables a pixelstick type device to function as a FPP remote (not all features are included). That is instead of receiving e1.31 packets of data over a network, it reads data from an xlights .PSEQ file on an SD card. The file name and synchronization are dictated by a single packet sent every 16 frames by FPP.

    Simple over view:
    Set some variables.
    Initialize stuff.
    Read a file called ‘fortytwo.txt.’ from the SD card. This contains the number of the first channel & the number of channels we will be using. These are set as variables. In future some other stuff will be added.

    Main loop:
    Listen for an Udp packet FPP on channel 32320, when this arrives it will be one of three types:
    Start: Read file name – open file. Set the show running flag & current frame number to 0.
    Stop: Clear the show running flag & close file.
    Sync: Amend current frame number if required.

    At this point we have two options:
    The show isn’t running: Do nothing & go back to listen for Udp packets.
    The show is running: Read data from the SD card based on frame number and output to lights (WS2812b only at the moment).

    Code:
    /*
    The following code is still under development by Barnabybear, use it in your show at your own risk..
    This will enable a device like a pixelstick to function as a FPP remote:
    Reading it's data from an SD card sync'ed by a packet from an FPP master in remote mode.
     */
    
    #include <SPI.h>
    #include <SD.h>
    #include <NeoPixelBus.h>
    #include <ESP8266WiFi.h>
    #include <WiFiUDP.h>
    
    #define pixelCount; // number of channels (read from file).
    #define pixelPin 2  // make sure to set this to the correct pin changed from 8 by //PC//
    bool Debug = 1; // minimum debug.
    bool PSEQ_Headder_Debug = 0; // debug .PSEQ headder.
    bool Show_Running = 0; // flag 1= show running.
    const char* ssid = "your SSID";  // your network SSID
    const char* pass = "your PASSWORD";  // your network password
    IPAddress IP_Multicast_Out(239, 255, 0, 1); // doesn't realy do much in this code.
    unsigned int Port_Multicast_Out = 5568; // doesn't realy do much in this code.
    unsigned int localPort = 32320;      // local port to listen on
    //const int chipSelect = 15;  // only needed if you don't use GPIO 15 as CS (Chip Select).
    long int First_Channel = 0;  // first channel number in .PSEQ file (read from file).
    long int Number_Pix = 170; // number of pixels for 'NeoPixelBus'.
    long int Data_Offset;  // start of data in .PSEQ file (length of headder) (read from file).
    long int Number_Channels;  //  total number of channels in .PSEQ file (read from file).
    long int Step_Lenght;  // number of frames in .PSEQ file (read from file).
    int Frame_Time;  // FPS of of frames in .PSEQ file (read from file). 
    unsigned long Time_Start;
    int j;
    char PSEQ_Data_File[13];
    char packetBuffer[31]; // buffer to hold incoming packet
    long int Current_Step;  // code current step / frame number.
    long int Frame_Number;  // FPP packet current step / frame number.
    File dataFile;  // required by SD.h.
    NeoPixelBus strip = NeoPixelBus(Number_Pix, pixelPin); // required by NeoPixelBus.h.
    WiFiUDP Udp;
    
    void setup()
    {
       Serial_Initialize(); // Initialize serial.
       Neo_Pixel_Initialize(); // Initalize Neo pixels.
       SD_Initialize(); // Initialize SD card. 
       dataFile = SD.open("fortytwo.txt"); // open SD card file "fortytwo.txt"
       fortytwo_Read();  //read setup data from file fortytwo and set variables.
       dataFile.close(); // close SD card file "fortytwo.txt"
       WiFi_Initialize(); // Initialize WiFi.
       Udp.begin(localPort); // start lisening for Udp packets.
    }
    
    void loop()
    {
          int packetSize = Udp.parsePacket(); // parse packet from FPP.
      if (packetSize) { // check there is a packet.
        int len = Udp.read(packetBuffer, 31); // read the packet into buffer.
    
          switch(packetBuffer[7]){ // 3 actions dependant on type of FPP packet.
           
          case 0: // Start Packet
          for(int i = 17; i < 29; i++){ // file name bytes.
          PSEQ_Data_File[i -17] = (packetBuffer[i]); // read FPP file name.
          }
          Serial.print("0x00 = Start_Packet");  // debug print.
          Serial.print("  "); // debug print.
          Serial.println(PSEQ_Data_File); // debug print.
          PESQ_Headder_Read(); //call 'void PESQ_Headder_Read'.
          Show_Running = 1; // set fag to show running.
          Current_Step = 0; // reset current step / frame to zero.
          break;
              
          case 1: // End Packet //
          Serial.println("0x01 = End___Packet"); // debug print.
          Show_Running = 0; // set fag to show NOT running.
          dataFile.close(); // close current SD file.
          break;              
    
          case 2: // Sync Packet //
          Serial.println("0x02 = Sync__Packet"); // debug print.
          Frame_Number = (packetBuffer[10] * 256) + (packetBuffer[9]); // add 2 bytes to get frame number.
          Current_Step = Frame_Number; // overwrite currrent frame number with FPP sync frame number.
          break;           
        }     
      }   
          switch (Show_Running){ // 2 actions dependant on show running flag.
    
            case 0: // show NOT running, go back and check for FPP packets.
            break;
    
            case 1: // show running get data from SD card and output to lights.
            if (dataFile) { // check file open.
            while(Current_Step < (Step_Lenght+1)) { // if NOT at the end of the sequence.
            dataFile.seek(((Data_Offset) -1) + First_Channel + ((Number_Channels) * Current_Step)); // first read postion = (after the file headder) + (miss out unused channels). Subcequent read postion = as above + (the number of channels in file * the number of previous reads).
            for (j =0; j < Number_Pix; j++){ // loop based on number of channels / pixels to read
            strip.SetPixelColor(j,dataFile.read(),dataFile.read(),dataFile.read()); // read 3 current pixel values into Neo pixel buffer.              
           }
            delay(Frame_Time - 20); // delay untill correct time to send to pixels.
            strip.Show(); // send data to pixels.
           Current_Step++; // add 1 to the current step postion.
           Serial.print("."); // debug print.
           break; // to check for new packets for FPP.  
           }
    //       Show_Running = 0;
    //       Current_Step = 0;
           }
           }}
    //*************** void Serial_Initialize ***************//
      void Serial_Initialize(){
      // Open serial communications and wait for port to open:
      Serial.begin(115200); // debug print.
      while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only.
      }
      Serial.println("Serial initialized @ 115200.");
      }
    /////////////////////////////////////////////////////////
    
    //*************** void WiFi_Initialize ***************//
    void WiFi_Initialize(){
      WiFi.begin(ssid, pass);
      Serial.print("[Connecting]"); // debug print.
      Serial.print(ssid); // debug print.
      int tries=0;
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print("."); // debug print.
        tries++;
        if (tries > 30){
          break;  
        }}
        Serial.println("Connected."); // debug print.
        }
    /////////////////////////////////////////////////////////
    
    //*************** void Neo_Pixel_Initialize ***************//
      void Neo_Pixel_Initialize(){   
        strip.Begin(); // start neo pixel.
        strip.Show(); // set all to off.
        Serial.println("Neo Pixel initialized & set to all off."); // debug print.
      }
    /////////////////////////////////////////////////////////
    
    //*************** void SD_Initialize ***************//
        void SD_Initialize() {
      Serial.print("Initializing SD card... "); // debug print.
      if (!SD.begin()) {  // see if the card is present and can be initialized.
        Serial.println("Card failed, or not present"); // debug print.
        return;
      }
      Serial.println("Card initialized."); // debug print.
        }
    /////////////////////////////////////////////////////////
    
    //*************** void fortytwo_Read ***************//
        void fortytwo_Read() { // file on SD card with setup data - first channel number - number of channels.
        if (dataFile) {
          dataFile.seek(9); // set read pionter to correct byte.
          First_Channel = (((dataFile.read()-48) *1000) + ((dataFile.read()-48) *100) + ((dataFile.read()-48) *10) + (dataFile.read()-48));
          // read first channel: number and convert from ascii then correct values and add together.
          dataFile.seek(14); // set read pionter to correct byte.
          Number_Pix = (((dataFile.read()-48) *1000) + ((dataFile.read()-48) *100) + ((dataFile.read()-48) *10) + (dataFile.read()-48));
          // read number of pixels: number and convert from ascii then correct values and add together.     
          while (Debug){ // debug print.
          dataFile.seek(0); // set read pionter to correct byte.
          Serial.println(); // debug print.
          Serial.print("File fortytwo data: "); // debug print.
          for (int i = 0; i < 22; i++){
          Serial.write(dataFile.read()); // debug print.
          }
          Serial.print(" First channel: "); // debug print.
          Serial.print(First_Channel); // debug print.
          Serial.print(" Number of pixels: "); // debug print.
          Serial.print(Number_Pix); // debug print.
          Serial.println();
          break;
          }}
         // if the file isn't open, pop up an error:
         else {
         while (Debug){ // debug print.
         Serial.println("error opening fortytwo.txt"); // debug print.
         break;  
    }}}
    /////////////////////////////////////////////////////////
    
    //*************** void PESQ_Headder_Read ***************//
    void PESQ_Headder_Read(){
      Serial.print("Opened "); // debug print.
      dataFile = SD.open(PSEQ_Data_File); // open fire referenced by FPP.
      if (dataFile) { // check file open.
    //-----------------------------------------
          dataFile.seek(4); // set read pionter to correct byte.
          Data_Offset = (dataFile.read()); // read LSB.
          Data_Offset = Data_Offset + (dataFile.read() *256); // read MSB & add to LSB.
          while (PSEQ_Headder_Debug){ // debug print.
          Serial.println(); // debug print.
          Serial.print("Data Offset: "); // debug print.
          Serial.print(Data_Offset); // debug print.
          Serial.print(" "); // debug print.
          break;
          }
    //-----------------------------------------
          dataFile.seek(10); // set read pionter to correct byte.
          Number_Channels = (dataFile.read()); // read LSB.
          Number_Channels = Number_Channels + (dataFile.read() *256); // read MSB & add to LSB.
          while (PSEQ_Headder_Debug){ // debug print.
          Serial.println(); // debug print.
          Serial.print("Channels: "); // debug print.
          Serial.print(Number_Channels); // debug print.
          Serial.print(" "); // debug print.
          break;
          }
    //-----------------------------------------
          dataFile.seek(14); // set read pionter to correct byte.
          Step_Lenght = (dataFile.read()); // read LSB.
          Step_Lenght = Step_Lenght + (dataFile.read() *256); // read MSB & add to LSB. 
          while (PSEQ_Headder_Debug){ // debug print.
          Serial.println(); // debug print.
          Serial.print("Step Length: "); // debug print.
          Serial.print(Step_Lenght); // debug print.
          Serial.print(" "); // debug print.
          break;
          }
    //-----------------------------------------
          dataFile.seek(18); // set read pionter to correct byte.
          Frame_Time = (dataFile.read()); // Read FPS.
          while (PSEQ_Headder_Debug){ // debug print.
          Serial.println(); // debug print.
          Serial.print("Frame Timing: "); // debug print.
          Serial.print(Frame_Time, DEC); // debug print.
          Serial.print(" "); // debug print.
          break;
          }
    //-----------------------------------------
         while (Debug){ // debug print.
         Serial.print(PSEQ_Data_File); // debug print.
         Serial.println(" and variables set."); // debug print.
         delay(10);
         break;
         }}
      // if the file isn't open, pop up an error:
         else {
         while (Debug){ // debug print.
         Serial.print("error opening "); // debug print.
         Serial.println(PSEQ_Data_File); // debug print.
         break;
         }}
         return;
         }
    /////////////////////////////////////////////////////////
    File fortytwo:
    Code:
    fortytwo:4036:0072:11
    
    Byte 0 -> 7	Header to check file is correct for setup data.
    Byte 9 -> 12	First channel (Decimal number must be 4 digits).
    Byte 14 -> 17	Number of pixels (Decimal number must be 4 digits).
    Byte 19		Debug main (1 on).
    Byte 20		Debug advanced (1 on).
    The details of the replacement for the ESP can be found in this post. http://doityourselfchristmas.com/for...with-ESP8266-s

    I still have some work to do on the timing correction it’s very clunky at the moment (check back for updates). I think I’ll add an option to join a show, this means that if the start packet is missed for any reason but a sync packet is received and the show is not running, it will implement the start routine and join in even if this is half way through.

    This is development – I would not base my show at this point in time until more testing has been done!

    I’ll post a video tomorrow.
    Last edited by Barnabybear; 11-20-2017 at 07:27 PM.

  2. #2
    Join Date
    Nov 2010
    Location
    Livermore, CA
    Posts
    2,122
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Okay sir, here is an fseq for an indoor tree start channel 1, 150 nodes., just a basic color fade.
    https://www.dropbox.com/s/uua9y8luex...eSequence.fseq

    Tory
    Happy to Show support;
    Xlights/Nutcracker and The Falcon Team

  3. #3
    Join Date
    Nov 2010
    Location
    Livermore, CA
    Posts
    2,122
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    What I stated earlier "Although loading from an SD card doesn't seem like the ideal solution for something small, as it will require other components. adding a simple piece to the ESPixelstick interface to upload a small fseq seems cleaner."

    I'll assist as much as I can.
    Happy to Show support;
    Xlights/Nutcracker and The Falcon Team

  4. #4
    Join Date
    Dec 2011
    Location
    UK S80 postcode
    Posts
    1,271
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Hi, you can do this without the SD card but it depends on the size of the .FSEQ.

    Looking at the one you linked you have 3572 channels currently used by xlights.
    50mS timing and that sequence is 351 seconds long (351 seems a lot I may have messed up with that).

    Does that look correct?

  5. #5
    Join Date
    Nov 2010
    Location
    Livermore, CA
    Posts
    2,122
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    OOPS that won't work that thing is almost 31MB (not sure how much space is left on the ESPixle stick.. So that prob won't work (it was an hour long color wash) .. https://www.dropbox.com/s/q0lw1ogwkm...tree-5min.fseq try that one it's a 5 minute color wash, 150 channels 1 universe. Does that look more doable?
    Happy to Show support;
    Xlights/Nutcracker and The Falcon Team

  6. #6
    Join Date
    Dec 2011
    Location
    UK S80 postcode
    Posts
    1,271
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Hi, that might be more do-able. It would need to put the .FSEQ in the 3M SPIFFS location. I'll look at this over the weekend and post back any updates.

    One universe (512) * 50mS frame timing (20) * 300 second sequence (300) would be the absolute maximum if this is possable as this equates to 3M.

  7. #7
    Join Date
    Nov 2010
    Location
    Livermore, CA
    Posts
    2,122
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Quote Originally Posted by Barnabybear View Post
    Hi, that might be more do-able. It would need to put the .FSEQ in the 3M SPIFFS location. I'll look at this over the weekend and post back any updates.

    One universe (512) * 50mS frame timing (20) * 300 second sequence (300) would be the absolute maximum if this is possable as this equates to 3M.
    Okay I think i could also reduce that if required as well. I could also probably go to something like 100ms even (if that's even possible to reduce the resolution as well), this is only a color fade and twinkle on a tree, so I can play around as well.
    Happy to Show support;
    Xlights/Nutcracker and The Falcon Team

  8. #8
    Join Date
    Dec 2011
    Location
    UK S80 postcode
    Posts
    1,271
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Hi, I've just upgraded the IDE to 1.6.20 and added the spiffs file uploader.

    http://esp8266.github.io/Arduino/ver...ilesystem.html

    Page 16.

    The download goes in you in a file called tools in your normal sketch folder NOT the Folder that the Arduino IDE created and stores all its stuff in.

    Then sure enough when you restart the IDE and click on Tools from the menu bar, there is a new option called ESP8266 Sketch Data Upload.

    Now to see how much of the 3MB it will let us use.
    Last edited by Barnabybear; 11-17-2017 at 03:05 PM.

  9. #9
    Join Date
    Nov 2010
    Location
    Livermore, CA
    Posts
    2,122
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Very cool, I guess folks were not kidding when they said there is a memory issue hahahah Ya but still think this is fruitful if we can modify the ESP web page to also take a up to 3M or smaller file for a seq.. perfect for bikes, cars, trees, planes and trains
    Happy to Show support;
    Xlights/Nutcracker and The Falcon Team

  10. #10
    Join Date
    Dec 2011
    Location
    UK S80 postcode
    Posts
    1,271
    Post Thanks / Like

    Default Re: Project to use a pixelstick type device as a FPP remote.

    Hi, yep I'm sure someone will find a use for it. The biggest file I've been able to upload is 2.5MB which to be honest is pretty dam impressive, I wasn’t sure we’d get above 1MB.

    To put that in perspective:
    Each pixel is 3 bytes so your 150 pixels = 450 bytes for each frame.
    20 frames / second = 450 * 20 = 9,000 bytes per second (9KB).
    2.5MB / 9KB = 277 seconds or 4.5 minutes of display before repeating.

    Now it’s in memory we just need to read it back and send it out to the pixels.

Page 1 of 4 123 ... LastLast

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
  •