Posts | Comments

Planet Arduino

Archive for the ‘neopixel’ Category

You might think that making your own electronic games would require some kind of LCD, but lately, [Mirko Pavleski] has been making his using inexpensive 8X8 WS2812B LED panels. This lets even a modest microcontroller easily control a 64-pixel “screen.” In this case, [Mirko] uses an Arduino Nano, 3 switches, and a buzzer along with some 3D printed components to make a good-looking game. You can see it in action in the video below.

The WS2812B panels are easy to use since the devices have a simple protocol where you only talk to the first LED. You send pulses to determine each LED’s color. The first LED changes color and then starts repeating what you send to the next LED, which, of course, does the same thing. When you pause a bit, the array decides you are done, and the next train of pulses will start back at the first LED.

It looks like the project is based on a German project from [Bernd Albrecht], but our German isn’t up to snuff, and machine translation always leaves something to be desired. Another developer added a play against the computer mode. This is a simple program and would be easy to port to the microcontroller of your choice. [Mirko]’s execution of it looks like it could be a commercial product. If you made one as a gift, we bet no one would guess you built it yourself.

Of course, you could play a real robot. You could probably repurpose this hardware for many different games, too.

I fell into an internet search rabbit hole and came across ‘Drag Racing’ start lights. I had seen references to these on the Arduino forum and they looked interesting enough, and followed well defined rules, to be a relatively simple project for programming practice.

Here’s the result from an afternoon of tinkering.

How do these start lights work?

Drag races are started electronically by a system known as a Christmas tree. A common Christmas tree consists of a column of seven lights for each driver or lane, as well as a set of light beams across the track itself. The light beams are arranged with one set on the starting line, and another set 7 inches behind it.

Each side of the column of lights is the same from the top down:

  • two blue/white/yellow (it seems to vary) lamps at the top
  • three amber/yellow lamps
  • one green lamp
  • one red lamp

When drivers are preparing to race, they first cross the beams 7 inches behind the starting line. Crossing this beam put the race in pre-staged mode and activates the top bulbs. At this point the tree is activated.

Once pre-staged, drivers roll up 7 inches and cross the second beam on the starting line. Once the first driver activates the bottom (staged) bulbs, the subsequent drivers have 7 seconds to do the same or they are timed out and automatically disqualified.

Once all drivers have crossed the staged sensor, or are timed out, the starting system activates the amber lighting sequence within 1.3 seconds of the last car being staged or being disqualified. The lighting sequence will be different based on the type of tree and race start being used:

  1. A Standard tree lights up each amber light in sequence with a 500 millisecond (ms) delay between them, followed by the green light after another 500 ms delay.
  2. A Professional tree lights up all the amber lights at the same time, followed by the green light after a 400 ms delay.
  3. A Hybrid (or Professional 500) tree, is the same as a professional tree with a 500 ms delay before the green light.

On the activation of the green light the drivers are supposed to start the race.

Leaving the “Staged” line before the green light activates will instantly stop the count down and result in a lighting of the red light and a provisional disqualification of the offending driver.

Software Design

There are 2 things that we need to keep track of for this project.

The first is the racer or racing lane (these are one-to-one so I consider them equivalent). Each race has a number of lanes (usually 2 but in our world potentially more). A lane has a digital device (digital input for us) to show that the vehicle is staged and a similar device to show when the vehicle moves past the start line. A lane/racer also has the attributes of being in a staged and/or foul state.

The second is the set of lights. Each lane has one or more start light trees associated with that lane. There is always one light tree facing the racer but there could be more for crowd/officials. A light tree therefore has an association with a racer and the appropriate lighting circuits.

The logic to progress the lighting sequence is simple to implement as a Finite State Machine that follows the process description above. In my case I also wanted to capture Standard, Professional and Hybrid operating modes within the same code base.

Hardware Implementation

The first decision for the hardware is to decide how the software will be used. I decided that the software was probably most likely to be used for model or radio-controlled cars, so Neopixel (serial RGB) LEDs can be used allowing the system to be implemented with relatively low power requirements. The code logic is, obviously, scalable to larger systems if required by changing the output hardware.

For simplicity I also assumed that digital inputs provide the necessary signals for staging and foul condition. A simple digital is also used as a control to restart the lights sequence. During testing all these digital signals were connected to tact switches.

