How to Control NeoPixel Installations via Wi-Fi Using Fishino and NodeMCU with Python

By on November 5, 2024
Pin It

We create NeoPixel light installations with Fishino and NodeMCU controlled via Wi-Fi from a PC or Raspberry Pi using a Python library.

A few years ago, the American company Adafruit Industries transformed the LED market by introducing NeoPixels, RGB LEDs that incorporate their own controller in a single package.

Adafruit aimed to simplify LED management for the Arduino community by combining the controller and RGB LED in one unit.

Since then, NeoPixels have become highly popular, thanks to the ability to chain them together and address them individually, controlling each LED’s color and brightness. Inside each NeoPixel is an RGB SMD LED (usually a 5050 type emitting about 20 lumens) along with a WS2811 or WS2812 driver.

A microcontroller (e.g., an Arduino) sends an array of bytes with precise timing across all connected LEDs, allowing the creation of vibrant, luminous animations.

NeoPixels are available in various forms and compositions: individual LEDs, strips, rings, arcs, and matrices.

Their widespread availability has spurred numerous projects showcasing their versatility, from indoor and outdoor lighting to wearable tech, LED walls, and more.

In many projects, the microcontroller controlling NeoPixels contains predefined effect sequences that it loops through. Or it’s connected via USB to a PC to receive commands, which makes remote installation challenging without extensive wiring or sketch updates whenever animations need changing.

Christmas Star with NeoPixel LEDs

Our Project

In this article, we present a system for controlling multiple NeoPixel installations around the house via Wi-Fi, without needing to modify the sketch on the microcontrollers each time. We’ll connect a Fishino Guppy to a NeoPixel star and a NodeMCU to a 150-LED NeoPixel strip (both equipped with the ESP8266 chip for Wi-Fi connectivity), using a Python program as the software controller. This program, which leverages a specially developed library, can run on either a Windows PC or Raspberry Pi and will send the various effects to all connected NeoPixel devices over Wi-Fi.

To complete this project, we need the following components, available from www.futurashop.it:

A 5-meter NeoPixel strip (part number: STRIP300LED);
A NeoPixel star with 56 LEDs (part number: FT1300M);
A 5V DC power supply with appropriate wattage (part number: MW05005);
A 470-ohm resistor;
Two 1,000 µF capacitors (6V or higher);
A Fishino Guppy board (part number: GUPPY);
A NodeMCU board (part number: NODEMCUESP);
A 3.3 to 5V logic level converter (part number: LLCTTL);
Wiring and jumper cables;
A Raspberry Pi with a microSD card and power supply.

When working with NeoPixels, it’s essential to select a power supply with the appropriate rating. A NeoPixel LED can draw up to 60 milliamps when fully bright and white. For the 150 LEDs in the 5-meter strip, that means a current draw of 9 amps.

Other necessary precautions include using capacitors and resistors: the capacitor is connected to the power cables with correct polarity to smooth the initial voltage spike from the power supply that could damage the LEDs, while the resistor is connected between the microcontroller pin and the data line (DIN) of the NeoPixel strip (a resistor is not required for the star, as it is already built into the PCB).

If you use a NodeMCU, you’ll need a logic level converter since this board operates at 3.3V logic, while NeoPixels require 5V (you could theoretically use 3.3V if the NeoPixel power supply is between 3.3 and 3.8 volts, but we have a 5V power supply).

