Most efficient method for transmitting and receiving a color array through websockets

I am looking to control a large number of LEDs, purely for entertainment purposes and not work related.

The user interface (UI) is coded in javascript and will be sending data (a color array) approximately 60 times per second.

The LED driver is a microcontroller (ESP8266) programmed in C++ using the websocket library with the Arduino IDE.

The LEDs are addressable and controlled over a single pin. More information on the data transmission between the LEDs and the microcontroller can be found in this datasheet.But I am utilizing a simplified library that controls them using i2s and DMA to offload CPU usage.

Currently, I am sending one color to the first LED. The color is converted into a hex string to save space.

Client

//javascript
websocket.send('#ff0000');

Server

//c++
if(payload[0]=='#'){
 uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16);
 pixels[1].R=((rgb >> 16) & 0xFF);
 pixels[1].G=((rgb >> 8) & 0xFF);
 pixels[1].B=((rgb >> 0) & 0xFF);
}

Initially, I thought about sending a "hex" like string and then splitting it...

"#ff0000ff0000ff0000"
//or
"#ff0000#ff0000#ff0000"

However, after discussing with others, they suggested using binary or ascii. This seems difficult for me so I would require some examples, especially for the C++ part. I'm unsure if the websocket library can handle ascii or binary properly and then convert it back to numbers.

The problem:

The microcontroller has several limitations including memory constraints, transmission speed, and the time it takes to convert data. Therefore, the final color array should be small in size and easy to convert back to RGB values.

What is the best way to send and receive a color array?


The selection of various libraries involves thorough research:

  • Arduino IDE: User-friendly with the chip and has a large community.
  • Arduino ESP8266 Websocket lib: Reportedly the fastest based on the Arduino IDE.
  • WS2812B i2s: Utilizes DMA to control LEDs without involving the CPU.
  • Using JavaScript for UI: Compatible with all mobile devices and free to use.
  • Websockets: Allows bidirectional real-time data transfer and works on all mobile devices, also free.

Answer №1

Credit goes to the amazing enhzflep

I'm leaving this here as a reminder of how it works.

The usage of String.fromCharCode() is unnecessary since it's a Uint8Array, simply add the color range from 0 to 255 individually.

To transmit binary data over websocket, just pass the Uint8Array.buffer

Javascript

Create and send an array with 16 red pixels.

var pixels=16,
a=new Uint8Array(pixels*3),
l=pixels*1;
while(l--){
 a[l*3]=255;//red
 a[l*3+1]=0;//green
 a[l*3+2]=0;//blue
}
ws.send(a.buffer);

C++

Set all the pixels from the received payload using the i2s library and the ws library

case WStype_BIN:
 uint8_t l=NUM_LEDS*1;
 while(l--){
  pixels[l].R=payload[l*3];
  pixels[l].G=payload[l*3+1];
  pixels[l].B=payload[l*3+2];
 }
 ledstrip.show(pixels);
break;

The code has been running flawlessly for over an hour now, smoothly updating wireless 16 LEDs every 15ms.

With any other code or libraries, I faced memory and other issues after a maximum of 15 minutes when using only one LED.

So... many thanks to enhzflep.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing ID for Data Filtering