Software Implementation

The full sketch for this project is available at my code repository.

The first thing to define are the racer and light tree data structures as they form the basis for the rest of the code.

The oneTree_t type defines a tree of lights. The set of neopixel LEDs for a tree is assumed to be consecutive and similar (ie, same order) for all trees. This means that we just need to keep track of the base LED number for each tree and the rest are standard offsets from this base.

// Define the offsets from base for each set of lights
const uint8_t idStaging = 0;            // Staging LED
const uint8_t idStaged = 1;             // Staged LED
const uint8_t idReady[3] = { 2, 3, 4 }; // Ready LED (yellow)
const uint8_t idGo = 5;                 // Go LED (green)
const uint8_t idFoul = 6;               // Fould LED (red)

const uint8_t LED_PER_TREE = 7;         // LEDS in each tree

// Define what we need to keep track of for one tree of lamps
struct oneTree_t
{
  uint8_t idRacer;    // 0 .. NUM_RACERS-1. Racer's tree.
  uint8_t idLEDBase;  // The first led number for this tree
};

// Define the data for all the lamp trees required
// There are only 2 types of trees (one per racer) but these
// may be displayed multiple times (eg, front and back of a
// column, around the park, etc).
// This array defines the number of trees required, which 
// racers they 'belong' to and the starting neopixel address 
// for the LED_PER_TREE leds for this tree.
// Altogether this is the total number of LEDS that the 
// FastLED software has to manage.
oneTree_t display[] =
{
  { 0, 0 },
  { 1, LED_PER_TREE * 1 },
  { 0, LED_PER_TREE * 2 },
  { 1, LED_PER_TREE * 3 },
};

The oneRacer_t type groups the data related to one racer. Input pins are defined for the ‘staged’ and ‘fault’ inputs, and booleans keep track of the staged and foul conditions.

// Define what we need to keep track of for one racer
struct oneRacer_t
{
  uint8_t pinStaged;  // input pin indicates staged when low
  uint8_t pinFoul;    // input pin indicates foul when low
  bool isStaged;      // true if the racer is staged
  bool isFoul;        // true if tree is showing foul
};

// Define the data for all the racers
// One line entry per racer. There are normally only 2 
// racers in a drag race but more can be defined if required 
// without changes to the software.
oneRacer_t racer[] =
{
  { 4, 5, false, false },
  { 6, 7, false, false },
};

// Derive global constants from this array definition
const uint8_t NUM_RACERS = ARRAY_SIZE(racer);

The different operating modes are implemented through timing differences and some minor code variation. The software will compile to operate in any of the three modes by using the compile time #define TREE_MODE.

// Define the running mode for the tree
// Set 0 = Standard, 1 = Professional or 2 = Hybrid
#ifndef TREE_MODE
#define TREE_MODE 0
#endif

// Set up parameters for different modes
#if TREE_MODE == 0  // Standard Mode
#warning "Compiling for STANDARD TREE"

const uint32_t STAGE_DELAY = 7000; // in milliseconds
const uint32_t READY_DELAY = 1300; // in milliseconds  
const uint32_t SET_DELAY = 500;    // in milliseconds
const uint32_t GO_DELAY = 500;     // in milliseconds

#elif TREE_MODE == 1  // Professional Mode
#warning "Compiling for PROFESSIONAL TREE"

const uint32_t STAGE_DELAY = 7000; // in milliseconds
const uint32_t READY_DELAY = 1300; // in milliseconds  
const uint32_t SET_DELAY = 0;      // in milliseconds
const uint32_t GO_DELAY = 400;     // in milliseconds

#elif TREE_MODE == 2  // Hybrid Mode
#warning "Compiling for HYBRID TREE"

const uint32_t STAGE_DELAY = 7000; // in milliseconds
const uint32_t READY_DELAY = 1300; // in milliseconds  
const uint32_t SET_DELAY = 0;      // in milliseconds
const uint32_t GO_DELAY = 500;     // in milliseconds

#endif

