Translate

Monday, July 5, 2021

Lights show with Trinket M0

When needed a simple LED show, how to proceed from the idea to building ?

This article is more to discuss strategies and ways to approach a problem rather than describe in detail what is done (also if there is something about that too in it).

Requirements

Let  start with some requirements.

This has to be a single unit, i.e. no mass production is involved, basically only a prototype.
In addition to that the application is totally not critical.
Having around small boards like the Trinket, the choice was to use on of these small boards using Arduino for the programming.

The system will have to :
  • control about 26 LEDs in order to form light patterns.
    The LEDs are glued on a board in a fixed shape, starting with a single line but soon dividing in two, connected in parallel
  • with some form of input, be capable to change the speed of the LED pattern
  • with some form of input, be capable to change the LED pattern
  • possibility to change the light color 

Power considerations

We are dealing with some RGB LEDs of the Neopixel series (WS2811), 26 to be precise, so is important to see what we are talking about the power requirements.
Neopixel LED can arrive to use up to about 60 mA each at full brightness with all 3 colors on.
An average usage can be estimated around 20-25 mA, but let see what would be the worse case scenario.
Let have 26 LED full luminosity with the white color : 26 * 60 = 1560 mA, i.e. about 1.6 Ampere !
Definitively is necessary to connect them directly to the power rather than go thru the micro controlled power. Is OK doing so for development with a maximum of 8 LED since usually the voltage regulator of the controllers can arrive up to 500 mA (60 x 8 = 480 mA).

However if we reduce the brightness not to full (let say 50%) we might assume about 25-30 mA each, thus about 780 mA (26 * 30), still too much for the internal regulator.

So AT LEAST we need to have a 5V-1.5A power supply, better to use a 5V-2A one.

But this pose another problem.
The Trinket M0 is a 3.3V microcontroller. 
Powering the LEDs from the microcontroller (as we did so far because the low number of LEDs) put both micro and LED at the same power, so the "binary logic" works.
0 is 0V and 1 is 3.3V.
But powering the LEDs to 5V make the logic 1 equal to 5V.
Giving only 3.3V could not be enough and the LED would not understand the commands.

It is necessary to adapt the logic level between the 3.3V and 5V.

Alternatively of course would be to power supply the Trinket with a 3.3V /2A power supply.
At 3.3V the LED probably will consume less, thus will be  little bit less bright, but more importantly the logic chain will be preserved, allowing the Neopixel to receive a 3.3V signal as logic 1.

Shopping list

Looking for things already in the house, a first shopping list for the system was :
The Trinket 5V has some limitations due the fact some pins are shared with some specific hardware.
Specifically, on 5 I/O available, 3 of them have limitations to be used as input.
Basically only 2 I/O are available to be used as digital input and interrupt, so the decision become to change the controller and use a Trinket M0, that also has other advantages like full USB support (allows to use the monitor for debug) and more memory (see Arduino IDE settings for : Trinket M0 )

With the Trinket M0 we have all the required I/O to be used in input.

Schematic

As usual with EasyEDA a schematic is set up.


























Let have a quick tour.
The 3 input for the encoder are all pulled up internally and interrupt enabled.
The two capacitors are just to clean up the signal in case of noisy environment but on average it will work also without.
The 470uF is helpful to reduce the spikes when the power is applied and the 470 ohm resistor is just for a better protection for the Neopixel input.
The power is applied to the BAT pin that accept from 3V to 6V

The H3 jumper exists to facilitate the development.
When the system is powered from the USB port (typical when you develop ) the Neopixel can receive the power directly from the micro, in this case the jumper will be in the position 1-2.
In this case NO MORE than 8 LED are allowed !!!

When the micro is powered from the external power, the jumper should be in the position 2-3, the Neopixel will be powered from the external power supply.

IMPORTANT !  The power supply must be a 3.3V 2A.
No signal level adjustment is planned.

Software


Of course without a software the contraption is quite useless.
The code is quite simple and straightforward.
The encoder is handled completely under interrupt, the same for the push button on the encoder.

The encoder reading control the delay value (in milliseconds) used in the patterns, the encoder pushbutton changes the "pattern" of the LEDs.
The LEDS are controlled in the main loop, designed around two state machines.

One to select the pattern to display and one to handle each specific pattern.
In this way the code is capable to react quickly to any encoder input.

A state machine is a way to execute different operations depending what "state" is active at a specific moment.
The state machine is placed in an infinite loop and the states are changed in each state, depending some events.
This allow to split operations in different times without disrupting the loop.
Each state can not have ANY internal loop or delay, only the main loop is allowed. 

Let see in more details some patterns.

Knight single


The pattern Knight single (from the TV series Knight Rider) is a single light going from left to right and then back.
How to obtain the effect ? 

We have a "state machine" with 3 possible different states :
  • RESET
  • SHOW
  • DELAY
In the main loop only one state at time is engaged.

State RESET


The first as the title suggest, initialize the effect and after being executed switch in the state SHOW.
The initialization reset some variables used to control the pattern.
We need some variables :
  • LED control
    Is a variable that indicate what LED to control.
    Can go from 0 to the maximum number of LED available.
    Initialized to zero
  • Direction
    Is a flag that indicate what direction the lights sequence should go.
    Initialized to FORWARD
    • FORWARD   --> the starting direction, from left to right (i.e. counter from 0 to maximum number of LEDs)
    • BACKWARD --> from right to left (i.e. counter from maximum number of LED to zero)
  • Delay
    Time in milliseconds before to change LED
    Initialized to 80
After the initialization the state is set to SHOW.

State SHOW


In the state SHOW, is where the magic happens.
First all the LED are forced OFF, then only the LED indicated by the variable LED control is turned ON and then it is issued the command to show (i.e. the programmed LED are make visible).

Then the LED counter is updated.
  • if Direction is FORWARD
    • counter is increased by one
    • if counter goes over the maximum number of LED, then is forced to the maximum number of LED minus one and the Direction is set to BACKWARD
  • If Direction is BACKWARD
    • counter is decreased by one
    • if counter goes below 0, then is forced to zero and the Direction is set to FORWARD
The general delay value is assigned to the delay variable and then is set the state DELAY.

State DELAY


The state DELAY allows to wait "n" milliseconds before to go back to the state SHOW
The Delay counter is decreased every time the state DELAY is called and when 0 the state is set back to SHOW.

Interrupts

The encoder plus the push button, are handled under interrupt.
It means that the software that read the encoder and push button, is called form the hardware itself when the controller detect a change of the electric signal.
For example, the push button.

The push button is connected from one side to an input and the input is pulled up internally.
The other side is grounded.
If the push button is not pushed, the signal on the pin is "high" (because the pull up).
As soon as is pushed down, the signal goes down to zero. i.e. it is a change and thus the interrupt is generated.

The concept of "interrupt" is that the code stops to do whatever is doing and goes to execute a specific function (called "interrupt function") that deals with the specific interrupt happening.
The interrupt functions need to be fast !
No loops,  no delay.  Typically read the signal, set some variable or increment/decrement a counter and then exit, to allow the code "interrupted" to resume.

We are talking about microseconds here, not even milliseconds.
Shorter is better.

Prototype


A quick point-by-point prototype was built.
No PCB design since is a single use.


3D Prints


Associated to the project there are also 3 3D print projects.

Rotary encoder breakout support

This allows to easily attach the rotary encoder breakout to the panel.
The project on Tinkercad is available here.

Protective box


A box to be put over the electronic for protection.
The project on Tinkercad is available here.

LED holders


To keep the LED in the correct position a 26 LED holder are printed.
The project on Tinkercad is available here.


No comments:

Post a Comment