Wednesday, 6 June 2012

Codes for Matrix


#include "TimerOne.h"

/***************************************************************/
/************************** CONSTANTS **************************/
/***************************************************************/

// The amount of time in milliseconds the heart must be fully on after it completes.
const int HeartCompletedOnTimer = 2000;

// The amount of time in milliseconds the heart must fade out after it completes.
const int HeartCompletedOffTimer = 1000;

// The timer interval used to advance column, in microseconds.
const int ScreenColumnTimer = 2200;

// The digital pin that is used to read the heart beat detector.
const byte BeatInputPin = 23;

// Minimum time in milliseconds between a zero to one transition of valid beat bit.
// This is used to filter some false positive beats.
const int BeatUpTimer = 140;

// Minimum time in milliseconds between a one to zero transition of valid beat bit.
// This is used to filter some false positive beats.
const int BeatDownTimer = 150;

// The amount of light to increment when a led fades in
const byte FadeInAmount = 64;

// The minimum amount of light to decrement when a led fades out.
const byte FadeOutMinAmount = 4;

// The maximum amount of light to decrement when a led fades out.
const byte FadeOutMaxAmount = 24;

// Pins used to drive led matrix rows.
const byte ScreenRowPins[] = {
  2, 3, 5, // PWM TIMER 3
  6, 7, 8, // PWM TIMER 4
  9, 10    // PWM TIMER 2
};

// Pins used to drive led matrix columns.
const byte ScreenColumnPins[] = {
  14, 15, 16, 17, 18, 19, 20, 21
};

/***************************************************************/
/**************************** FIELDS ***************************/
/***************************************************************/

// Counter used to advance the screen column.
byte ScreenColumnCounter = 0;

// This portion of memory represent the content of the led matrix.
byte Screen[8][8];

// Keep track of the previous beat input pin state, synchronous to the main loop.
boolean BeatInputOld = true;

// The heart beat state, filtered from false positives.
boolean BeatValidated = true;

// When true, indicates that the heart is completed and the timer for restarting again started.
boolean HeartCompleted = false;

// Keep track of the last time in milliseconds when a valid beat input went from zero to one.
unsigned long BeatUpTime = 0;

// Keep track of the last time in milliseconds when a valid beat input went from one to zero.
unsigned long BeatDownTime = 0;

// Keep track of the last time in milliseconds when the hearth was completed.
unsigned long HeartCompletedTime = 0;

// HeartPixels array contains all the coordinates pair
// of pixels that can draw a full hearth.
// Coordinates pairs are encoded as (y + x * 8).
byte HeartPixels[] = {
     8, 16,         40, 48,  
 1,  9, 17, 25, 33, 41, 49, 57,
 2, 10, 18, 26, 34, 42, 50, 58,
 3, 11, 19, 27, 35, 43, 51, 59,
 4, 12, 20, 28, 36, 44, 52, 60,
    13, 21, 29, 37, 45, 53,  
        22, 30, 38, 46,      
            31, 39
};

// A table of random number we use to fade out leds in randomized time.
byte HeartFadeOutTable[8][8];

// Number of currently used pins in the HeartPixels array.
byte HeartPixelsCounter = 0;

// The number of elements in HeartPixels array.
const byte HeartPixelsSize = sizeof(HeartPixels);

/***************************************************************/
/************************** FUNCTIONS **************************/
/***************************************************************/

// Randomize the HeartFadeOutTable matrix to give a different fadeout timing for each led.
// A random value between FadeOutMinAmount and FadeOutMaxAmount is used for each pixel.
void RandomizeHeartFadeOutTable() {
  for (byte x = 0; x < 8; ++x) {
    for (byte y = 0; y < 8; ++y) {
      HeartFadeOutTable[x][y] = random(FadeOutMinAmount, FadeOutMaxAmount);
    }
  }
}

// Shuffle the HeartPixels array using a pseudorandom number generator.
// The array at the end will contains the same items but in random order
void ShuffleHeartPixelsArray() {
  // The array shuffler just swap every item in the array with a random item.
  for (byte a=0; a < HeartPixelsSize; ++a)
  {
    // Pix a random index.
    byte r = random(a, HeartPixelsSize);
 
    // Swap current item with the random index.
    byte temp = HeartPixels[a];
    HeartPixels[a] = HeartPixels[r];
    HeartPixels[r] = temp;
  }
}