The bulk of the controlling code is in the loop() function, which is a Finite State Machine implemented in a case statement with the following cases defined:

  static enum { 
    RESET,        // reset variables for next run
    PRE_STAGE,    // wait for signal to enable tree
    STAGING,      // wait for all lanes to stage or time out
    WAIT_START,   // delay before start sequence
    START_READY,  // yellow light sequence 
    START_SET,    // delay before green
    START_GO,     // set green light
    WAIT_RESET,   // sequence ended, waiting for signal to reset
  } curState = RESET;

I fell into an internet search rabbit hole and came across ‘Drag Racing’ start lights. I had seen references to these on the Arduino forum and they looked interesting enough, and followed well defined rules, to be a relatively simple project for programming practice.

Here’s the result from an afternoon of tinkering.

How do these start lights work?

Drag races are started electronically by a system known as a Christmas tree. A common Christmas tree consists of a column of seven lights for each driver or lane, as well as a set of light beams across the track itself. The light beams are arranged with one set on the starting line, and another set 7 inches behind it.

Each side of the column of lights is the same from the top down:

  • two blue/white/yellow (it seems to vary) lamps at the top
  • three amber/yellow lamps
  • one green lamp
  • one red lamp

When drivers are preparing to race, they first cross the beams 7 inches behind the starting line. Crossing this beam put the race in pre-staged mode and activates the top bulbs. At this point the tree is activated.

Once pre-staged, drivers roll up 7 inches and cross the second beam on the starting line. Once the first driver activates the bottom (staged) bulbs, the subsequent drivers have 7 seconds to do the same or they are timed out and automatically disqualified.

Once all drivers have crossed the staged sensor, or are timed out, the starting system activates the amber lighting sequence within 1.3 seconds of the last car being staged or being disqualified. The lighting sequence will be different based on the type of tree and race start being used:

  1. A Standard tree lights up each amber light in sequence with a 500 millisecond (ms) delay between them, followed by the green light after another 500 ms delay.
  2. A Professional tree lights up all the amber lights at the same time, followed by the green light after a 400 ms delay.
  3. A Hybrid (or Professional 500) tree, is the same as a professional tree with a 500 ms delay before the green light.

On the activation of the green light the drivers are supposed to start the race.

Leaving the “Staged” line before the green light activates will instantly stop the count down and result in a lighting of the red light and a provisional disqualification of the offending driver.

Software Design

There are 2 things that we need to keep track of for this project.

The first is the racer or racing lane (these are one-to-one so I consider them equivalent). Each race has a number of lanes (usually 2 but in our world potentially more). A lane has a digital device (digital input for us) to show that the vehicle is staged and a similar device to show when the vehicle moves past the start line. A lane/racer also has the attributes of being in a staged and/or foul state.

The second is the set of lights. Each lane has one or more start light trees associated with that lane. There is always one light tree facing the racer but there could be more for crowd/officials. A light tree therefore has an association with a racer and the appropriate lighting circuits.

The logic to progress the lighting sequence is simple to implement as a Finite State Machine that follows the process description above. In my case I also wanted to capture Standard, Professional and Hybrid operating modes within the same code base.

Hardware Implementation

The first decision for the hardware is to decide how the software will be used. I decided that the software was probably most likely to be used for model or radio-controlled cars, so Neopixel (serial RGB) LEDs can be used allowing the system to be implemented with relatively low power requirements. The code logic is, obviously, scalable to larger systems if required by changing the output hardware.

For simplicity I also assumed that digital inputs provide the necessary signals for staging and foul condition. A simple digital is also used as a control to restart the lights sequence. During testing all these digital signals were connected to tact switches.

Software Implementation

The full sketch for this project is available at my code repository.

The first thing to define are the racer and light tree data structures as they form the basis for the rest of the code.

The oneTree_t type defines a tree of lights. The set of neopixel LEDs for a tree is assumed to be consecutive and similar (ie, same order) for all trees. This means that we just need to keep track of the base LED number for each tree and the rest are standard offsets from this base.

// Define the offsets from base for each set of lights
const uint8_t idStaging = 0;            // Staging LED
const uint8_t idStaged = 1;             // Staged LED
const uint8_t idReady[3] = { 2, 3, 4 }; // Ready LED (yellow)
const uint8_t idGo = 5;                 // Go LED (green)
const uint8_t idFoul = 6;               // Fould LED (red)

const uint8_t LED_PER_TREE = 7;         // LEDS in each tree

// Define what we need to keep track of for one tree of lamps
struct oneTree_t
{
  uint8_t idRacer;    // 0 .. NUM_RACERS-1. Racer's tree.
  uint8_t idLEDBase;  // The first led number for this tree
};

// Define the data for all the lamp trees required
// There are only 2 types of trees (one per racer) but these
// may be displayed multiple times (eg, front and back of a
// column, around the park, etc).
// This array defines the number of trees required, which 
// racers they 'belong' to and the starting neopixel address 
// for the LED_PER_TREE leds for this tree.
// Altogether this is the total number of LEDS that the 
// FastLED software has to manage.
oneTree_t display[] =
{
  { 0, 0 },
  { 1, LED_PER_TREE * 1 },
  { 0, LED_PER_TREE * 2 },
  { 1, LED_PER_TREE * 3 },
};

The oneRacer_t type groups the data related to one racer. Input pins are defined for the ‘staged’ and ‘fault’ inputs, and booleans keep track of the staged and foul conditions.

// Define what we need to keep track of for one racer
struct oneRacer_t
{
  uint8_t pinStaged;  // input pin indicates staged when low
  uint8_t pinFoul;    // input pin indicates foul when low
  bool isStaged;      // true if the racer is staged
  bool isFoul;        // true if tree is showing foul
};

// Define the data for all the racers
// One line entry per racer. There are normally only 2 
// racers in a drag race but more can be defined if required 
// without changes to the software.
oneRacer_t racer[] =
{
  { 4, 5, false, false },
  { 6, 7, false, false },
};

// Derive global constants from this array definition
const uint8_t NUM_RACERS = ARRAY_SIZE(racer);

The different operating modes are implemented through timing differences and some minor code variation. The software will compile to operate in any of the three modes by using the compile time #define TREE_MODE.

// Define the running mode for the tree
// Set 0 = Standard, 1 = Professional or 2 = Hybrid
#ifndef TREE_MODE
#define TREE_MODE 0
#endif

// Set up parameters for different modes
#if TREE_MODE == 0  // Standard Mode
#warning "Compiling for STANDARD TREE"

const uint32_t STAGE_DELAY = 7000; // in milliseconds
const uint32_t READY_DELAY = 1300; // in milliseconds  
const uint32_t SET_DELAY = 500;    // in milliseconds
const uint32_t GO_DELAY = 500;     // in milliseconds

#elif TREE_MODE == 1  // Professional Mode
#warning "Compiling for PROFESSIONAL TREE"

const uint32_t STAGE_DELAY = 7000; // in milliseconds
const uint32_t READY_DELAY = 1300; // in milliseconds  
const uint32_t SET_DELAY = 0;      // in milliseconds
const uint32_t GO_DELAY = 400;     // in milliseconds

#elif TREE_MODE == 2  // Hybrid Mode
#warning "Compiling for HYBRID TREE"

const uint32_t STAGE_DELAY = 7000; // in milliseconds
const uint32_t READY_DELAY = 1300; // in milliseconds  
const uint32_t SET_DELAY = 0;      // in milliseconds
const uint32_t GO_DELAY = 500;     // in milliseconds

#endif

The bulk of the controlling code is in the loop() function, which is a Finite State Machine implemented in a case statement with the following cases defined:

  static enum { 
    RESET,        // reset variables for next run
    PRE_STAGE,    // wait for signal to enable tree
    STAGING,      // wait for all lanes to stage or time out
    WAIT_START,   // delay before start sequence
    START_READY,  // yellow light sequence 
    START_SET,    // delay before green
    START_GO,     // set green light
    WAIT_RESET,   // sequence ended, waiting for signal to reset
  } curState = RESET;

"The Great Resistor" color code illumination project

With surface-mount components quickly becoming the norm, even for homebrew hardware, the resistor color-code can sometimes feel a bit old-hat. However, anybody who has ever tried to identify a random through-hole resistor from a pile of assorted values will know that it’s still a handy skill to have up your sleeve. With this in mind, [j] decided to super-size the color-code with “The Great Resistor”.

Resistor color code from Wikipedia with white background
How the resistor color-code bands work