First, download the project files from GitHub (https://github.com/open-electronics/NeoPy), which include sketches for both boards as well as the Python library source and sample animations.

Prepare the Arduino IDE development environment to program both boards. For Fishino, download the libraries from www.fishino.it and check that the firmware version matches the library version (visit the “Firmware Update” page in the “Documentation” section of the site for details).

To prepare NodeMCU programming, open the IDE settings from the “File” menu, click the right icon of “Additional URLs for Board Manager,” and paste this string into the window that opens: http://arduino.esp8266.com/stable/package_esp8266com_index.json.

Next, install the board by selecting “Tools->Board->Board Manager…” and searching for “esp8266.” Install the latest version of “esp8266 by ESP8266 Community.”

Now, under Tools -> Board, you should see “NodeMCU 1.0” in the “ESP8266 Modules” section: select it and set the “Upload speed” to 115,200.

The final setup step (needed for both boards) is downloading the NeoPixel library from Adafruit.

Download the zip, unzip it into Arduino’s “libraries” folder, and restart the IDE to import the new library. Open the “NeoPy_Fishino” sketch (select “Arduino Nano” in the Tools menu), modify the MY_SSID and MY_PASS values for your Wi-Fi network and the number of LEDs you want to connect to the board. Leave the PORT and PIN values as they are; uncomment and modify the IPADDR line to set a static IP, then upload the sketch to Fishino.

Connect the NodeMCU to the PC and open the “NeoPy_NodeMCU” sketch (select “NodeMCU 1.0” in the Tools menu), modify only the values in the “SETUP” section, and leave the PORT and PIN values unchanged, then upload the sketch to NodeMCU.

The system’s operation is illustrated in Fig. 1: the Python “NeoPy” library creates an object representing our NeoPixel installation, then we set the LEDs by updating only the array within the object itself with the “Set()” or “SetAll()” methods; the “Show()” method packages the array with the information for all LEDs and sends it via UDP to the specified endpoint (IP and port).

Fig. 1 NeoPy object and sketch operation

In Listing 1 (Fishino Guppy sketch) and Listing 2 (NodeMCU code), the sketches are very similar: in the “setup” function, the Wi-Fi connection is initialized with the previously configured parameters, then a UDP server is created to listen on the specified port.

In the “loop” function, the UDP packet is received, and its length is validated: a correct packet length is three times the number of specified LEDs since each LED’s color is represented by an RGB array of three bytes; for example, a packet for two LEDs would be RGBRGB.

Listing 1

 

/*
Name: NeoPy - Fishino
Description: NeoPixels UDP controller
Author: Luca Bellan
Version: 1.3
*/

#include <Fishino.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>

 // BEGIN SETUP
#define MY_SSID“ mio_ssid”
#define MY_PASS“ mia_password”
#define LEDS 56
//#define IPADDR 192, 168, 1, 19
#define GATE 192, 168, 1, 1
#define SUB 255, 255, 255, 0
#define PORT 4242
#define PIN 3
// END SETUP

FishinoUDP Udp;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDS, _ PIN, NEO_GRB + NEO_KHZ800);
#ifdef IPADDR
IPAddress ip(IPADDR);
IPAddress gateway(GATE);
IPAddress subnet(SUB);
#endif
long unsigned int packetSize;
unsigned int len;
int r, g, b;

void setup() {
  while (!Fishino.reset()) {
    delay(500);
  }
  Fishino.setMode(STATION_MODE);
  while (!Fishino.begin(MY_SSID, MY_PASS)) {
    delay(500);
  }
  #ifdef IPADDR
  Fishino.config(ip, gateway, subnet);
  #else
  Fishino.staStartDHCP();
  #endif
  while (Fishino.status() != STATION_GOT_IP) {
    delay(500);
  }
  Udp.begin(PORT);
  strip.begin();
  strip.show();
}

void loop() {
  packetSize = Udp.parsePacket();
  if (packetSize == LEDS * 3) {
    char packetBuffer[packetSize];
    len = Udp.read(packetBuffer, packetSize);
    if (len > 0) {
      packetBuffer[len] = 0;
    }
    for (int i = 0; i < LEDS * 3; i += 3) {
      r = (int)(byte * )(packetBuffer)[i];
      g = (int)(byte * )(packetBuffer)[i + 1];
      b = (int)(byte * )(packetBuffer)[i + 2];
      strip.setPixelColor(i / 3, r, g, b);
    }
    strip.show();
  }
}

Listing 2

/*
Name: NeoPy - NodeMCU
Description: NeoPixels UDP controller
Author: Luca Bellan
Version: 1.3
*/
#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 // BEGIN SETUP
#define MY_SSID“ mio_ssid”
#define MY_PASS“ mia_password”
#define LEDS 150
//#define IPADDR 192, 168, 1, 32
#define GATE 192, 168, 1, 1
#define SUB 255, 255, 255, 0
#define PORT 4242
#define PIN D3
// END SETUP

WiFiUDP Udp;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDS, PIN,
  NEO_GRB + NEO_KHZ800);