[ { "acronym": "VMF", "defaultValue": "Video & Audio Management Function", "description": "This is defined as the Video and/or Audio Management functionality that can be performed on a Digital Item. The Video & Audio M ...

Use AJAX to send a form submission along with an anchor tag

I've been facing a challenge trying to make this work, but unfortunately, I haven't had any success. Typically, all my forms include a submit input, and I handle AJAX submission in the following manner: <script> $("input#submit").click(fun ...

I am new to javascript and jquery. I have encountered numerous cases involving audio players

Recently delved into learning javascript and jquery. I managed to create a basic audio player that plays short audio clips. However, I've encountered an issue where clicking the play button on one clip displays stop buttons on all clips instead of on ...

Creating an account on React Native

Currently working on developing an Android App using React-Native and in need of implementing the SignUp Method. For the database, I am utilizing PouchDB/CouchDB. Sharing a snippet of my signup page code here: Any ideas why it's not working as expe ...

Adjust the font color to match the background in a div

I am currently working on a project where I need to place text on a dynamically generated background. To ensure that the text is clear and readable, I want to determine the color of the text based on the background. After some experimentation, I came up w ...

What could be causing the issue of loading text not appearing in Vue.js?

I have the following code snippet in my application: <div id="app"> <button v-if="!isPrepared && !isLoading" @click="startLoading()">Start Loading</button> <div v-if="isLoading">Lo ...

Calculating the height of a window using JavaScript and Ajax

As you navigate down the page, new images start loading at the bottom. However, I want them to load before reaching the very end of the page. Below is the code snippet from the page template: <?php /** * Template Name: gallery */ get_header(); ?> ...

Checking for user-uploaded photos in ReactJs can be done by implementing a function that

I need the cards to be styled differently based on whether or not the user has selected a photo. If they have, I want the card width to be 600px. However, if no photo is selected, I don't want to display an image thumbnail and instead have the width s ...

Focus automatically on an input component when the value in the Vuex store is updated in Vue

Here's the code snippet from my component: //template <v-select ref='ItemSearchSelect' :options="options"></v-select> ... //script created: function () { this.$store.subscribe((setFocusSearch, state) => { ...

HTML/JS Implementation: Back to Top Visual Element

- This website appears to be quite simple at first glance. However, I have encountered an issue where every time I scroll down and then click on the "About" menu option, it abruptly takes me back to the top of the page before displaying the section with a ...

What is the process for converting a double to a 64-bit ieee754 format?

Below is the code snippet: std::string GetBinary32( double value ) { union { float input; // assumes sizeof(float) == sizeof(int) int output; } data; data.input = value; std::bitset<sizeof(float) * CHAR_BIT> bits(data.output); ...

Issue: ENOENT - The specified file or directory, './views/s.ejs', does not exist in Node.js Express

Encountering an error when attempting to render a file from the 'views' directory in the 'routes'. The specific error message is as follows: Error: Valid Login { [Error: ENOENT: no such file or directory, open './views/s ...

Retrieve user information from Auth0 once the user has completed the signup process

I am looking to integrate the ability to create new users on Auth0 through my admin panel. Currently, I am utilizing Auth0 lock for signups, but now I need to store these users in my Database, which requires their email and Auth0 user ID. I am exploring o ...

JavaScript fails to effectively validate URLs

I have implemented the following validation for URLs: jQuery.validator.addMethod("urlValidatorJS", function (value, element) { var regExp = (/^HTTP|HTTP|http(s)?:\/\/(www\.)?[A-Za-z0-9]+([\-\.]{1}[A-Za-z0-9]+)*\.[A-Za-z]{ ...

Updating visual appearance with button clicks and unclicks

Is there a way to dynamically update the button image while clicking on it? This is what I have tried: $('.gamebox_minimap_plus').click(function() { $(this).css("background-image","url('gfx/plus2.png')"); }); The image ch ...

Unusual behavior observed with ES5 filter functionality in Node.js

My goal is to use ES5 : filter to refine the data provided below. { "EmailAddress": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="167c797356736e777b667a73e98175d3faf7">[email protected]</a> ...

Pressing the Enter key does not initiate a redirect on the page

Hey there! I've set up a text field where users need to input a password in order to download a PDF file. If the password is correct, they are directed to the URL of the PDF file. However, if the password is wrong, they are redirected to a page called ...

Has the const keyword been compromised when used with std::views?

void updateCollection(const auto& items) { *items.begin() = 104; } int main() { std::vector<int> numbers {1, 2, 3, 4, 5}; updateCollection(numbers); // This will result in an error updateCollection(numbers | std::views::all); // ...

Track and display live updates of marker movement on Google Maps

Every 20 seconds, the database table gets updated with new data. I am trying to update the marker on the map with the new latitude and longitude. I attempted to run a query every 30 seconds to retrieve the latest record from the table and update the mark ...

The Ubuntu virtual machine hosted on Google Cloud is experiencing difficulties connecting through Node.js using an external IP address

const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const app = express(); app.listen(3000, function(){ console.log('Server is now live on port 3000' ...