At the heart of the project is an Arduino Nano clone and a potential divider that measures the resistance of the test resistor against a known fixed value. Using the 16-bit ADC, the range of measurable values is theoretically 0 Ω to 15 MΩ, but there are some remaining issues with electrical noise that currently limit the practical range to between 100 Ω and 2 MΩ.

[j] is measuring the supply voltage to help counteract the noise, but intends to move to an oversampling/averaging method to improve the results in the next iteration.

The measured value is shown on the OLED display at the front, and in resistor color-code on an enormous symbolic resistor lit by WS2812 RGB LEDs behind.

Inside view of the great resistor showing WS2812 LEDs and baffle plates
Inside The Great Resistor, the LEDs and baffle plates make the magic work

Precision aside, the project looks very impressive and we like the way the giant resistor has been constructed. It would look great at a science show or a demonstration. We’re sure that the noise issues can be ironed out, and we’d encourage any readers with experience in this area to offer [j] some tips in the comments below. There’s a video after the break of The Great Resistor being put through its paces!

If you want to know more about the history of the resistor color code bands, then we have you covered.  Alternatively, how about reading the color code directly with computer vision?

"The Great Resistor" color code illumination project

With surface-mount components quickly becoming the norm, even for homebrew hardware, the resistor color-code can sometimes feel a bit old-hat. However, anybody who has ever tried to identify a random through-hole resistor from a pile of assorted values will know that it’s still a handy skill to have up your sleeve. With this in mind, [j] decided to super-size the color-code with “The Great Resistor”.

Resistor color code from Wikipedia with white background
How the resistor color-code bands work

At the heart of the project is an Arduino Nano clone and a potential divider that measures the resistance of the test resistor against a known fixed value. Using the 16-bit ADC, the range of measurable values is theoretically 0 Ω to 15 MΩ, but there are some remaining issues with electrical noise that currently limit the practical range to between 100 Ω and 2 MΩ.

[j] is measuring the supply voltage to help counteract the noise, but intends to move to an oversampling/averaging method to improve the results in the next iteration.

The measured value is shown on the OLED display at the front, and in resistor color-code on an enormous symbolic resistor lit by WS2812 RGB LEDs behind.

Inside view of the great resistor showing WS2812 LEDs and baffle plates
Inside The Great Resistor, the LEDs and baffle plates make the magic work

Precision aside, the project looks very impressive and we like the way the giant resistor has been constructed. It would look great at a science show or a demonstration. We’re sure that the noise issues can be ironed out, and we’d encourage any readers with experience in this area to offer [j] some tips in the comments below. There’s a video after the break of The Great Resistor being put through its paces!

If you want to know more about the history of the resistor color code bands, then we have you covered.  Alternatively, how about reading the color code directly with computer vision?

One of the problems with a classic Turing machine is the tape must be infinitely long. [Mark’s] Turing Ring still doesn’t have an infinite tape, but it does make it circular to save space. That along with a very clever and capable UI makes this one of the most usable Turing machines we’ve seen. You can see a demo in the video below.

The device uses an Arduino Nano, a Neopixel ring, an encoder, and a laser-cut enclosure that looks great. The minimal UI has several modes and the video below takes you through all of them.

You can even store tapes to EEPROM or the serial port, so that’s even more practical. Of course, you might wonder what practicality is a Turing machine? The honest answer is not much, but on the bright side, this one also has a clock mode so even when you aren’t explaining how a Turing machine works, it will make a good conversation piece.

We were impressed with the lettering on the case in addition to the simplicity of the user interface. [Mark] had won the LED ring in a competition so the total cost of this — to him — was low, but it wouldn’t be too much even if you bought all the pieces.

This one is certainly more compact than the last Turing machine we looked at. If you need a refresher on Turing machines and why they matter, here’s some reading for you.

We suppose it’s a bit early to call it just yet, but we definitely have a solid contender for Father of the Year. [DIY_Maxwell] made a light-up hockey game for his young son that looks like fun for all ages. Whenever the puck is hit with the accompanying DIY hockey stick (or anything else), it lights up and produces different sounds based on its acceleration.

Inside the printed puck is an Arduino Nano running an MPU6050 accelerometer, a 12-NeoPixel ring, and a piezo buzzer. [DIY_Maxell] reused a power bank charging circuit to charge up the small LiPo battery.