#ifdef IPADDR
IPAddress ip(IPADDR);
IPAddress gateway(GATE);
IPAddress subnet(SUB);
#endif
long unsigned int packetSize;
unsigned int len;
int r, g, b;

void setup() {
  WiFi.mode(WIFI_STA);
  #ifdef IPADDR
  WiFi.config(ip, gateway, subnet);
  #endif
  WiFi.begin(MY_SSID, MY_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  Udp.begin(PORT);
  strip.begin();
  strip.show();
}

void loop() {
  packetSize = Udp.parsePacket();
  if (packetSize == LEDS * 3) {
    char packetBuffer[packetSize];
    len = Udp.read(packetBuffer, packetSize);
    if (len > 0) {
      packetBuffer[len] = 0;
    }
    for (int i = 0; i < LEDS * 3; i += 3) {
      r = (int)(byte * )(packetBuffer)[i];
      g = (int)(byte * )(packetBuffer)[i + 1];
      b = (int)(byte * )(packetBuffer)[i + 2];
      strip.setPixelColor(i / 3, r, g, b);
    }
    strip.show();
  }
}

}}

 


The UDP packet is then unpacked, and each LED is set; finally, the “strip.show()” method updates all the LEDs.

We chose UDP for this system because it transmits packets more quickly than TCP, which is crucial for effects requiring rapid color changes. However, UDP doesn’t handle packet loss, especially with slow networks or high transmission speeds.

To create our effects, we’ll add small delays to avoid packet overlap on Fishino or NodeMCU. After programming both boards, connect pin 3 of Fishino to the NeoPixel strip data line (IN pin) via jumpers, including the 470-ohm resistor as in Fig. 2.

Power the star via the 5V and GND pins from the power supply, and power Fishino using the same 5V and GND pins. For NodeMCU, follow Fig. 3 to connect pin D3 to the 3.3V side of the logic level converter, then connect from the 5V side through a 470-ohm resistor to the data line of the NeoPixel strip (white wire).

Power the converter’s low-voltage side with the 3.3V and GND pins of NodeMCU; use the 5V supply for the high side, NodeMCU (VIN and GND), and the NeoPixel strip.

Power both NeoPixel installations and confirm their Wi-Fi connection (e.g., via the router configuration page or with free software like Advanced IP Scanner); download and install the latest Python 3.x version on your PC.

Fig. 2 Fishino Guppy and NeoPixel strip wiring diagram

Fig. 3 NodeMCU and NeoPixel strip wiring diagram

Python Development

We chose Python to develop the Wi-Fi controller because it’s a modern, flexible, intuitive, and easy-to-learn language. Additionally, it’s cross-platform, allowing our code to run on Windows, Apple, and Linux (in our case, on Raspberry Pi).

The official website also provides a complete Python tutorial.

Open IDLE, the program just installed, which may look like a simple text editor but allows you to write and run Python programs. Save the empty file in the same folder as neopy.py.

The NeoPy library provides the following commands:

object.Set(N, (R, G, B)): Set LED number N (e.g., from 0 to 55 in our example) to the color represented by R, G, B (each can range from 0 to 255); for example, to set the fifth LED to green, use object.Set(4, (0, 255, 0)).

object.SetAll((R, G, B)): Similar to the previous command, but sets all LEDs to the same color (use double parentheses); for example, to set all LEDs to blue, use object.SetAll((0, 0, 255)).

object.SetBrightness(L): Sets all LEDs to brightness percentage L (0 to 100), defaulting to 80. For 50% brightness, use object.SetBrightness(50).

object.Wheel(V): Returns an (R, G, B) value based on the passed parameter V (ranging from 0 to 255, cycling through all colors); for example, to set all LEDs to a random color, use object.SetAll(object.Wheel(RANDOM_NUMBER)).

object.Show(): Sends the UDP command via Wi-Fi to update all LEDs physically.

Now that we know the commands, let’s write a short program:

from neopy import NeoPy
import time
stella= NeoPy(56, “192.168.1.3”)
stella.SetBrightness(30)
for i in range(56):
  stella.Set(i, (255, 0, 0))
  stella.Show()
  time. Sleep(0.5)

The first line imports the NeoPy library, while the second imports the time library, which we’ll use to time the animation. Next, we create a NeoPy object named “star,” indicating 56 LEDs and IP address 192.168.1.3 (port 4242 is the default and should match the sketch).

