diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2024-03-22 22:08:39 +0100 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2024-03-22 22:08:39 +0100 |
commit | e61784ab518fa07eff653cc5f97b99601d7ff2d2 (patch) | |
tree | 7db649772c4bb57bca4c2c59c4eccc69e7f4a96f | |
parent | d74b3238cdf03cbb47d58cedbe25bf900b798af8 (diff) | |
download | traffic-light-e61784ab518fa07eff653cc5f97b99601d7ff2d2.tar.gz |
Add a README.md file
-rw-r--r-- | README.md | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f7b773 --- /dev/null +++ b/README.md @@ -0,0 +1,140 @@ +# Traffic light toy + +Children love playing with car and vehicle toys, and this simple toy-sized +traffic light adds some extra fun. + + +## Photos + +[](images/traffic-light-green.jpeg) [](images/traffic-light-red.jpeg) [](images/traffic-light-back.jpeg) + + +## Hardware + +The initial version of this traffic light used three different LEDs: green, +orange and red. However, finding LEDs with sufficiently discernible color +difference between orange and red, and achieving uniform brightness across +these LEDs by adjusting the serial resistors, proved to be very difficult. This +first version, while functional, was not that great. The version presented +here, uses 8mm Neopixel LEDs, allowing for easy adjustment of color and +brightness through software, even if in practice the three LEDs consistently +display the same color: red for the bottom one, orange for the middle one, and +red for the top one. This change also simplifies the bill of material, as there +are just 3 identical LEDs. This also simplifies the schematic, as they are +daisy-chained, allowing the three of them to be controlled with a single MCU +pin (well, in practice two as explained below) instead of three. + +The board was designed using [KiCad](https://www.kicad.org/) 6.0. The +[schematic](images/schematic.png) is simple with very few components, as anyway +space is quite constrained on the PCB. For this reason, and due to the 5 V +power supply required by the Neopixels LEDs, I opted for an ATtiny9 MCU, which +operates directly at 5 V. It has limited resources both in terms of RAM, Flash +and pin counts, but suits the design well. It only has 6 pins, with two are +allocated for the power supply, leaving 4 GPIO pins available. One is reserved +for the reset signal of the programming interface, another is used by the push +button, and one more controls the Neopixel LEDs. The last pin is used to +provide power to the Neopixels LEDs, as unfortunately their idle current of 1 +mA would quickly drain the battery if left powered. Indeed there is no ON/OFF +switch on this device (as kids will forget to switch it off), instead the MCU +enters a power-down after some time, typically consuming less than a micro-amp. +The push button is then used to wake-up the MCU when the traffic light needs to +be switched on. To avoid exceeding the maximum current per GPIO pin of 40mA, +the brightness of the LEDs and the number of simultaneously lit LEDs must be +limited, but this is not an issue for a traffic light usage. Given the low pin +count of the MCU, the Neopixel and the push button pins are multiplexed with +the programming interface. In practice, it means the push button should not be +used during programming, although it should only result in programming failure, +as programmers should be protected against short circuits. The five pins +required to program the MCU are accessible as pads on the PCB, allowing them to +be temporarily soldered for programming purposes. Finally, to provide the 5 V +required by the MCU and the LEDs, a TPS61222 boost converter is used. It +operates down to 0.7V and has a quiescent current of only 5.5 ยต, providing a +few months of usage on a pair of NiMH batteries. + +All the components from the [bill of material](BOM.txt) should be easily +available from many distributors. Soldering the components onto the PCB should +be relatively straightforward for someone used to SMD components. As seen on +the photos, the battery holder is used as a stand for the traffic light, +ensuring its stability, and the PCB is attached through an angle bracket and a +pair of M3 screws. + + +## Software + +The software for the MCU is quite simple, mostly written in C (with the +exception of the timing-critical routine for controlling Neopixel LEDs) and +organized around a single source file. The entire code occupies a bit less than +two-thirds of the 1-kilobyte flash memory. The RAM is not used as everything +fits in the CPU registers, thanks to the 32 registers of the AVR CPU. + +The main part of the code consists mostly in a state machine, defined by the +`states_desc` table. It describes all possible states of a traffic light. For +each state, the brightness of each of the 3 RGB LEDs inside each of the 3 +Neopixel LEDs is defined. Additionally, for each state, the following are +defined: + +- Duration of the state +- Next state at the end of the duration +- Next state in case of a short button press +- Next state in case of a medium button press +- Next state in case of a long button press + +Button presses shorter than 10 ms are ignored for debouncing purposes, and +longer ones are categorized as follows: + +- Short: >= 10 ms and < 500 ms +- Medium: >= 500 ms and < 1500 ms +- Long: > 1500 ms + +By default, the state machine is configured to execute the standard traffic +light sequence observed in France and many other countries: green, orange, red, +and back to green. The code includes comments to support the use of orange and +red together between the red and green states, as seen in some countries. A +short button push advances to the next state without waiting for the full +duration. A medium push switches the traffic light to blinking orange, and +another medium push restores the normal sequence. Finally, a long push turns +off the traffic light, using the special state `state_off`, which disables the +power supply pin of the LEDs, enables interrupt on the button pin, and puts the +MCU in a power-down state. + +The signal to control the Neopixel LEDs is generated through bit-banging, using +an inline assembly-based routine. As [nicely explained by Josh +Levine](https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/), +the timing is not as critical as one might expect from reading the datasheet, +only certain aspects of the timing are crucial. This trick enables the use of +the internal RC oscillator running at only 8 MHz. + + +A makefile is provided to compile the code using [AVR +GCC](https://gcc.gnu.org/wiki/avr-gcc) and [AVR +Libc](https://github.com/avrdudes/avr-libc): +``` + $ make + avr-gcc -MMD -g -Wall -Wextra -Os -fshort-enums -mmcu=attiny9 -c -o main.o main.c + avr-gcc -MMD -g -Wall -Wextra -Os -fshort-enums -mmcu=attiny9 -Wl,-Map,traffic-light.map,--relax -fwhole-program -o traffic-light.elf main.o + avr-objdump -h -S traffic-light.elf > traffic-light.lst + avr-objcopy -j .text -j .data -j .rodata -O ihex traffic-light.elf traffic-light.hex + AVR Memory Usage + ---------------- + Device: attiny9 + + Program: 594 bytes (58.0% Full) + (.text + .data + .bootloader) + + Data: 0 bytes (0.0% Full) + (.data + .bss + .noinit) +``` + +To program the device using an AVRISP MKII programmer and the +[avrdude](https://github.com/avrdudes/avrdude) software, simply execute the +`make flash` command. Admittedly, the makefile has only been tested on Debian +GNU/Linux, so it might require some adjustments, especially when using a +different programmer. + + +## License + +The contents of this repository, with the exception the software, is released +under the [Creative Commons Attribution-ShareAlike 4.0 International License +(CC BY-SA 4.0)](LICENSE). The software is released under the [terms of the GNU +GPL, version 2](software/COPYING). |