The original circuit used a pair of coin cells, but the Arduino was randomly freezing up, probably because of the LEDs’ current draw. Be sure to check out the video after the break, which begins with a little stop motion and features a solder stand in the shape of a 3D printer.

Got a house full of carpet or breakables? You could always build an air hockey table instead.

When we see RGB LEDs used in a project, they’re often used more for aesthetic purposes than as a practical source of light. It’s an easy way to throw some color around, but certainly not the sort of thing you’d try to light up anything larger than a desk with. Apparently nobody explained the rules to [Brian Harms] before he built Light[s]well.

Believe it or not, this supersized light installation doesn’t use any exotic hardware you aren’t already familiar with. Fundamentally, what we’re looking at is a WiFi enabled Arduino MKR1000 driving strips of NeoPixel LEDs. It’s just on a far larger scale than we’re used to, with a massive 4 x 8 aluminum extrusion frame suspended over the living room.

Onto that frame, [Brian] has mounted an undulating diffuser made of 74 pieces of laser-cut cardstock. Invoking ideas of waves or clouds, the light looks like its of natural or even biological origin while at the same time having a distinctively otherworldly quality to it.

The effect is even more pronounced when the RGB LEDs kick in, thanks to the smooth transitions between colors. In the video after the break, you can see Light[s]well work its way from bright white to an animated rainbow. As an added touch, he added Alexa voice control through Arduino’s IoT Cloud service.

While LED home lighting is increasingly becoming the norm, projects like Light[s]well remind us that we aren’t really embracing the possibilities offered by the technology. The industry has tried so hard to make LEDs fit into the traditional role of incandescent bulbs, but perhaps its time to rethink things.

While the Nintendo GameCube stood deep in the shadows of the PS2 in its day, its controller remains a popular target for all sorts of modifications today — many of them involving LEDs, thanks to a translucent bottom and button option. As an avid player of the Super Smash Bros. series, [goomysmash] is of course an owner of the very same controller, which motivated him to write GoomWave, a “versatile and hackable LED library”. In an impressively detailed Instructable, he shows how to modify your own controller in two different ways to make use of the library for yourself.

Initially inspired by the Shinewave mod that lights up RGB LEDs in colors associated to pre-defined moves in Smash Bros, [goomysmash] aimed to improve on it and add more versatility from the very beginning. Its latest iteration comes in a simplified ABXY-buttons-only variety using an ATtiny85, and a full-blown all-button variety using an Arduino Nano. Both of them are powered straight from the controller board, and have different modes where they either react to controller interactions, or are just custom lights. A brief showcasing of all the different modes can be seen in the video after the break, and there a few more details also in an older version’s video, also embedded below.

Mesmerizing LED-blinking aside, we just have to admire the diligence and cleanliness [goomysmash] put into the wiring and fitting everything inside the controller. But in case light mods aren’t your thing or you’re looking for other GameCube controller modifications, how about adding Bluetooth?

You are stuck at home quarantined and you want to do some Arduino projects. The problem is you don’t have all the cool devices you want to use. Sure, you can order them, but the stores are slow shipping things that aren’t essential these days. If you want to get a headstart while you are waiting for the postman, check out Wokwi’s Playground. For example, you can write code to drive a virtual NeoPixel 16×16 matrix. There’s even example code to get you started.

There are quite a few other choices in the playground including Charlieplexed LEDs, a keypad, and an LCD. There are also challenges. For example, in the traffic light challenge, you are given code that uses a task scheduler library to implement a traffic light. You have to add a turn signal to the code.

In addition to LEDs in various configurations, the site has some serial bus components, an LCD, a keypad, and a NeoPixel strip. There are also a few tools including an EasyEDA to KiCad converter and a way to share sourcecode similar to Pastebin.

Of course, simulations only get you so far, but the site is a fun way to play with some different I/O devices. It would be very nice if you could compose for the different components together, but you could work your code in sections, if necessary. You can do similar things with TinkerCad circuits. If you want to install software, there’s a simulator for you, too.



  • Newsletter

    Sign up for the PlanetArduino Newsletter, which delivers the most popular articles via e-mail to your inbox every week. Just fill in the information below and submit.

  • Like Us on Facebook