// Interrupt function called to output a column to the led matrix.
void outputScreen() {
    // It's time to process one screen row.

    // We turn off the previous column.
    digitalWrite(ScreenColumnPins[ScreenColumnCounter], LOW);
 
    // We increment the column counter, wrapping to zero when it reaches 7.
    ScreenColumnCounter = (ScreenColumnCounter + 1) & 0x07;

    for (byte i = 0; i < 8; ++i) {
      // Turn off the row.
      digitalWrite(ScreenRowPins[i], 0);
      // We write the PWM value into the row.
      analogWrite(ScreenRowPins[i], Screen[ScreenColumnCounter][i]);
    }
 
    // We turn on the new column.
    digitalWrite(ScreenColumnPins[ScreenColumnCounter], HIGH);
 
    if (ScreenColumnCounter == 7) {
      // Last column, we can update the screen content.

      if (!BeatValidated) {
 
        // Fade out.
 
        for (byte x = 0; x < 8; ++x) {
          for (byte y = 0; y < 8; ++y) {
            byte v = Screen[x][y];
            byte f = HeartFadeOutTable[x][y];
            Screen[x][y] = v > f ? v - f : 0;
          }
        }
 
      } else {
 
        // Fade in.
     
        // For each pixel in the heart ...
        for (byte i = 0; i < HeartPixelsCounter; ++i) {
          byte coordinates = HeartPixels[i];
       
          // Decode the coordinates stored in HeartPixels[i]
          byte y = coordinates & 0x7;
          byte x = coordinates >> 3;
       
          // Pixel fade in
          byte v = Screen[x][y];
          Screen[x][y] = (v < 255 - FadeInAmount) ? v + FadeInAmount : 255;
        }
 
      }
    }
}

/***************************************************************/
/**************************** SETUP ****************************/
/***************************************************************/

void setup() {

  // Setup input pin.

  // Set the BeatInputPin as input and enable the pullup resistor.
  pinMode(BeatInputPin, INPUT_PULLUP);

  // Setup output pins.

  for (byte i = 0; i < 8; ++i) {
    pinMode(ScreenColumnPins[i], OUTPUT);
    digitalWrite(ScreenColumnPins[i], LOW);
    pinMode(ScreenRowPins[i], OUTPUT);
    analogWrite(ScreenRowPins[i], 0);
  }

  // Clear the screen.
  for (byte x = 0; x < 8; ++x) {
    for (byte y = 0; y < 8; ++y) {
      Screen[x][y] = 0;
    }
  }

  // Shuffle the heart pixel array so the pixel sequence looks random.
  ShuffleHeartPixelsArray();

  // Fill the fadeout table with random numbers
  RandomizeHeartFadeOutTable();

  // Setup the PWM timers for faster frequency.
  // We need higher frequency because we are using a multiplexed led matrix.
  // pwmFrequencyFlag = 0x04 means  488.28125 hertz (default)
  // pwmFrequencyFlag = 0x03 means  976.5625  hertz
  // pwmFrequencyFlag = 0x02 means 3926.25    hertz

  const byte pwmFrequencyFlag = 0x03;

  TCCR2B = (TCCR2B & 0xF8) | pwmFrequencyFlag;
  TCCR3B = (TCCR3B & 0xF8) | pwmFrequencyFlag;
  TCCR4B = (TCCR4B & 0xF8) | pwmFrequencyFlag;

  // Setup the timer interrupt to output the screen to the led matrix

  Timer1.initialize(ScreenColumnTimer);
  Timer1.attachInterrupt(outputScreen);
}

/***************************************************************/
/************************** MAIN LOOP **************************/
/***************************************************************/

void loop()
{
  // Gets current time in milliseconds.
  unsigned long now = millis();

  if (HeartCompleted) {
    // This code gets executed only when the heart was completed.

    unsigned long timeDiff = now - HeartCompletedTime;
    if (timeDiff < HeartCompletedOnTimer) {
      // The heart is completed, keep it on until HeartCompletedOnTimer milliseconds passes.
      BeatValidated = true;
    } else if (timeDiff < (HeartCompletedOnTimer + HeartCompletedOffTimer)) {
      // The heart is completed and we already waited the HeartCompletedOnTimer, fade it out.
      BeatValidated = false;
    } else {
      // We need to reset the hearth.
      HeartCompleted = false;
   
      // Reset the counter so we start drawing pixels again from the beginning.
      HeartPixelsCounter = 0;
   
      // Shuffle the array so the pixel sequence will follow a different order.
      ShuffleHeartPixelsArray();

      // Fill the fadeout table with random numbers
      RandomizeHeartFadeOutTable();
    }

  } else {
    // Beat detector code
 
    // We read the current beat input pin state.
    boolean beatInput = digitalRead(BeatInputPin);
 
    // If currently read input is different from the old input...
    if (beatInput != BeatInputOld) {
      BeatInputOld = beatInput;
      if (beatInput) {
        // Check if enough time since last time the pin was down passed.
        if (now - BeatDownTime > BeatDownTimer) {
          BeatUpTime = now;
       
          if (!BeatValidated) {
            BeatValidated = true;

            if (HeartPixelsCounter < HeartPixelsSize - 1) {
              // We add a pixel to the screen.
              ++HeartPixelsCounter;
            } else {
              // The heart is completed!
              HeartCompleted = true;
              // Store the completion time, in milliseconds.
              HeartCompletedTime = now;
            }
          }
        }
      }
      else if (BeatValidated) {
        // Store the time when the pin became down.
        BeatDownTime = now;
      }
    }
    else if (now - BeatUpTime > BeatUpTimer) {
      // The pin is high for too much time
      BeatValidated = false;
    }
  }
}

Schematics

Analog 



LED Matrix





Naresh in Action


The process of soldering and cutting loose wires.

Things you need and need to know!

Soldering Basics




Shopping List