We then set the overall brightness to 30% and create a for loop where, at each step, variable “i” takes values from 0 to 55. At each step, we set one LED to red using the “Set()” method, update the LEDs with “Show()” and wait half a second with the “time” object.

Make sure to align the three commands inside the for loop with a tab, or Python will throw a compilation error. Save and press F5 to run the program: if all settings are correct, the NeoPixels on the star will animate.

You can instantiate as many objects as you like; for instance, with the following code, we instantiate both the star and the NeoPixel strip, coloring one white and the other red:

from neopy import NeoPy
stella= NeoPy(56, “192.168.1.3”)
striscia= NeoPy(150, “192.168.1.19”)
stella.SetAll((255, 255, 255))
stella.Show()
striscia.SetAll((255, 0, 0))
striscia.Show()

In the project repository on GitHub, you’ll also find the “examples_star.py” and “examples_strip.py” files, which include examples to help you understand the various scripts for creating animations.

Now, let’s switch to Raspberry Pi to run the same Python scripts we created on the PC. Download a new Raspbian image from the official site, write it to the MicroSD with Win32DiskImager, insert the MicroSD into the Raspberry Pi, power it on, and connect it to the same network as our NeoPixels.

Using an SSH terminal (like Putty or MobaXTerm), connect to Raspberry Pi (username “pi,” password “raspberry”) and navigate to the “pi” directory: cd /home/pi/. Install Git with the command (press Y and Enter when prompted): sudo apt-get install git. Next, download the project files from GitHub and enter the directory with the following commands:

 git clone https://github.com/open-electronics/NeoPy cd NeoPy/

Ensure that you’re in the same directory as “neopy.py” by typing ls -l and create a new file “test.py”:

 nano test.py

Copy the code for the small program that turns on one LED at a time on the star and close the file by saving it with CTRL+X, then Y, and Enter.

Run the program with:

 python3 test.py

The NeoPixel star will light up just as it did when we ran the same program on the PC. This lets us avoid leaving a PC on as the Wi-Fi controller for all NeoPixel installations—instead, we’ll leave the much more compact and energy-efficient Raspberry Pi running.

Imagine creating several Python programs on our Raspberry Pi, each executing different effects on our NeoPixel installations at various times of the day.

Manually launching these each time could be inconvenient, so we can use “crontab,” a scheduler in Raspbian, to set specific times to launch each program. The syntax may seem complicated at first, but we’ll go through it in detail.

Type the command:

 crontab -e

The first time, you’ll be prompted to choose an editor to edit the schedule file; type:

 2 (Nano) and press Enter.

This opens the editing window where you’ll insert task lines, with each line representing a program to be executed, and containing six parameters separated by spaces: MI H D MO DW COMMAND.

Let’s break down the parameters:

MI: Minutes (0-59, or * for “every minute”);
H: Hours (0-23, or * for “every hour”);
D: Day of the month (1-31, or * for “every day”);
MO: Month (1-12, or * for “every month”);
DW: Day of the week (0-6, where 0 is Sunday and 6 is Saturday, or * for “every day”);
COMMAND: The command to execute (always specify the full path to the Python file).
Scroll to the end of the file and enter this line:

 0 * * * * python3 /home/pi/NeoPy/test.py

This schedules test.py to run at minute zero, every hour, every day, every month, every day of the week. Save and close the file with CTRL+X, then Y and Enter, then wait for the next hour to start, which will trigger the script, and verify that the star lights up just as if we launched the script manually. You can program all the scripts you want by adding new lines in crontab.

Conclusions

With Wi-Fi-controlled NeoPixels and the Raspberry Pi scheduling system, you could place an LED strip in a bedroom to simulate sunrise at a specific time as a wake-up light or create fun garden lighting effects after sunset.

Additionally, by placing LEDs in various rooms, you could have them light up at set or random intervals to simulate your presence at home. Or, connect sensors to Raspberry Pi and control lighting based on sensor data.

About Boris Landoni

Boris Landoni is the technical manager of Open-Electronics.org. Skilled in the GSM field, embraces the Open Source philosophy and its projects are available to the community.

Leave a Reply

Your email address will not be published. Required fields are marked *