Add an output device to a microcontroller board you've designed
and program it to do something. Advice: make something in
support of the final project.
As I think about the final project, there are two kinds of output
that I need to figure out...
1) I need to light an LED that will give the students something to shoot for. Then, once they shoot I need to either light the LED green if they hit the right area and red if they don't.
2) I need to show them how hard they shot. For this I am thinking of using an LED strip and showing it in the same way they do with the carnival game where you try to ring the bell by hitting a big hammer on the button/ground. This is going to be similar, but the LED strip is going to light up.
First I ordered the LEDs. For that, I ordered two kinds of LEDs, individual NeoPixels and LED strips...both from Adafruit.
Choose and Learn about LEDs using Arduino
The first thing I decided to do was to pick a specific kind
of LED that I thought I could program. For this, I
went with the Adafruit
NeoPixel. I went with this because I wanted to
use as few pins as possible and the NeoPixels come with the
ability to control them using only one digital pin. I
was also impressed by their documentation on things like the
Program the Arduino strand to light up based on powerWhen a child hits the bounce back on my final project, the strand will need to only light a few lights at the bottom of the shot is weak and it will need to light up tons/all the lights if the shot is hard. And I am thinking that the color could change based on how hard (red if not hard, green if really hard). So here's what I want to program...
- weak shot: only a few lights light and have lights be red
- ok shot: medium amount of LEDs light up and they show up as yellow
- hard shot: all lights go off and show up green.
To make this easier, I am going to program the arduino to do this and then I am going to port the code over to work with by board.
Lessons 1: Colors Represented by Unsigned Integers
This is likely unique to the NeoPixels, but color (0,0,0) - parameters are R, G and B- makes the lights go dark. That's good as I'll need to do that before someone's shot goes of. Other colors to remember: Yellow = 255, 255, 0. Red is obviously 255, 0, 0 and Green is obviously 0, 255, 0. To make programming easy, I decided to define constants that I can use to just reference the color without having to worry about the values. Another note: when I created the constants, I used int. This didn't work. I had to set the colors to uint32_t instead. I guess the color values can be between 0 and 64K.
I also created a function that I will be able to call that will take two parameters...color and percent of lights to brighten. This will be what I will use to get the lights working
Here's the arduino code I ended up with.
Program single LEDs with Arduino
Get working with ATTinyNow that I have things working with the Arduino, I need get this working with the attiny and the board I previously designed. This might be hard because ...1) the timing is different and the NeoPixel's require precise timing, and 2) will the 1K resistor and/or 499 Ohm resistors work?
To start this, I read through the following tutorials:
In order to get this working with my board, I am going to have to be creative about the pins and their use. Here's what I need...
- +5v to power the LEDs (will use A3, as this doesn't have any resistors and will use it as a digital output)
- digital out pin to control the lights (will use A7 as this is the one with the 1K resistor)
- two GND pins, which is good news because I have many available
Lesson #1: attiny needs to run more slowly
The first problem I ran into was that I was getting errors when I tried to compile and upload the attiny code. When I ran the compile I got the follow error:
"/Users/pfearey/Documents/Arduino/libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp:383:3: error: #error "CPU SPEED NOT SUPPORTED""This was because the NeoPixel's couldn't run at 20MHz. To fix that, I got some help from Shawn and updated the boards.txt file with the following:
attiny84-20.name=Attiny84 (external 16 MHz resonator)I was then able to "Burn the Bootloader".
Lesson #2: attiny / avr programming needs different programming
The problem was, I couldn't get it to compile when I tried to get the attiny to use the internal clock at 8 or 16 Mhz. When I tried to compile I got the following error:
/Applications/strandtest_with_attiny_ino.ino:339: relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulhi3' defined in .text.libgcc section in /Applications/Arduino 1.0.5.app/Contents/Resources/Java/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/avr25/libgcc.a(_mulhi3.o)
As it suggests, I unzipped and replaced the ld file in the Arduino program. Once I did this, everything started compiling.
Lesson #3: attiny doesn't give off enough power
Now that I had the code compiling and downloading to the attiny, I ran my program. Nothing happened. No lights. No nothing. I also couldn't figure out a way to troubleshoot because my voltmeter wasn't going to be able to measure the digital signal because it changed too fast. Shawn confirmed this...you'd need an oscilloscope to troubleshoot that. This is where Shawn saved me (again)! He immediately pointed out (my first) problem...I was using the 7 pin from the attiny to power the LEDs. My theory was that, if I set a pin to high, that it would put out 5 volts- enough to power the lights. I was wrong. Shawn pointed out that the attiny only puts out 40 milliamps (see page 160 of the attiny85 data sheet). It says the following:
DC Current per I/O Pin ............................................... 40.0 mA
DC Current VCC and GND Pins................................ 200.0 mA
And that isn't enough to drive the lights. To fix this, I started plugging the power into the 2x3 programming header and the ground into the same header's GND pin.
Lesson #4: Using port B (rather than port A)
To drive the NeoPixel, I connected it to A3/pin 10, which is part of port A. My thinking was that this was programmed to a pin that had no resistance. When I asked Shawn about it, he started reading the Adafruit_NeoPixel.cpp file and he found the following code in the "// 8 MHz(ish) AVR" section of code.
// Squeezing an 800 KHz stream out of an 8 MHz chip requires code
// specific to each PORT register. At present this is only written
// to work with pins on PORTD or PORTB, the most likely use case --
// this covers all the pins on the Adafruit Flora and the bulk of
// digital pins on the Arduino Pro 8 MHz (keep in mind, this code
// doesn't even get compiled for 16 MHz boards like the Uno, Mega,
// Leonardo, etc., so don't bother extending this out of hand).
// Additional PORTs could be added if you really need them, just
// duplicate the else and loop and change the PORT. Each add'l
// PORT will require about 150(ish) bytes of program space.
Once I changed the attiny port I was plugged into from A3 to pin 8 / PB2, things started working!