项目代码
- #include <LedControl.h>
-
- //We always have to include the LedControl library
- #include "LedControl.h"
-
- /*
- Create LetControl object, define pin connections
- We have 2 MAX72XX for eyes.
- */
- #define PIN_EYES_DIN 12
- #define PIN_EYES_CS 11
- #define PIN_EYES_CLK 10
- LedControl lc = LedControl(PIN_EYES_DIN, PIN_EYES_CLK, PIN_EYES_CS, 2);
-
- // rotation
- bool rotateMatrix0 = false; // rotate 0 matrix by 180 deg
- bool rotateMatrix1 = false; // rotate 1 matrix by 180 deg
-
- // define eye ball without pupil
- byte eyeBall[8]={
- B00111100,
- B01111110,
- B11111111,
- B11111111,
- B11111111,
- B11111111,
- B01111110,
- B00111100
- };
-
- byte eyePupil = B11100111;
-
- // stores current state of LEDs
- byte eyeCurrent[8];
- int currentX;
- int currentY;
- int cntLoop = 0;
- int cntEffect = 0;
-
- // min and max positions
- #define MIN -2
- #define MAX 2
-
- // delays
- #define DELAY_BLINK 40
-
- // perform an effect every # of loop iterations, 0 to disable
- #define EFFECT_ITERATION 4
-
- /*
- Arduino setup
- */
- void setup()
- {
- // MAX72XX is in power-saving mode on startup, we have to do a wakeup call
- lc.shutdown(0,false);
- lc.shutdown(1,false);
-
- // set the brightness to low
- lc.setIntensity(0,1);
- lc.setIntensity(1,1);
-
- // clear both modules
- lc.clearDisplay(0);
- lc.clearDisplay(1);
-
- // LED test
- // vertical line
- byte b = B10000000;
- for (int c=0; c<=7; c++)
- {
- for (int r=0; r<=7; r++)
- {
- setRow(0, r, b);
- setRow(1, r, b);
- }
- b = b >> 1;
- delay(50);
- }
- // full module
- b = B11111111;
- for (int r=0; r<=7; r++)
- {
- setRow(0, r, b);
- setRow(1, r, b);
- }
- delay(500);
-
- // clear both modules
- lc.clearDisplay(0);
- lc.clearDisplay(1);
- delay(500);
-
- // random seed
- randomSeed(analogRead(0));
-
- // center eyes, crazy blink
- displayEyes(0, 0);
- delay(2000);
- blinkEyes(true, false);
- blinkEyes(false, true);
- delay(1000);
-
- }
-
- /*
- Arduino loop
- */
- void loop()
- {
- // move to random position, wait random time
- moveEyes(random(MIN, MAX + 1), random(MIN, MAX + 1), 50);
- delay(random(5, 7) * 500);
-
- // blink time?
- if (random(0, 5) == 0)
- {
- delay(500);
- blinkEyes();
- delay(500);
- }
-
- // effect time?
- if (EFFECT_ITERATION > 0)
- {
- cntLoop++;
- if (cntLoop == EFFECT_ITERATION)
- {
- cntLoop = 0;
- if (cntEffect > 6) cntEffect = 0;
- switch(cntEffect)
- {
- case 0: // cross eyes
- crossEyes();
- delay(1000);
- break;
-
- case 1: // round spin
- roundSpin(2);
- delay(1000);
- break;
-
- case 2: // crazy spin
- crazySpin(2);
- delay(1000);
- break;
-
- case 3: // meth eyes
- methEyes();
- delay(1000);
- break;
-
- case 4: // lazy eye
- lazyEye();
- delay(1000);
- break;
-
- case 5: // crazy blink
- blinkEyes(true, false);
- blinkEyes(false, true);
- delay(1000);
- break;
-
- case 6: // glow
- glowEyes(3);
- delay(1000);
- break;
-
- default:
- break;
- }
- cntEffect++;
- }
- }
- }
-
- /*
- This method blinks both eyes
- */
- void blinkEyes()
- {
- blinkEyes(true, true);
- }
-
- /*
- This method blinks eyes as per provided params
- */
- void blinkEyes(boolean blinkLeft, boolean blinkRight)
- {
- // blink?
- if (!blinkLeft && !blinkRight)
- return;
-
- // close eyelids
- for (int i=0; i<=3; i++)
- {
- if (blinkLeft)
- {
- setRow(0, i, 0);
- setRow(0, 7-i, 0);
- }
- if (blinkRight)
- {
- setRow(1, i, 0);
- setRow(1, 7-i, 0);
- }
- delay(DELAY_BLINK);
- }
-
- // open eyelids
- for (int i=3; i>=0; i--)
- {
- if (blinkLeft)
- {
- setRow(0, i, eyeCurrent[i]);
- setRow(0, 7-i, eyeCurrent[7-i]);
- }
- if (blinkRight)
- {
- setRow(1, i, eyeCurrent[i]);
- setRow(1, 7-i, eyeCurrent[7-i]);
- }
- delay(DELAY_BLINK);
- }
- }
-
- /*
- This methods moves eyes to center position,
- then moves horizontally with wrapping around edges.
- */
- void crazySpin(int times)
- {
- if (times == 0)
- return;
-
- moveEyes(0, 0, 50);
- delay(500);
-
- byte row = eyePupil;
- for (int t=0; t<times; t++)
- {
- // spin from center to L
- for (int i=0; i<5; i++)
- {
- row = row >> 1;
- row = row | B10000000;
- setRow(0, 3, row); setRow(1, 3, row);
- setRow(0, 4, row); setRow(1, 4, row);
- delay(50);
- if (t == 0)
- delay((5-i)*10); // increase delay on 1st scroll (speed up effect)
- }
- // spin from R to center
- for (int i=0; i<5; i++)
- {
- row = row >> 1;
- if (i>=2)
- row = row | B10000000;
- setRow(0, 3, row); setRow(1, 3, row);
- setRow(0, 4, row); setRow(1, 4, row);
- delay(50);
- if (t == (times-1))
- delay((i+1)*10); // increase delay on last scroll (slow down effect)
- }
- }
- }
-
- /*
- This method crosses eyes
- */
- void crossEyes()
- {
- moveEyes(0, 0, 50);
- delay(500);
-
- byte pupilR = eyePupil;
- byte pupilL = eyePupil;
-
- // move pupils together
- for (int i=0; i<2; i++)
- {
- pupilR = pupilR >> 1;
- pupilR = pupilR | B10000000;
- pupilL = pupilL << 1;
- pupilL = pupilL | B1;
-
- setRow(0, 3, pupilR); setRow(1, 3, pupilL);
- setRow(0, 4, pupilR); setRow(1, 4, pupilL);
-
- delay(100);
- }
-
- delay(2000);
-
- // move pupils back to center
- for (int i=0; i<2; i++)
- {
- pupilR = pupilR << 1;
- pupilR = pupilR | B1;
- pupilL = pupilL >> 1;
- pupilL = pupilL | B10000000;
-
- setRow(0, 3, pupilR); setRow(1, 3, pupilL);
- setRow(0, 4, pupilR); setRow(1, 4, pupilL);
-
- delay(100);
- }
- }
-
- /*
- This method displays eyeball with pupil offset by X, Y values from center position.
- Valid X and Y range is [MIN,MAX]
- Both LED modules will show identical eyes
- */
- void displayEyes(int offsetX, int offsetY)
- {
- // ensure offsets are in valid ranges
- offsetX = getValidValue(offsetX);
- offsetY = getValidValue(offsetY);
-
- // calculate indexes for pupil rows (perform offset Y)
- int row1 = 3 - offsetY;
- int row2 = 4 - offsetY;
-
- // define pupil row
- byte pupilRow = eyePupil;
-
- // perform offset X
- // bit shift and fill in new bit with 1
- if (offsetX > 0) {
- for (int i=1; i<=offsetX; i++)
- {
- pupilRow = pupilRow >> 1;
- pupilRow = pupilRow | B10000000;
- }
- }
- else if (offsetX < 0) {
- for (int i=-1; i>=offsetX; i--)
- {
- pupilRow = pupilRow << 1;
- pupilRow = pupilRow | B1;
- }
- }
-
- // pupil row cannot have 1s where eyeBall has 0s
- byte pupilRow1 = pupilRow & eyeBall[row1];
- byte pupilRow2 = pupilRow & eyeBall[row2];
-
- // display on LCD matrix, update to eyeCurrent
- for(int r=0; r<8; r++)
- {
- if (r == row1)
- {
- setRow(0, r, pupilRow1);
- setRow(1, r, pupilRow1);
- eyeCurrent[r] = pupilRow1;
- }
- else if (r == row2)
- {
- setRow(0, r, pupilRow2);
- setRow(1, r, pupilRow2);
- eyeCurrent[r] = pupilRow2;
- }
- else
- {
- setRow(0, r, eyeBall[r]);
- setRow(1, r, eyeBall[r]);
- eyeCurrent[r] = eyeBall[r];
- }
- }
-
- // update current X and Y
- currentX = offsetX;
- currentY = offsetY;
- }
-
- /*
- This method corrects provided coordinate value
- */
- int getValidValue(int value)
- {
- if (value > MAX)
- return MAX;
- else if (value < MIN)
- return MIN;
- else
- return value;
- }
-
- /*
- This method pulsates eye (changes LED brightness)
- */
- void glowEyes(int times)
- {
- for (int t=0; t<times; t++)
- {
- for (int i=2; i<=8; i++)
- {
- lc.setIntensity(0,i);
- lc.setIntensity(1,i);
- delay(50);
- }
-
- delay(250);
-
- for (int i=7; i>=1; i--)
- {
- lc.setIntensity(0,i);
- lc.setIntensity(1,i);
- delay(25);
- }
-
- delay(150);
- }
- }
-
- /*
- This method moves eyes to center, out and then back to center
- */
- void methEyes()
- {
- moveEyes(0, 0, 50);
- delay(500);
-
- byte pupilR = eyePupil;
- byte pupilL = eyePupil;
-
- // move pupils out
- for (int i=0; i<2; i++)
- {
- pupilR = pupilR << 1;
- pupilR = pupilR | B1;
- pupilL = pupilL >> 1;
- pupilL = pupilL | B10000000;
-
- setRow(0, 3, pupilR); setRow(1, 3, pupilL);
- setRow(0, 4, pupilR); setRow(1, 4, pupilL);
-
- delay(100);
- }
-
- delay(2000);
-
- // move pupils back to center
- for (int i=0; i<2; i++)
- {
- pupilR = pupilR >> 1;
- pupilR = pupilR | B10000000;
- pupilL = pupilL << 1;
- pupilL = pupilL | B1;
-
- setRow(0, 3, pupilR); setRow(1, 3, pupilL);
- setRow(0, 4, pupilR); setRow(1, 4, pupilL);
-
- delay(100);
- }
- }
-
- /*
- This method moves both eyes from current position to new position
- */
- void moveEyes(int newX, int newY, int stepDelay)
- {
- // set current position as start position
- int startX = currentX;
- int startY = currentY;
-
- // fix invalid new X Y values
- newX = getValidValue(newX);
- newY = getValidValue(newY);
-
- // eval steps
- int stepsX = abs(currentX - newX);
- int stepsY = abs(currentY - newY);
-
- // need to change at least one position
- if ((stepsX == 0) && (stepsY == 0))
- return;
-
- // eval direction of movement, # of steps, change per X Y step, perform move
- int dirX = (newX >= currentX) ? 1 : -1;
- int dirY = (newY >= currentY) ? 1 : -1;
- int steps = (stepsX > stepsY) ? stepsX : stepsY;
- int intX, intY;
- float changeX = (float)stepsX / (float)steps;
- float changeY = (float)stepsY / (float)steps;
- for (int i=1; i<=steps; i++)
- {
- intX = startX + round(changeX * i * dirX);
- intY = startY + round(changeY * i * dirY);
- displayEyes(intX, intY);
- delay(stepDelay);
- }
- }
-
- /*
- This method lowers and raises right pupil only
- */
- void lazyEye()
- {
- moveEyes(0, 1, 50);
- delay(500);
-
- // lower left pupil slowly
- for (int i=0; i<3; i++)
- {
- setRow(1, i+2, eyeBall[i+2]);
- setRow(1, i+3, eyeBall[i+3] & eyePupil);
- setRow(1, i+4, eyeBall[i+4] & eyePupil);
- delay(150);
- }
-
- delay(1000);
-
- // raise left pupil quickly
- for (int i=0; i<3; i++)
- {
- setRow(1, 4-i, eyeBall[4-i] & eyePupil);
- setRow(1, 5-i, eyeBall[5-i] & eyePupil);
- setRow(1, 6-i, eyeBall[6-i]);
- delay(25);
- }
- }
-
- /*
- This method spins pupils clockwise
- */
- void roundSpin(int times)
- {
- if (times == 0)
- return;
-
- moveEyes(2, 0, 50);
- delay(500);
-
- for (int i=0; i<times; i++)
- {
- displayEyes(2, -1); delay(40); if (i==0) delay(40);
- displayEyes(1, -2); delay(40); if (i==0) delay(30);
- displayEyes(0, -2); delay(40); if (i==0) delay(20);
- displayEyes(-1, -2); delay(40);if (i==0) delay(10);
- displayEyes(-2, -1); delay(40);
- displayEyes(-2, 0); delay(40);
- displayEyes(-2, 1); delay(40);if (i==(times-1)) delay(10);
- displayEyes(-1, 2); delay(40);if (i==(times-1)) delay(20);
- displayEyes(0, 2); delay(40); if (i==(times-1)) delay(30);
- displayEyes(1, 2); delay(40); if (i==(times-1)) delay(40);
- displayEyes(2, 1); delay(40); if (i==(times-1)) delay(50);
- displayEyes(2, 0); delay(40);
- }
- }
-
-
- /*
- This method sets values to matrix row
- Performs 180 rotation if needed
- */
- void setRow(int addr, int row, byte rowValue)
- {
- if (((addr == 0) && (rotateMatrix0)) || (addr == 1 && rotateMatrix1))
- {
- row = abs(row - 7);
- rowValue = bitswap(rowValue);
- }
-
- lc.setRow(addr, row, rowValue);
- }
-
-
- /*
- Reverse bits in byte
- http://www.nrtm.org/index.php/2013/07/25/reverse-bits-in-a-byte/
- */
- byte bitswap (byte x)
- {
- byte result;
-
- asm("mov __tmp_reg__, %[in] \n\t"
- "lsl __tmp_reg__ \n\t" /* shift out high bit to carry */
- "ror %[out] \n\t" /* rotate carry __tmp_reg__to low bit (eventually) */
- "lsl __tmp_reg__ \n\t" /* 2 */
- "ror %[out] \n\t"
- "lsl __tmp_reg__ \n\t" /* 3 */
- "ror %[out] \n\t"
- "lsl __tmp_reg__ \n\t" /* 4 */
- "ror %[out] \n\t"
-
- "lsl __tmp_reg__ \n\t" /* 5 */
- "ror %[out] \n\t"
- "lsl __tmp_reg__ \n\t" /* 6 */
- "ror %[out] \n\t"
- "lsl __tmp_reg__ \n\t" /* 7 */
- "ror %[out] \n\t"
- "lsl __tmp_reg__ \n\t" /* 8 */
- "ror %[out] \n\t"
- : [out] "=r" (result) : [in] "r" (x));
- return(result);
- }
复制代码
|