MAX7219 LED Clock with Arduino Nano

This is a small project that I created using MAX7219 8 Digit 7 Segment Displays to create a clock that shows the date and time. I used an DS1307 Real Time Clock for keeping time, and an Arduino Nano to bring it all together on a small breadboard (for now).

Components Required

MAX7219 8 digit 7 segment display x 2
TinyRTC I2C DS1307 RTC Module
Arduino Nano (can also be used on an Uno)
Breadboard
Connecting Wires

 

TinyRTC Issues

I ordered a TinyRTC I2C module from eBay, however, it did not come with a rechargeable LIM2032 battery but a standard CR2032 non rechargeable lithium battery. As the TinyRTC I2C DS1307 module has a charging circuit for charging lithium cells, this needed to be modified so that it would not charge a non rechargeable cell. I’d like to credit the website brainy-bits.com for the details below on how to modify the module to remove the charging circuitry and allow me to use the module with a standard CR2032 battery.

Modifying the TinyRTC

You need to remove the Diode at D1 and both the resistors at R6 and R4. You then need to create a solder (or wire bridge) between the pads of R6. If you need further advice with this, check out their original article which I found this information from here.

Now that we have modified the DS1307, we can attach it to the Arduino on the SPI headers, which on the Nano is located at A5 for SCL and A4 for SDA. Then you need to connect VCC to +5 Volt and GND to GND.

Attaching the MAX7219 strips

Then to attach our first MAX7219 with the following connections: Pin 9 is connected to the DataIn, Pin 8 is connected to the CLK and pin 7 is connected to LOAD. VCC goes to +5 Volt and GND to GND.

Our second MAX7219 display can connect to the first one, making sure that DataOut on the first module is connected to DataIn on the second module and that LOAD, CLK, VCC and GND are connected to each other.

Setting The Time

Now your circuit is built, we need to set the time on the DS1307. Once you have installed the required libraries (linked below), you can open the example sketch from the DS1307RTC for SetTime.

However, I have found that this sets the time 7 seconds too slow. This is because it uses the time that the program was compiled as its reference for time, and takes a few seconds to upload to the Arduino nano. This modified sketch won’t function correctly if you compile within the last 7 seconds of a minute, however this can be adjusted by changing the DEFINE Offset 7 below if you find that this isn’t correct for your needs.

Libraries

Time Library – https://github.com/PaulStoffregen/Time or download here
DS1307RTC Library – https://github.com/PaulStoffregen/DS1307RTC or download here
LedControl Library – https://github.com/wayoda/LedControl or download here

SetTime_with_Offset.ino

/*   FILENAME: SetTime_with_Offset.ino
*   AUTHOR(s): Jessica at AccessiblePixel.com
*   CONTACT: media@accessiblepixel.com
*   LICENSE: 
*     
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#define OFFSET 7 // Offset for Adding Seconds
const char *monthName[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
tmElements_t tm;
void setup() {
bool parse=false;
bool config=false;
// get the date and time the compiler was run
if (getDate(__DATE__) && getTime(__TIME__)) {
parse = true;
// and configure the RTC with this info
if (RTC.write(tm)) {
config = true;
}
}
Serial.begin(9600);
while (!Serial) ; // wait for Arduino Serial Monitor
delay(200);
if (parse && config) {
Serial.print("DS1307 configured Time=");
Serial.print(tm.Hour);
Serial.print(tm.Minute);
Serial.print(tm.Second);
Serial.print(", Date=");
Serial.println(__DATE__);
} else if (parse) {
Serial.println("DS1307 Communication Error :-{");
Serial.println("Please check your circuitry");
} else {
Serial.print("Could not parse info from the compiler, Time=\"");
Serial.print(__TIME__);
Serial.print("\", Date=\"");
Serial.print(__DATE__);
Serial.println("\"");
}
}
void loop() {
}
bool getTime(const char *str)
{
int Hour, Min, Sec;
if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
tm.Hour = Hour;
tm.Minute = Min;
tm.Second = Sec;
tm.Second = tm.Second + OFFSET;
return true;
}
bool getDate(const char *str)
{
char Month[12];
int Day, Year;
uint8_t monthIndex;
if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
for (monthIndex = 0; monthIndex < 12; monthIndex++) {
if (strcmp(Month, monthName[monthIndex]) == 0) break;
}
if (monthIndex >= 12) return false;
tm.Day = Day;
tm.Month = monthIndex + 1;
tm.Year = CalendarYrToTm(Year);
return true;
}

Now if you open your serial console, you should see that it has set the time correctly.

Finally you can upload the following code (after installing the libraries linked above) to get your clock up and running.

MAX7219_LED_Clock.ino

/*   FILENAME: MAX7219_LED_Clock.ino 
*   AUTHOR(s): Jessica at AccessiblePixel.com
*   CONTACT: media@accessiblepixel.com
*   LICENSE: 
*     
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
//
// Include Libraries
//
#include <Time.h>  // Time Manipulation Library
#include <DS1307RTC.h>  // DS1307 RTC Library
#include "LedControl.h" // MAX72XX Library
//
// Defines
//
#define TOTAL_STRIPS 2 // Set How Many Strips of MAX7219 7 Segment Displays
#define DATAIN 9 // pin 9 is connected to the DataIn 
#define CLK 8 // pin 8 is connected to the CLK
#define LOAD 7 // pin 7 is connected to LOAD 
//
// Start LedControl MAX7219 Library
//
LedControl lc=LedControl(DATAIN,CLK,LOAD,TOTAL_STRIPS);
//
// Set Variables
//
int year4digit;  // 4 digit year
//
// Setup (Run Once)
//
void setup() {
//
// The MAX7219 needs waking up as it is in power-saving mode on startup.
// This will wake all connected displays.
//
for (int loop = 0; loop < (TOTAL_STRIPS); loop++) {
lc.shutdown(loop,false);
// Set the brightness to a medium value
lc.setIntensity(loop,4);
// Clear the display
lc.clearDisplay(loop);
}
}
//
// Loop (Run Forever)
//
void loop() {
//
// Get data from the DS1307 RTC
//
tmElements_t tm;
if (RTC.read(tm)) {
year4digit = tm.Year + 1970;  // Create an accurate 4 digit year variable
}
//
// Get Single Digits from each number using modulus
//
// Quick Guide to Modulus with Arduino
// Given the number 2018:
// How to get:
// 8 is 2018 % 10
// 1 is 2018 / 10 % 10
// 0 is 2018 / 100 % 10
// 2 is 2018 / 1000 % 10
int firsthourdigit = tm.Hour /10 % 10;
int secondhourdigit = tm.Hour % 10;
int firstminutedigit = tm.Minute /10 % 10;
int secondminutedigit = tm.Minute % 10;
int firstseconddigit = tm.Second /10 % 10;
int secondseconddigit = tm.Second % 10;
int firstdigitday = tm.Day /10 % 10;
int seconddigitday = tm.Day %10;
int firstdigitmonth = tm.Month /10 % 10;
int seconddigitmonth = tm.Month % 10;
int firstdigityear = year4digit / 1000 % 10;
int seconddigityear = year4digit / 100 % 10;
int thirddigityear = year4digit / 10 % 10;
int fourthdigityear = year4digit %10;
//
// Output the digits
//
//
// First Display (as wired) displaying Time: HH.MM.SS format
//
lc.setDigit(0,6,firsthourdigit,false);    // First Hour Digit     2
lc.setDigit(0,5,secondhourdigit,true);    // Second Hour Digit    1 (with a .)
lc.setDigit(0,4,firstminutedigit,false);  // First Minute Digit   2
lc.setDigit(0,3,secondminutedigit,true);  // Second Minute Digit  3 (with a .)
lc.setDigit(0,2,firstseconddigit,false);  // First Second Digit   3
lc.setDigit(0,1,secondseconddigit,true);  // Second Second Digit  4 (with a .)
//
// Second Display (as wired) displaying Date: DD.MM.YYYY format.
//
lc.setDigit(1,7,firstdigitday,false);     // First Day Digit      1
lc.setDigit(1,6,seconddigitday,true);     // Second Day Digit     8 (with a .)
lc.setDigit(1,5,firstdigitmonth,false);   // First Month Digit    1
lc.setDigit(1,4,seconddigitmonth,true);   // Second Month Digit   2 (with a .)
lc.setDigit(1,3,firstdigityear,false);    // First Year Digit     2
lc.setDigit(1,2,seconddigityear,false);   // Second Year Digit    0
lc.setDigit(1,1,thirddigityear,false);    // Third Year Digit     1
lc.setDigit(1,0,fourthdigityear,false);   // Fourth Year Digit    8
delay(250);
}

ATTiny85 Art Piece and first circuit development

This is the first circuit designed with a stand alone chip that runs the basic blink sketch. It uses an ATTiny85.
To setup the Arduino IDE, there is an excellent guide available at highlowtech.org which also works with the latest version of the Arduino IDE.

ATTiny85 in a small wooden, black frame and circuit background.

Once you have setup a circuit to program the ATTiny85, you can choose how fast the processor runs. Usually you’d want to run it at 8MHz. However, because I am running the piece off a CR2032 lithium cell, power is at a minimum. I read the data-sheet for the ATTiny85 and found that at 8MHz (at 3volt) it uses around 3.5mA and at 1MHz it uses about 0.5mA. So using this I managed to save 3mA of power. The other issue was the LED. This was consuming approximately 15-20mA every time it lit up. So I added a 47k ohm resistor to it, and reduced its power consumption.

As the average CR2032 cell has 235mA capacity, with the original power consumption the piece would have only lasted about a day. With these power optimisations, it will last at least 17 days before the cell needs replacing.

The first revision of the circuit board, before power optimisation

The circuit has been placed on a small green breadboard, a CR2032 cell holder, a CR2032 cell, connecting wire, a 47K ohm resistor and the ATTiny85 chip. I also printed a circuit background for the piece.

The code the ATTiny85 is running is simple, it’s just a modified version of the default blink sketch.

void setup() {
pinMode(0, OUTPUT);
}
void loop() {
digitalWrite(0, HIGH);
delay(1000);
digitalWrite(0, LOW);
delay(1000);
}

Final-ish Code for Workshop

We have the final(ish) code ready for the prototypes that people will be able to make from our kits.

// Accessible Pixel version 1
// APvl.ino
// designed by AccessiblePixel.com
//Include Libraries
#include <Adafruit_NeoPixel.h>
#include <Keypad.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// Initialise Variables
#define PIN 9 // PIN for LED Strip
volatile int frame=0;
volatile int backcolorframe=0;
volatile int r = 0;
volatile int g = 0;
volatile int b = 0;
volatile int brightred = 0;
volatile int brightgreen = 0;
volatile int brightblue = 0;
volatile int brightcolor = 0;
volatile int up = 0;
volatile int rainbowi = 0;
volatile int rainboww = 0;
volatile int circleanimation = 0;
// Initialise Pixels
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);
// Setup Keypad
const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 8, 7, 6, 5 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 4, 3, 2 }; 
// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// Main Setup Loop (Run Once At Start Up)
void setup() {
// Initialize Pixels
strip.begin();    
strip.setBrightness(135);
strip.setPixelColor(0,50,50,50);
strip.setPixelColor(1,0,0,0);
strip.setPixelColor(2,50,50,50);
strip.setPixelColor(3,0,0,0);
strip.setPixelColor(4,50,50,50);
strip.setPixelColor(5,0,0,0);
strip.setPixelColor(6,50,50,50);
strip.setPixelColor(7,0,0,0);
strip.setPixelColor(8,50,50,50);
strip.setPixelColor(9,0,0,0);
strip.setPixelColor(10,50,50,50);
strip.setPixelColor(11,0,0,0);
strip.setPixelColor(12,50,50,50);
strip.setPixelColor(13,0,0,0);
strip.setPixelColor(14,50,50,50);
strip.setPixelColor(15,0,0,0);
strip.show(); 
// Setup Interrupt at 32hz
// Stop Interrupts
cli();
// Clear Timer Register
TCCR1A = 0;// Set entire TCCR1A register to 0
TCCR1B = 0;// Same for TCCR1B
TCNT1  = 0;// Initialize counter value to 0
// set compare match register for 32hz increments
OCR1A = 488;// = (16*10^6) / (32*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);  
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
// Allow Interrupts
sei();
}//end setup loop
// Function Declarations
//Initialize Reset Function
void(* resetFunc) (void) = 0; //declare reset function @ address 0 
uint32_t wheelz(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
// Run Animation Frames
ISR(TIMER1_COMPA_vect){
if(frame==1){ 
strip.setPixelColor(0,135,0,0);
strip.show(); 
frame++;
}
else if(frame==2) {  
strip.setPixelColor(1,135,0,0);
strip.show(); 
frame++;
}
else if(frame==3) {  
strip.setPixelColor(2,135,0,0);
strip.show(); 
frame++;
}
else if(frame==4) {  
strip.setPixelColor(3,135,0,0);
strip.show(); 
frame++;
}
else if(frame==5) {  
strip.setPixelColor(4,135,0,0);
strip.show(); 
frame++;
}
else if(frame==6) {  
strip.setPixelColor(5,135,0,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==7) {  
strip.setPixelColor(6,135,0,0);
strip.show(); 
frame++;
}
else if(frame==8) {  
strip.setPixelColor(7,135,0,0);
strip.show(); 
frame++;
}
else if(frame==9) {  
strip.setPixelColor(8,135,0,0);
strip.show(); 
frame++;
}
else if(frame==10) {  
strip.setPixelColor(9,135,0,0);
strip.show(); 
frame++;
}
else if(frame==11) {  
strip.setPixelColor(10,135,0,0);
strip.show(); 
frame++;
}
else if(frame==12) {  
strip.setPixelColor(11,135,0,0);
strip.show(); 
frame++;
}
else if(frame==13) {  
strip.setPixelColor(12,135,0,0);
strip.show(); 
frame++;
}
else if(frame==14) {  
strip.setPixelColor(13,135,0,0);
strip.show(); 
frame++;
}
else if(frame==15) {  
strip.setPixelColor(14,135,0,0);
strip.show(); 
frame++;
}
else if(frame==16) {  
strip.setPixelColor(15,135,0,0);
strip.show(); 
frame = 38;
}
// RESET ANIMATION
else if(frame==17){ 
strip.setPixelColor(15,0,0,0);
strip.show(); 
frame++;
}
else if(frame==18) {  
strip.setPixelColor(14,0,0,0);
strip.show(); 
frame++;
}
else if(frame==19) {  
strip.setPixelColor(13,0,0,0);
strip.show(); 
frame++;
}
else if(frame==20) {  
strip.setPixelColor(12,0,0,0);
strip.show(); 
frame++;
}
else if(frame==21) {  
strip.setPixelColor(11,0,0,0);
strip.show(); 
frame++;
}
else if(frame==22) {  
strip.setPixelColor(10,0,0,0);
strip.show(); 
frame++;
}
else if(frame==23) {  
strip.setPixelColor(9,0,0,0);
strip.show(); 
frame++;
}
else if(frame==24) {  
strip.setPixelColor(8,0,0,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==25) {  
strip.setPixelColor(7,0,0,0);
strip.show(); 
frame++;
}
else if(frame==26) {  
strip.setPixelColor(6,0,0,0);
strip.show(); 
frame++;
}
else if(frame==27) {  
strip.setPixelColor(5,0,0,0);
strip.show(); 
frame++;
}
else if(frame==28) {  
strip.setPixelColor(4,0,0,0);
strip.show(); 
frame++;
}
else if(frame==29) {  
strip.setPixelColor(3,0,0,0);
strip.show(); 
frame++;
}
else if(frame==30) {  
strip.setPixelColor(2,0,0,0);
strip.show(); 
frame++;
}
else if(frame==31) {  
strip.setPixelColor(1,0,0,0);
strip.show(); 
frame++;
}
else if(frame==32) {  
strip.setPixelColor(0,0,0,0);
strip.show(); 
} else if(frame==33) {
strip.setPixelColor(random(0,15),random(0,135),random(0,135),random(0,135));
strip.setPixelColor(random(0,15),0,0,0,0);
strip.show();
}
else if(frame==34){strip.setPixelColor(0,0,0,0);
strip.setPixelColor(1,0,0,0);
strip.setPixelColor(2,0,0,0);
strip.setPixelColor(3,0,0,0);
strip.setPixelColor(4,0,0,0);
strip.setPixelColor(5,0,0,0);
strip.setPixelColor(6,0,0,0);
strip.setPixelColor(7,0,0,0);
strip.setPixelColor(8,0,0,0);
strip.setPixelColor(9,0,0,0);
strip.setPixelColor(10,0,0,0);
strip.setPixelColor(11,0,0,0);
strip.setPixelColor(12,0,0,0);
strip.setPixelColor(13,0,0,0);
strip.setPixelColor(14,0,0,0);
strip.setPixelColor(15,0,0,0);
strip.show();
}
else if(frame==35){
strip.setPixelColor(0,brightred,brightgreen,brightblue);
strip.setPixelColor(1,brightred,brightgreen,brightblue);
strip.setPixelColor(2,brightred,brightgreen,brightblue);
strip.setPixelColor(3,brightred,brightgreen,brightblue);
strip.setPixelColor(4,brightred,brightgreen,brightblue);
strip.setPixelColor(5,brightred,brightgreen,brightblue);
strip.setPixelColor(6,brightred,brightgreen,brightblue);
strip.setPixelColor(7,brightred,brightgreen,brightblue);
strip.setPixelColor(8,brightred,brightgreen,brightblue);
strip.setPixelColor(9,brightred,brightgreen,brightblue);
strip.setPixelColor(10,brightred,brightgreen,brightblue);
strip.setPixelColor(11,brightred,brightgreen,brightblue);
strip.setPixelColor(12,brightred,brightgreen,brightblue);
strip.setPixelColor(13,brightred,brightgreen,brightblue);
strip.setPixelColor(14,brightred,brightgreen,brightblue);
strip.setPixelColor(15,brightred,brightgreen,brightblue);
strip.show();
if (brightcolor==0) {
if (up == 0) {
if (brightred < 135) {
brightred++; 
}
else if (brightred == 135) {
brightred=135; 
up = 1;
} 
}
else if(up == 1) {
if(brightred > 0) {
brightred--;
} 
else if (brightred == 0) {
up = 0;brightcolor++;
} 
}
} 
else if (brightcolor==1) {
if (up == 0) {
if (brightgreen < 135) {
brightgreen++; 
}
else if (brightgreen == 135) {
brightgreen=135; 
up = 1;
} 
}
else if(up == 1) {
if(brightgreen > 0) {
brightgreen--;
} 
else if (brightgreen == 0) {
up = 0;brightcolor++;
} 
}
} 
else if (brightcolor==2) {
if (up == 0) {
if (brightblue < 135) {
brightblue++; 
}
else if (brightblue == 135) {
brightblue=135; 
up = 1;
} 
}
else if(up == 1) {
if(brightblue > 0) {
brightblue--;
} 
else if (brightblue == 0) {
up = 0;brightcolor=0;
} 
}
}            
}
else if(frame==36){
strip.setPixelColor(rainbowi, wheelz((rainbowi+rainboww) & 255));
strip.show();
if (rainbowi < 15 )
{ rainbowi++; } else if (rainbowi == 15) { rainbowi = 0; }
if (rainboww < 255 )
{rainboww++; } if (rainboww == 255) {rainboww =0; }
}
else if(frame==37){frame=0;}
if(frame==38){ 
strip.setPixelColor(0,0,0,135);
strip.show(); 
frame++;
}
else if(frame==39) {  
strip.setPixelColor(1,0,0,135);
strip.show(); 
frame++;
}
else if(frame==40) {  
strip.setPixelColor(2,0,0,135);
strip.show(); 
frame++;
}
else if(frame==41) {  
strip.setPixelColor(3,0,0,135);
strip.show(); 
frame++;
}
else if(frame==42) {  
strip.setPixelColor(4,0,0,135);
strip.show(); 
frame++;
}
else if(frame==43) {  
strip.setPixelColor(5,0,0,135);
strip.show(); 
frame++;
}
else if(frame==44) {  
strip.setPixelColor(6,0,0,135);
strip.show(); 
frame++;
}
else if(frame==45) {  
strip.setPixelColor(7,0,0,135);
strip.show(); 
frame++;
}
else if(frame==46) {  
strip.setPixelColor(8,0,0,135);
strip.show(); 
frame++;
}
else if(frame==47) {  
strip.setPixelColor(9,0,0,135);
strip.show(); 
frame++;
}
else if(frame==48) {  
strip.setPixelColor(10,0,0,135);
strip.show(); 
frame++;
}
else if(frame==49) {  
strip.setPixelColor(11,0,0,135);
strip.show(); 
frame++;
}
else if(frame==50) {  
strip.setPixelColor(12,0,0,135);
strip.show(); 
frame++;
}
else if(frame==51) {  
strip.setPixelColor(13,0,0,135);
strip.show(); 
frame++;
}
else if(frame==52) {  
strip.setPixelColor(14,0,0,135);
strip.show(); 
frame++;
}
else if(frame==53) {  
strip.setPixelColor(15,0,0,135);
strip.show(); 
frame++;
}
if(frame==54){ 
strip.setPixelColor(0,0,135,0);
strip.show(); 
frame++;
}
else if(frame==55) {  
strip.setPixelColor(1,0,135,0);
strip.show(); 
frame++;
}
else if(frame==56) {  
strip.setPixelColor(2,0,135,0);
strip.show(); 
frame++;
}
else if(frame==57) {  
strip.setPixelColor(3,0,135,0);
strip.show(); 
frame++;
}
else if(frame==58) {  
strip.setPixelColor(4,0,135,0);
strip.show(); 
frame++;
}
else if(frame==59) {  
strip.setPixelColor(5,0,135,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==60) {  
strip.setPixelColor(6,0,135,0);
strip.show(); 
frame++;
}
else if(frame==61) {  
strip.setPixelColor(7,0,135,0);
strip.show(); 
frame++;
}
else if(frame==62) {  
strip.setPixelColor(8,0,135,0);
strip.show(); 
frame++;
}
else if(frame==63) {  
strip.setPixelColor(9,0,135,0);
strip.show(); 
frame++;
}
else if(frame==64) {  
strip.setPixelColor(10,0,135,0);
strip.show(); 
frame++;
}
else if(frame==65) {  
strip.setPixelColor(11,0,135,0);
strip.show(); 
frame++;
}
else if(frame==66) {  
strip.setPixelColor(12,0,135,0);
strip.show(); 
frame++;
}
else if(frame==67) {  
strip.setPixelColor(13,0,135,0);
strip.show(); 
frame++;
}
else if(frame==68) {  
strip.setPixelColor(14,0,135,0);
strip.show(); 
frame++;
}
else if(frame==69) {  
strip.setPixelColor(15,0,135,0);
strip.show(); 
frame = 1;
} else if(frame==70) {  
strip.setPixelColor(0,50,50,50);
strip.setPixelColor(1,0,0,0);
strip.setPixelColor(2,50,50,50);
strip.setPixelColor(3,0,0,0);
strip.setPixelColor(4,50,50,50);
strip.setPixelColor(5,0,0,0);
strip.setPixelColor(6,50,50,50);
strip.setPixelColor(7,0,0,0);
strip.setPixelColor(8,50,50,50);
strip.setPixelColor(9,0,0,0);
strip.setPixelColor(10,50,50,50);
strip.setPixelColor(11,0,0,0);
strip.setPixelColor(12,50,50,50);
strip.setPixelColor(13,0,0,0);
strip.setPixelColor(14,50,50,50);
strip.setPixelColor(15,0,0,0);
strip.show();
}
else if(frame==71) {  
strip.setPixelColor(0,135,0,0);
strip.setPixelColor(1,135,0,0);
strip.setPixelColor(2,135,0,0);
strip.setPixelColor(3,135,0,0);
strip.setPixelColor(4,135,0,0);
strip.setPixelColor(5,135,0,0);
strip.setPixelColor(6,135,0,0);
strip.setPixelColor(7,135,0,0);
strip.setPixelColor(8,135,0,0);
strip.setPixelColor(9,135,0,0);
strip.setPixelColor(10,135,0,0);
strip.setPixelColor(11,135,0,0);
strip.setPixelColor(12,135,0,0);
strip.setPixelColor(13,135,0,0);
strip.setPixelColor(14,135,0,0);
strip.setPixelColor(15,135,0,0);
strip.show();
}
else if(frame==72) {  
strip.setPixelColor(0,0,135,0);
strip.setPixelColor(1,0,135,0);
strip.setPixelColor(2,0,135,0);
strip.setPixelColor(3,0,135,0);
strip.setPixelColor(4,0,135,0);
strip.setPixelColor(5,0,135,0);
strip.setPixelColor(6,0,135,0);
strip.setPixelColor(7,0,135,0);
strip.setPixelColor(8,0,135,0);
strip.setPixelColor(9,0,135,0);
strip.setPixelColor(10,0,135,0);
strip.setPixelColor(11,0,135,0);
strip.setPixelColor(12,0,135,0);
strip.setPixelColor(13,0,135,0);
strip.setPixelColor(14,0,135,0);
strip.setPixelColor(15,0,135,0);
strip.show();
}
else if(frame==73) {  
strip.setPixelColor(0,0,0,135);
strip.setPixelColor(1,0,0,135);
strip.setPixelColor(2,0,0,135);
strip.setPixelColor(3,0,0,135);
strip.setPixelColor(4,0,0,135);
strip.setPixelColor(5,0,0,135);
strip.setPixelColor(6,0,0,135);
strip.setPixelColor(7,0,0,135);
strip.setPixelColor(8,0,0,135);
strip.setPixelColor(9,0,0,135);
strip.setPixelColor(10,0,0,135);
strip.setPixelColor(11,0,0,135);
strip.setPixelColor(12,0,0,135);
strip.setPixelColor(13,0,0,135);
strip.setPixelColor(14,0,0,135);
strip.setPixelColor(15,0,0,135);
strip.show();
}
else if(frame==74) {  
strip.setPixelColor(0,0,68,68);
strip.setPixelColor(1,0,68,68);
strip.setPixelColor(2,0,68,68);
strip.setPixelColor(3,0,68,68);
strip.setPixelColor(4,0,68,68);
strip.setPixelColor(5,0,68,68);
strip.setPixelColor(6,0,68,68);
strip.setPixelColor(7,0,68,68);
strip.setPixelColor(8,0,68,68);
strip.setPixelColor(9,0,68,68);
strip.setPixelColor(10,0,68,68);
strip.setPixelColor(11,0,68,68);
strip.setPixelColor(12,0,68,68);
strip.setPixelColor(13,0,68,68);
strip.setPixelColor(14,0,68,68);
strip.setPixelColor(15,0,68,68);
strip.show();
}
else if(frame==75) {  
strip.setPixelColor(0,68,0,68);
strip.setPixelColor(1,68,0,68);
strip.setPixelColor(2,68,0,68);
strip.setPixelColor(3,68,0,68);
strip.setPixelColor(4,68,0,68);
strip.setPixelColor(5,68,0,68);
strip.setPixelColor(6,68,0,68);
strip.setPixelColor(7,68,0,68);
strip.setPixelColor(8,68,0,68);
strip.setPixelColor(9,68,0,68);
strip.setPixelColor(10,68,0,68);
strip.setPixelColor(11,68,0,68);
strip.setPixelColor(12,68,0,68);
strip.setPixelColor(13,68,0,68);
strip.setPixelColor(14,68,0,68);
strip.setPixelColor(15,68,0,68);
strip.show();
}
else if(frame==76) {  
strip.setPixelColor(0,68,68,0);
strip.setPixelColor(1,68,68,0);
strip.setPixelColor(2,68,68,0);
strip.setPixelColor(3,68,68,0);
strip.setPixelColor(4,68,68,0);
strip.setPixelColor(5,68,68,0);
strip.setPixelColor(6,68,68,0);
strip.setPixelColor(7,68,68,0);
strip.setPixelColor(8,68,68,0);
strip.setPixelColor(9,68,68,0);
strip.setPixelColor(10,68,68,0);
strip.setPixelColor(11,68,68,0);
strip.setPixelColor(12,68,68,0);
strip.setPixelColor(13,68,68,0);
strip.setPixelColor(14,68,68,0);
strip.setPixelColor(15,68,68,0);
strip.show();
}
else if(frame==77) {  
strip.setPixelColor(0,50,50,50);
strip.setPixelColor(1,50,50,50);
strip.setPixelColor(2,50,50,50);
strip.setPixelColor(3,50,50,50);
strip.setPixelColor(4,50,50,50);
strip.setPixelColor(5,50,50,50);
strip.setPixelColor(6,50,50,50);
strip.setPixelColor(7,50,50,50);
strip.setPixelColor(8,50,50,50);
strip.setPixelColor(9,50,50,50);
strip.setPixelColor(10,50,50,50);
strip.setPixelColor(11,50,50,50);
strip.setPixelColor(12,50,50,50);
strip.setPixelColor(13,50,50,50);
strip.setPixelColor(14,50,50,50);
strip.setPixelColor(15,50,50,50);
strip.show();
}
}
void loop(){
char key = kpd.getKey();
if(key)  // Check for a valid key.
{
switch (key)
{
case '1':
frame = 1;
break;
case '#':
frame = 33;
break;
case '2':
frame = 35;
up = 0;
break;
case '3':
frame = 36;
break;
case '4':
frame = 71;
break;
case '5':
frame = 72;
break;
case '6':
frame = 73;
break;
case '7':
frame = 74;
break;
case '8':
frame = 75;
break;
case '9':
frame = 76;
break;
case '*':
frame = 77;
break;
case '0':
resetFunc();
break;
default:
break;
}
}
}

Did somebody say Business Cards and Build Kits?

Business Cards

Well, exciting news, we’ve finally ordered a small run of Accessible Pixel business cards.

Accessible Pixel Business Card – Front

Normally we’d use VistaPrint, but their prices aren’t that competitive any-more and you can only order 100 cards minimum, so I’ve tried a different company – 123Print. We have our first run of 50 on order with 280GSM paper stock, colour and double sided. We would have liked to have had rounded corners and thicker paper stock, but for a test run it has to be the most cost effective option that we choose 🙂

Accessible Pixel Business Card – Back

 

kits

The topic eluded to something else too…Kits! Yes, we now have an idea of how much kits will cost, and what it will realistically cost us to produce them.

A basic component kit* will include:

  • 1 x Arduino Nano Clone OR 1 x Arduino Pro Mini Clone (Your Choice)
  • 2 x WS2812 5050 LED 8 Pixel Module
  • 1 x 1000uF Electrolytic Capacitor
  • 2 x 470ohm Resistor
  • 3 x Pieces of connecting wire (Black, Red and Blue)
  • 1 x Piece of lead based solder
  • 1 x 3×4 matrix keypad
  • 1 x Mini USB Cable
  • 3 x Female Header Pins
  • 10 x Male Header Pins
  • 3 x Accessible Pixel Business Cards
  • 1 x Mini CD-ROM containing the Accessible Pixel code, drivers and the Arduino IDE
  • 1 x Cardboard Box (White Outside, Brown Inside)
  • 1 x Anti-static Protective Bag

A full build kit* will include all of the above plus:

  • 1 x 3D Printed Housing (Black)
  • 1 x Semi-Transparent Acrylic Plastic Front Cover (White)
  • 4 x Mounting screws
  • 1 x Microphone
  • 4 x Black Cable Ties

If you see us at an event, we will also include:

  • 1x 1200mAh USB Powerbank
  • 1x Micro USB Cable

We would like to include Powerbanks with every kit, however the postal service has restrictions on sending lithium based batteries through the post, so we can only include the Powerbank with kits that are bought from us at an event.

We are hoping to offer basic kits that will be available for a minimum donation of £20* to the project (+shipping) and hoping to offer the full build kits for a minimum donation of £30* plus shipping.

Please let us know if you are interested as demand may outstrip supply if we don’t know how many people are interested. We will also announce when the first kits are available. The full build kit won’t be available for a while since we are still designing them, however the component kits will be available soon depending on demand for them. If you would like to register your interest in one, please email media@accessiblepixel.com and let us know!

* Specifications and prices are subject to change without notice.

Inexpensive Powerbanks

Some inexpensive Powerbanks, which we bought at Poundland, a high-value discount store where most things cost just £1 GBP. We saw these Powerbanks a long time ago, but never decided to buy them – and regretted it. They were out of stock for a few weeks, but finally came back into our local store recently. They come with the Powerbank, a keyring, a cord and a small USB micro cable (about 15cm).

The capacity is rated at 1,200mAh. The Powerbank outputs a maximum of 1A at 5V, anything higher than an amp and the Powerbank struggles. When the capacity runs down, the power output is adjusted downwards to remain active. They are charged between 800mAh and 1000mA so a standard Wall Adaptor USB Plug will charge these just fine. While these are rated 1A, I wouldn’t rely on them for anything above 500mA. Still, as an inexpensive power source for small projects, you cannot beat the affordability.

Coupling these Powerbanks with USB key-chain 3 LED light circuit boards is an excellent idea. We bought these chip based USB plug devices from China on eBay for £1.98 for 10 pieces. They are exceptionally bright, and will last a while using one of these Powerbanks and make great emergency lights.

capacity tests

Battery Discharge 1 Charge 1 Discharge 2 Charge 2
Black 0500 mAh 0932 mAh 0640 mAh 0902 mAh
Pink 0600 mAh 0972 mAh 0580 mAh 0974 mAh
Blue 0600 mAh 0987 mAh 0534 mAh 0924 mAh
Green 0590 mAh 1027 mAh 0620 mAh 1016 mAh
White 0601 mAh 0943 mAh 0597 mAh 0984 mAh

These tests are based on using a KCX-17 USB Charge Monitor with a Drok Resistive USB Discharge Device running at a load of 500mA until the Powerbanks cut-off voltage was reached. This table does not account for the losses converting from the Lithium cell’s 3.7 volts to 5 volts.

Summary

Capacity however is what lets these Powerbanks down. While they claim 1200mAh, the cells are closer to 1,000mAh, and with conversion to 5v this capacity drops further to around 700mAh. All things considered though, you get not only the plastic case, circuit board, 18650 cell, cord, keyring and a USB cable there’s nothing stopping you opening up the Powerbank and adding a better 18650 cell (for example an unprotected 2,500mAh Samsung INR-25R for about £11.15 for two). These style plastic powerbanks are available without cell from China for 99p which in itself is good value, adding a lithium cell to them and selling them for £1 is great economy.

P.S: The only colour we don’t have is the Orange Powerbank, as they did not have any of those left.

More Microcontrollers – Digispark ATTiny85

Browsing eBay for additional Arduino hardware, I came across a Digispark ATTiny85 clone for £1.99 shipped from the UK. You can get them cheaper in bulk from China though. I did some searching on YouTube to see the kind of things that this development board is capable of. I initially searched for compatibility with the WS2812 LED strings, and yes – there’s someone running the Adafrult Neopixel Library and the srandtest sketch on the Digispark ATTiny85 🙂

These tiny boards can also be used for many other projects – including emulating a USB Keyboard. I might make something to switch input over on the future video recordings 🙂

Here are some specifications:

  • 16.5mHz Microcontroller
  • Power via USB or external source – 5v or 7-35v (Recommend 12v if 5v not available)
  • On-board 500ma 5v regulator
  • 6 I/O Pins (2 of which are used for USB port only if your program uses the USB port, otherwise all 6 are available)
  • 8k Flash Memory (~6k free after bootloader)
  • I2C and SPI (via USI)
  • PWM on 3 pins (more is possible via software PWM)
  • ADC on 4 pins
  • Power LED and Test/Status LED

One thing I quite like is the built in voltage regulator, this will come handy for tiny embedded projects!

There are some caveats to be aware of using this board though. There is no reverse voltage protection, so applying GND and +5 the wrong way around will almost certainly damage the board so perhaps a Diode would be helpful here or a MOSFET?

When uploading a sketch, you have to unplug and re-plug the device to enter programming mode (which the device stays in for 5000ms) then it will run whatever sketch you have uploaded to it.

I’m looking forward to testing this hardware out and now I’m just waiting for delivery 🙂

New Testing Hardware Arrived and New Code

So, my new Nano testing board with screw terminal break out shield arrived. My soldering is not perfect, but I am still waiting on some flux and desoldering wick to arrive to have another go at it. I’ve certainly seen worse though 🙂

The new iteration of the code adds more animations and control with the keypad. We’ll soon start making videos and uploading them so you can get a glimpse into Team Accessible Pixel’s workshop 🙂

// interrupt_animation_3.ino
// designed by AccessiblePixel.com
//Include Libraries
#include <Adafruit_NeoPixel.h>
#include <Keypad.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// Initialise Variables
#define PINBACK 9 // PIN for REAR light
#define PINFLOOR 10 // PIN for FLOOR light
#define PINFRONT 11 // PIN for FRONT light
volatile int frame=0;
volatile int backcolorframe=0;
volatile int r = 0;
volatile int g = 0;
volatile int b = 0;
volatile int brightred = 0;
volatile int brightgreen = 0;
volatile int brightblue = 0;
volatile int brightcolor = 0;
volatile int up = 0;
volatile int rainbowi = 0;
volatile int rainboww = 0;
// Initialise Pixels
Adafruit_NeoPixel stripBack = Adafruit_NeoPixel(16, PINBACK, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripFloor = Adafruit_NeoPixel(16, PINFLOOR, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripFront = Adafruit_NeoPixel(16, PINFRONT, NEO_GRB + NEO_KHZ800);
// Setup Keypad
const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 8, 7, 6, 5 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 4, 3, 2 }; 
// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// Main Setup Loop (Run Once At Start Up)
void setup() {
// Initialize Back Pixels
stripBack.begin();
stripBack.show(); 
// Initialize Floor Pixels
stripFloor.begin();
stripFloor.show();
// Initialize Front Pixels
stripFront.begin();
stripFront.show();
// Setup Interrupt at 32hz
// Stop Interrupts
cli();
// Clear Timer Register
TCCR1A = 0;// Set entire TCCR1A register to 0
TCCR1B = 0;// Same for TCCR1B
TCNT1  = 0;// Initialize counter value to 0
// set compare match register for 32hz increments
OCR1A = 488;// = (16*10^6) / (32*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);  
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
// Allow Interrupts
sei();
}//end setup loop
// Function Declarations
uint32_t wheelz(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return stripBack.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return stripBack.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return stripBack.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<stripBack.numPixels(); i++) {
stripBack.setPixelColor(i, c);
stripBack.show();
delay(wait);
}
}
// Run Animation Frames
ISR(TIMER1_COMPA_vect){
if(frame==1){ 
stripBack.setPixelColor(0,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==2) {  
stripBack.setPixelColor(1,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==3) {  
stripBack.setPixelColor(2,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==4) {  
stripBack.setPixelColor(3,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==5) {  
stripBack.setPixelColor(4,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==6) {  
stripBack.setPixelColor(5,r,g,b);
delay(50);
stripBack.show(); 
frame++;
}
else if(frame==7) {  
stripBack.setPixelColor(6,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==8) {  
stripBack.setPixelColor(7,r,g,b);
delay(50);
stripBack.show(); 
frame++;
}
else if(frame==9) {  
stripBack.setPixelColor(8,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==10) {  
stripBack.setPixelColor(9,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==11) {  
stripBack.setPixelColor(10,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==12) {  
stripBack.setPixelColor(11,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==13) {  
stripBack.setPixelColor(12,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==14) {  
stripBack.setPixelColor(13,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==15) {  
stripBack.setPixelColor(14,r,g,b);
stripBack.show(); 
frame++;
}
else if(frame==16) {  
stripBack.setPixelColor(15,r,g,b);
stripBack.show(); 
}
else if(frame==17){ 
stripBack.setPixelColor(15,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==18) {  
stripBack.setPixelColor(14,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==19) {  
stripBack.setPixelColor(13,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==20) {  
stripBack.setPixelColor(12,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==21) {  
stripBack.setPixelColor(11,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==22) {  
stripBack.setPixelColor(10,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==23) {  
stripBack.setPixelColor(9,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==24) {  
stripBack.setPixelColor(8,0,0,0);
delay(50);
stripBack.show(); 
frame++;
}
else if(frame==25) {  
stripBack.setPixelColor(7,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==26) {  
stripBack.setPixelColor(6,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==27) {  
stripBack.setPixelColor(5,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==28) {  
stripBack.setPixelColor(4,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==29) {  
stripBack.setPixelColor(3,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==30) {  
stripBack.setPixelColor(2,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==31) {  
stripBack.setPixelColor(1,0,0,0);
stripBack.show(); 
frame++;
}
else if(frame==32) {  
stripBack.setPixelColor(0,0,0,0);
stripBack.show(); 
} else if(frame==33) {
stripBack.setPixelColor(random(0,15),random(0,25),random(0,25),random(0,25));
stripBack.setPixelColor(random(0,15),0,0,0,0);
stripBack.setPixelColor(random(0,15),0,0,0,0);
delay(30);
stripBack.show();
}
else if(frame==34){stripBack.setPixelColor(0,0,0,0);
stripBack.setPixelColor(1,0,0,0);
stripBack.setPixelColor(2,0,0,0);
stripBack.setPixelColor(3,0,0,0);
stripBack.setPixelColor(4,0,0,0);
stripBack.setPixelColor(5,0,0,0);
stripBack.setPixelColor(6,0,0,0);
stripBack.setPixelColor(7,0,0,0);
stripBack.setPixelColor(8,0,0,0);
stripBack.setPixelColor(9,0,0,0);
stripBack.setPixelColor(10,0,0,0);
stripBack.setPixelColor(11,0,0,0);
stripBack.setPixelColor(12,0,0,0);
stripBack.setPixelColor(13,0,0,0);
stripBack.setPixelColor(14,0,0,0);
stripBack.setPixelColor(15,0,0,0);
stripBack.show();
}
else if(frame==35){
stripBack.setPixelColor(0,brightred,brightgreen,brightblue);
stripBack.setPixelColor(1,brightred,brightgreen,brightblue);
stripBack.setPixelColor(2,brightred,brightgreen,brightblue);
stripBack.setPixelColor(3,brightred,brightgreen,brightblue);
stripBack.setPixelColor(4,brightred,brightgreen,brightblue);
stripBack.setPixelColor(5,brightred,brightgreen,brightblue);
stripBack.setPixelColor(6,brightred,brightgreen,brightblue);
stripBack.setPixelColor(7,brightred,brightgreen,brightblue);
stripBack.setPixelColor(8,brightred,brightgreen,brightblue);
stripBack.setPixelColor(9,brightred,brightgreen,brightblue);
stripBack.setPixelColor(10,brightred,brightgreen,brightblue);
stripBack.setPixelColor(11,brightred,brightgreen,brightblue);
stripBack.setPixelColor(12,brightred,brightgreen,brightblue);
stripBack.setPixelColor(13,brightred,brightgreen,brightblue);
stripBack.setPixelColor(14,brightred,brightgreen,brightblue);
stripBack.setPixelColor(15,brightred,brightgreen,brightblue);
stripBack.show();
if (brightcolor==0) {
if (up == 0) {
if (brightred < 60) {
brightred++; 
}
else if (brightred == 60) {
brightred=60; 
up = 1;
} 
}
else if(up == 1) {
if(brightred > 0) {
brightred--;
} 
else if (brightred == 0) {
up = 0;brightcolor++;
} 
}
} 
else if (brightcolor==1) {
if (up == 0) {
if (brightgreen < 60) {
brightgreen++; 
}
else if (brightgreen == 60) {
brightgreen=60; 
up = 1;
} 
}
else if(up == 1) {
if(brightgreen > 0) {
brightgreen--;
} 
else if (brightgreen == 0) {
up = 0;brightcolor++;
} 
}
} 
else if (brightcolor==2) {
if (up == 0) {
if (brightblue < 60) {
brightblue++; 
}
else if (brightblue == 60) {
brightblue=60; 
up = 1;
} 
}
else if(up == 1) {
if(brightblue > 0) {
brightblue--;
} 
else if (brightblue == 0) {
up = 0;brightcolor=0;
} 
}
}            
}
else if(frame==36){
stripBack.setPixelColor(rainbowi, wheelz((rainbowi+rainboww) & 255));
stripFloor.setPixelColor(rainbowi, wheelz((rainbowi+rainboww) & 255));
stripFront.setPixelColor(rainbowi, wheelz((rainbowi+rainboww) & 255));
stripBack.show();
stripFloor.show();
stripFront.show();
if (rainbowi < 15 )
{ rainbowi++; } else if (rainbowi == 15) { rainbowi = 0; }
if (rainboww < 255 )
{rainboww++; } if (rainboww == 255) {rainboww =0; }
}
else if(frame==37){frame=0;}
}
void loop()
{
char key = kpd.getKey();
if(key)  // Check for a valid key.
{
switch (key)
{
case '1':
if(backcolorframe==0) {  
r = 60;
g = 0;
b = 0;
backcolorframe++;
frame = 1;
}
else if(backcolorframe==1) {
r = 0;
g = 60;
b = 0;
backcolorframe++; frame = 1;
}
else if(backcolorframe==2) {
r = 0;
g = 0;
b = 60;
backcolorframe++; frame = 1;
}
else if(backcolorframe==3) {
r = 30;
g = 0;
b = 30;
backcolorframe++; frame = 1;
}
else if(backcolorframe==4) {
r = 30;
g = 30;
b = 30;
backcolorframe=0; frame = 1;
}
break;
case '2':
frame = 17;
backcolorframe=0;
break;
case '3':
frame = 33;
break;
case '4':
frame = 35;
up = 0;
break;
case '*':
frame = 36;
break;
case '0':
frame = 34;
backcolorframe=0;
brightcolor=0;
brightred = 0;
brightgreen = 0;
brightblue = 0;
r = 0;
g = 0;
b = 0;
up = 0;
rainbowi = 0;
rainboww = 0;
break;
default:
break;
}
}
}

Interrupt Code with Animation Frames and Keypad Input

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 9
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.
volatile int frame=0;
#include <Keypad.h>
const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'A','0','B'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 8, 7, 6, 5 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 4, 3, 2 }; 
// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
//set pins as outputs
pinMode(13, OUTPUT);
// Fill the dots one after the other with a color
cli();//stop interrupts
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1  = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 977;// = (16*10^6) / (8*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);  
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
}//end setup
ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
if(frame==1){ 
strip.setPixelColor(0,60,0,0);
strip.show(); 
frame++;
}
else if(frame==2) {  
strip.setPixelColor(1,60,0,0);
strip.show(); 
frame++;
}
else if(frame==3) {  
strip.setPixelColor(2,60,0,0);
strip.show(); 
frame++;
}
else if(frame==4) {  
strip.setPixelColor(3,60,0,0);
strip.show(); 
frame++;
}
else if(frame==5) {  
strip.setPixelColor(4,60,0,0);
strip.show(); 
frame++;
}
else if(frame==6) {  
strip.setPixelColor(5,60,0,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==7) {  
strip.setPixelColor(6,60,0,0);
strip.show(); 
frame++;
}
else if(frame==8) {  
strip.setPixelColor(7,60,0,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==9) {  
strip.setPixelColor(8,60,0,0);
strip.show(); 
frame++;
}
else if(frame==10) {  
strip.setPixelColor(9,60,0,0);
strip.show(); 
frame++;
}
else if(frame==11) {  
strip.setPixelColor(10,60,0,0);
strip.show(); 
frame++;
}
else if(frame==12) {  
strip.setPixelColor(11,60,0,0);
strip.show(); 
frame++;
}
else if(frame==13) {  
strip.setPixelColor(12,60,0,0);
strip.show(); 
frame++;
}
else if(frame==14) {  
strip.setPixelColor(13,60,0,0);
strip.show(); 
frame++;
}
else if(frame==15) {  
strip.setPixelColor(14,60,0,0);
strip.show(); 
frame++;
}
else if(frame==16) {  
strip.setPixelColor(15,60,0,0);
strip.show(); 
}
else if(frame==17){ 
strip.setPixelColor(15,0,0,0);
strip.show(); 
frame++;
}
else if(frame==18) {  
strip.setPixelColor(14,0,0,0);
strip.show(); 
frame++;
}
else if(frame==19) {  
strip.setPixelColor(13,0,0,0);
strip.show(); 
frame++;
}
else if(frame==20) {  
strip.setPixelColor(12,0,0,0);
strip.show(); 
frame++;
}
else if(frame==21) {  
strip.setPixelColor(11,0,0,0);
strip.show(); 
frame++;
}
else if(frame==22) {  
strip.setPixelColor(10,0,0,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==23) {  
strip.setPixelColor(9,0,0,0);
strip.show(); 
frame++;
}
else if(frame==24) {  
strip.setPixelColor(8,0,0,0);
delay(50);
strip.show(); 
frame++;
}
else if(frame==25) {  
strip.setPixelColor(7,0,0,0);
strip.show(); 
frame++;
}
else if(frame==26) {  
strip.setPixelColor(6,0,0,0);
strip.show(); 
frame++;
}
else if(frame==27) {  
strip.setPixelColor(5,0,0,0);
strip.show(); 
frame++;
}
else if(frame==28) {  
strip.setPixelColor(4,0,0,0);
strip.show(); 
frame++;
}
else if(frame==29) {  
strip.setPixelColor(3,0,0,0);
strip.show(); 
frame++;
}
else if(frame==30) {  
strip.setPixelColor(2,0,0,0);
strip.show(); 
frame++;
}
else if(frame==31) {  
strip.setPixelColor(1,0,0,0);
strip.show(); 
frame++;
}
else if(frame==32) {  
strip.setPixelColor(0,0,0,0);
strip.show(); 
} else if(frame==33) {
strip.setPixelColor(random(16),random(0,25),random(0,25),random(0,25));
strip.setPixelColor(random(16),0,0,0,0);
strip.setPixelColor(random(16),0,0,0,0);
delay(30);
strip.show();
}
else if(frame==34){frame=0;}
}
void loop()
{
char key = kpd.getKey();
if(key)  // Check for a valid key.
{
switch (key)
{
case '1':
frame = 1;
break;
case '2':
frame = 17;
break;
case '3':
frame = 33;
break;
default:
break;
}
}
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}

Timer Interrupt Test

Here is some of my test code for setting up a timer1 interrupt. It is based on some code that I found at http://www.instructables.com/id/Arduino-Timer-Interrupts/

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 9
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.
boolean toggle1 = 0;
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
//set pins as outputs
pinMode(13, OUTPUT);
// Fill the dots one after the other with a color
cli();//stop interrupts
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1  = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);  
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
}//end setup
ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
if (toggle1){    
digitalWrite(13,HIGH);
toggle1 = 0;
}
else{
digitalWrite(13,LOW);
toggle1 = 1;
}
}
void loop() {
colorWipe(strip.Color(1, 1, 1), 25);
colorWipe(strip.Color(0, 0, 0), 25);
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
Skip to content