Created
September 3, 2013 04:14
-
-
Save rwinscot/6419667 to your computer and use it in GitHub Desktop.
Expands on the Robo_Face.ino sketch by adding a NeoPixel Stick for the mouth. Animation is based on a time-slice rather than delays.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on the 'roboface' example sketch for Adafruit I2C 8x8 LED | |
// backpacks: | |
// | |
// www.adafruit.com/products/870 www.adafruit.com/products/1049 | |
// www.adafruit.com/products/871 www.adafruit.com/products/1050 | |
// www.adafruit.com/products/872 www.adafruit.com/products/1051 | |
// www.adafruit.com/products/959 www.adafruit.com/products/1052 | |
// | |
// And the NeoPixel Stick... | |
// | |
// www.adafruit.com/products/1426 | |
// | |
// Requires Adafruit_LEDBackpack, Adafruit_GFX, and Adafruit_NeoPixel | |
// libraries. For a simpler introduction, see the 'matrix8x8' for the | |
// 8x8 LED matrix or 'strandtest' for the NeoPixel Stick. | |
// | |
// This sketch demonstrates a couple of useful techniques: | |
// 1) Using a time-slice to animate eyes rather than using delay. | |
// 2) Displaying the same data on multiple matrices by sharing the | |
// same I2C address. | |
// 3) Adding-in a NeoPixel Stick for the mouth. | |
// | |
// This example uses 2 matrices on the same address (two share an address) | |
// to animate a pair of eyes: | |
// | |
// 0 0 <--- 8x8 LED Matrix | |
// | |
// ooooooo <--- NeoPixel Strip | |
// | |
// The 'eyes' both display the same image (always looking the same | |
// direction -- can't go cross-eyed) and thus share the same address | |
// (0x70). | |
// | |
// The 'mouth' displays a single color on all eight pixels. | |
// | |
// Adafruit invests time and resources providing this open source code, | |
// please support Adafruit and open-source hardware by purchasing | |
// products from Adafruit! | |
// | |
// Original example written by P. Burgess for Adafruit Industries, | |
// modified by Rick Winscot. | |
// | |
// BSD license, all text above must be included in any redistribution. | |
#include <Arduino.h> | |
#include <Wire.h> | |
#include <Adafruit_NeoPixel.h> | |
#include "Adafruit_LEDBackpack.h" | |
#include "Adafruit_GFX.h" | |
byte LED = 13; // debug LED on the Arduino | |
unsigned long tme = 0; // the last time we processed doBlink() | |
unsigned long slc = 20; // milliseconds between animation calls | |
unsigned long ms = 0; // a millis() time-slice | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, 3, NEO_GRB + NEO_KHZ800); | |
Adafruit_8x8matrix matrix = Adafruit_8x8matrix(); | |
static uint8_t PROGMEM // Bitmaps are stored in program memory | |
blinkImg[][8] = { // Eye animation frames | |
{ B00111100, // Fully open eye | |
B01111110, | |
B11111111, | |
B11111111, | |
B11111111, | |
B11111111, | |
B01111110, | |
B00111100 }, | |
{ B00000000, | |
B01111110, | |
B11111111, | |
B11111111, | |
B11111111, | |
B11111111, | |
B01111110, | |
B00111100 }, | |
{ B00000000, | |
B00000000, | |
B00111100, | |
B11111111, | |
B11111111, | |
B11111111, | |
B00111100, | |
B00000000 }, | |
{ B00000000, | |
B00000000, | |
B00000000, | |
B00111100, | |
B11111111, | |
B01111110, | |
B00011000, | |
B00000000 }, | |
{ B00000000, // Fully closed eye | |
B00000000, | |
B00000000, | |
B00000000, | |
B10000001, | |
B01111110, | |
B00000000, | |
B00000000 } }; | |
uint8_t | |
blinkIndex[] = { 1, 2, 3, 4, 3, 2, 1 }, // Blink bitmap sequence | |
blinkCountdown = 100, // Countdown to next blink (in frames) | |
gazeCountdown = 75, // Countdown to next eye movement | |
gazeFrames = 50, // Duration of eye movement (smaller = faster) | |
mouthPos = 0, // Current image number for mouth | |
mouthCountdown = 10; // Countdown to next mouth change | |
int8_t | |
eyeX = 3, eyeY = 3, // Current eye position | |
newX = 3, newY = 3, // Next eye position | |
dX = 0, dY = 0; // Distance from prior to new position | |
void setup() { | |
pinMode( LED, OUTPUT );// set Arduino LED as output - for debug blink | |
strip.begin(); | |
strip.show(); | |
randomSeed(analogRead(A0)); | |
matrix.begin(0x70); | |
} | |
void loop() { | |
ms = millis(); | |
digitalWrite(LED, LOW); // slices less than 100ms are difficult to see | |
if ( tme + slc < ms ) { | |
tme = ms; | |
digitalWrite(LED, HIGH); // set slc > 100ms to debug | |
// Single color fill for the mouth | |
uint32_t clr = strip.Color(0, 0, 255); | |
for(uint16_t i=0; i<strip.numPixels(); i++) { | |
strip.setPixelColor(i, clr); | |
strip.show(); | |
} | |
// Begin eye animation | |
matrix.clear(); | |
matrix.drawBitmap(0, 0, | |
blinkImg[ | |
(blinkCountdown < sizeof(blinkIndex)) ? // Currently blinking? | |
blinkIndex[blinkCountdown] : // Yes, look up bitmap # | |
0 // No, show bitmap 0 | |
], 8, 8, LED_ON); | |
// Decrement blink counter. At end, set random time for next blink. | |
if(--blinkCountdown == 0) blinkCountdown = random(5, 180); | |
// Add a pupil (2x2 black square) atop the blinky eyeball bitmap. | |
// Periodically, the pupil moves to a new position... | |
if(--gazeCountdown <= gazeFrames) { | |
// Eyes are in motion - draw pupil at interim position | |
matrix.fillRect( | |
newX - (dX * gazeCountdown / gazeFrames), | |
newY - (dY * gazeCountdown / gazeFrames), | |
2, 2, LED_OFF); | |
if(gazeCountdown == 0) { // Last frame? | |
eyeX = newX; eyeY = newY; // Yes. What's new is old, then... | |
do { // Pick random positions until one is within the eye circle | |
newX = random(7); newY = random(7); | |
dX = newX - 3; dY = newY - 3; | |
} while((dX * dX + dY * dY) >= 10); // Thank you Pythagoras | |
dX = newX - eyeX; // Horizontal distance to move | |
dY = newY - eyeY; // Vertical distance to move | |
gazeFrames = random(3, 15); // Duration of eye movement | |
gazeCountdown = random(gazeFrames, 120); // Count to end of next movement | |
} | |
} else { | |
// Not in motion yet -- draw pupil at current static position | |
matrix.fillRect(eyeX, eyeY, 2, 2, LED_OFF); | |
} | |
matrix.writeDisplay(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment