/* Spin8.pde - manually spin running lights in a sideways figure eight Spin8 Arduino Turn example Copyright (c) 2011 Devon Sean McCullough Licensed under the GPL (GNU Public License) Requires the Bounce, Turn, Trixel and LiquidCrystal libraries, a phase quadrature encoded control knob and a 10x2 or better LCD display with 5 or more characters of font RAM. http://arduino.cc/playground/Code/Bounce http://csail.mit.edu/~devon/Arduino/Turn http://csail.mit.edu/~devon/Arduino/Trixel Mama's LCD Card <===> MotherboardShield <===> Arduino Arduino Hard- Silk- Sketch pin ware screen symbol ---- ------ ------ ------ D0 Serial RX D1 Serial TX D2 Knob EA D3 Knob EB D4 LCD D4 D5 LCD D5 D6 LCD D6 D7 LCD D7 D8 D9 Knob EKNOB KNOB_PRESS D10 D11 LCD RS D12 LCD Enable D13 Serial uses pins 0, 1 Knob uses pins 2*, 3**, 9 LCD uses pins 4, 5, 6, 7, 11, 12 * Arduino pin D2 triggers interrupt 0 ** Arduino pin D3 triggers interrupt 1 */ #include #include #include #include // RS Enable D4 D5 D6 D7 LiquidCrystal lcd(11, 12, 4, 5, 6, 7); // 1x3 character graphic display Trixel trix( &lcd); // interrupt EA interrupt EB EA EB Turn knob( 0, 1, 2, 3); const int KNOB_PRESS = 9; // 5ms debounce time Bounce press(KNOB_PRESS, 5); /* 10 x 6 trixel matrix (in 10 x 2 LCD) // (dotimes (y 6) (princ "\n ") (dotimes (x 10) (princ (format " %3d," (+ x (* y 10)))))) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 1, 2, 7, 8, 10, 13, 16, 19, 20, 24, 25, 29, 30, 34, 35, 39, 40, 43, 46, 49, 51, 52, 57, 58, */ const byte path[] = { 1, 2, 13, 24, 35, 46, 57, 58, // down-right 49, 39, 29, 19, // up 8, 7, 16, 25, 34, 43, 52, 51, // down-left 40, 30, 20, 10 // up }; const byte pattern[] = {1, 1, 1, 0, 0, 0, 0, 0}; #define SIZEOF_ARRAY(a) (sizeof(a)/sizeof(*(a))) int mod (int quotient, int divisor) { // A reasonable compiler would reduce mod to a single machine instruction int remainder = quotient % divisor; if (remainder < 0) remainder += divisor; return remainder; } void setup() { pinMode(KNOB_PRESS, INPUT); // knob click input digitalWrite(KNOB_PRESS, HIGH); // ... with pullup lcd.begin(12, 2); // LCD size in columns and rows trix.begin(10, 2); // ... Trixel area size trix.moveWindow(1, 0); // ... and offset lcd.print(" turn/click"); // show instructions on LCD ... lcd.setCursor(0, 1); lcd.print("control knob"); delay(1000); knob.sleep(); // ... until user turns knob lcd.clear(); // mimic the Arduino[tm] logo lcd.setCursor(0, 1); lcd.write('-'); lcd.setCursor(11, 0); lcd.write('+'); } byte knob_mode = 0; // start in speed mode int old_count = 0; int phase = 0; void loop () { int count = knob.count() / 4; // four phases per click of this particular knob int delta = count - old_count; old_count = count; // Click knob to toggle position/speed modes byte knob_clicked = press.update() && press.risingEdge(); knob_mode ^= knob_clicked; if (knob_mode) { // position phase += delta; delay(10); } else { // speed phase += (count < 0 ? -1 : 1); int milliseconds = 200 / (count < 0 ? -count : count == 0 ? 1 : count); delay(milliseconds); #if 0 // speed limit if (milliseconds < 5) { knob.reset(); knob_mode = 1; } #endif } phase = mod(phase, SIZEOF_ARRAY(path)); // redisplay for (int i = 0; i < SIZEOF_ARRAY(path); i++) { int offset = mod(i - phase, SIZEOF_ARRAY(pattern)); byte xy = path[i]; byte x = xy % 10; byte y = xy / 10; trixel_color color = (trixel_color)pattern[offset]; trix.setDot(x, y, color); } trix.show(); } // end Spin8.pde