multiplexing 10x10 led matrix and a Memsick 2125 accelerometer

So I'm having trouble getting both of these to work with each other. The ultimate goal is to have a 2x2 dot that moves around the x and y of the led matrix according to the readings from the accelerometer. I haven't gotten to the dot point though because pulseIn() pauses the multiplexing code and creates a pretty nasty flicker. I was thinking of using a another atmega chip to split the load. That way I'd have one reading the accelerometer and sending the numbers to the one controlling the led matrix. I'm working with the Uno at the moment, but I do have some atmega8's laying around. However, I'd still like to keep it on one chip if it is possible. Any suggestions?

Chris

Hi neato3000,

You will need to supply more info on how your driving the 10x10 LED matrix and what accelerometer chip your using. I assume your using something like interrupt driven multiplexing techniques for the LEDS and the pulseIn() is disrupting this.
You could drive the LED matrix with something like the MAX7219 and then you can set and forget about them as it deals with all the multiplexing. Maybe you can do your own interrupt driven pulseIn routine.

I don't see why you need the pulseIn() function at all?

And yes, it is causing delays, which is not what you want when writing lots of changing outputs by multipexing, SPI or shiftOut()

creates a pretty nasty flicker

Sounds like you already have a (yet disappointing) approach to share and discuss.

Oops, I thought I replied last night ha ha, oh well.

The LED matrix is a very home brew circuit that I put together really before I knew what multiplexing was, so it might be a little unique. The device has two decade counters that run through the rows and columns while a transistor turns on at the end to let the current through only when the counters get to a specified LED. I had originally designed this using Visual Basic 6 and the Parallel port from my computer. The software is a loop that processes an array(the image)and sequences 5 pins to run the 2 clocks and resets of the counters, and the trigger transistor. It works great, but a little power hungry I think.

The accelerometer is the one from Radioshack, the Memsic 2125. The code I found to work was in the example code that comes with the arduino ide. But I quickly got bored of looking at the output over the serial port and set it up with some LEDS to measure one Axis. Then I had the idea of using this LED matrix I have to plot out both Axis. But Like I said as soon as I introduce the pulseIn() code to the LED code, I get flicker since the pulse it reads can be almost 20ms long from each axis. Last night I was able to read the accelerometer using interrupts, but that killed the LED code altogether.

Here is the code for the LED Matrix with out the accelerometer. Right now it is set up to scroll "Neato3000 :)" while stopping at the smiley for a second or two. I suppose I can make a video so every one can see what it looks like. I'll look into that. Any ideas on running both devices on the same chip? Or should just throw the towel and add a second controller?

int tPin = 2; //trigger pin, the pin that turns on the last stage transistor to allow electricity through the circuit the counters have pointed to
int xPin = 4; //x counter clock pin
int yPin = 3; //y counter clock pin
int r1Pin = 7; // counter 1 reset
int r2Pin = 8; // counter 2 reset
int intDel = 175; //trigger pin on time, higher times increase brightness, but also increase flicker
int intMillTime = 0;
int Framer = 0;

// green leads are clock
//white leads are reset
//inner black lead is trigger
//outer black lead is ground
//inner red wire is counter Vcc
//outer red wire is LED Vcc


//each array is made up of a series of decimal numbers that represent 10 bit binary numbers (0 through 1023)
//which will be converted later in the code as a column, and placed in the row it belongs to.
int picUno[10] = {
  0, 204, 204, 204, 476, 0, 510, 252, 120, 0};
int allOn[10] = {
  1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023};
int bioPic[10] = {
  72, 132, 132, 204, 120, 510, 633, 561, 48, 204};
int earthPic[10] = {
  120, 132, 386, 999, 975, 783, 975, 322, 132, 120};
int bugPic[10] = {
  0, 132, 120, 1007, 220, 1007, 220, 378, 258, 0};
int scroller[] = {
  0,0,0,0,0,0,0,0,0,0,1023,1023,224,112,56,28,1023,1023,0,62,127,219,219,219,123,59,0,14,223,211,211,126,63,3,192,192,1022,1023,195,195,0,60,126,195,195,126,60,0,390,903,819,819,1023,462,0,252,510,903,819,903,510,252,0,252,510,903,819,903,510,252,0,252,510,903,819,903,510,252,0,0,0,0,0,0,0,204,486,199,7,7,199,486,204,0,0,0,0,0,0,0,0,0,0};

void setup() {

  pinMode(tPin,OUTPUT);
  pinMode(xPin,OUTPUT);
  pinMode(yPin,OUTPUT);
  pinMode(r1Pin,OUTPUT);
  pinMode(r2Pin,OUTPUT);
  digitalWrite(r1Pin, HIGH); 
  digitalWrite(r2Pin, HIGH);
  delay(1);
  digitalWrite(r1Pin, LOW);
  digitalWrite(r2Pin, LOW);
  delay(1);
  digitalWrite(tPin,LOW); 
  intMillTime = millis();

}

void loop() {
  //Reset both counters
  digitalWrite(r2Pin, HIGH);
  digitalWrite(r2Pin, LOW);
  digitalWrite(r1Pin, HIGH); 
  digitalWrite(r1Pin, LOW);

  //Animation Timing
  int intMillNow = millis();
  int intTimeSpan = intMillNow - intMillTime;


  //This first if statement is here to stop the scroll effect at the smiley frame

    if(Framer == 84){
    if(intTimeSpan > 2000){
      Framer = ++Framer;
      intMillTime = millis();

    }
  } 
  else{                       
    //Remove or comment out from the last comment to here
    //to remove the stop on the smiley.
    //(don't forget the extra curly bracket below!!!)

    //Animation delay time
    if(intTimeSpan > 50){
      intMillTime = millis();
      Framer = ++Framer;
      //Once yer at the final frame, reset the frame counter 
      //to 0, set this condition to the length of your array.
      //This is set for the 82 length array that contains the 
      //scrolling "Neato3000 :)" normally a 10x10 picture should 
      //just be 10.
      if(Framer > 92){
        Framer = 0;
      }
    }
  }
  // Remove or comment from animation timing to here and set 
  // Framer = 0; 
  // for the other images.

  //send the data to the led matrix by reading the column 
  //information from the array one row at a time.
  //Basically everything below prints the array.
  for(int iy = 0; iy < 10; iy++){

    String myPntr;
    //This is the line that defines the array(image) to use, 
    //as well as adding the frame count to adjust the array
    //pointer to "scroll" the array if 'Framer' is changed in
    //the code above.
    int myNum = scroller[iy + Framer];
    
    //This converts the number in the array that was picked in the 
    //last line to a 10 bit binary number.
    int zeros = 10 - String(myNum,BIN).length();
    String myStr;

    for (int i=0; i<zeros; i++) {
      myStr = myStr + "0";
    }
    myStr = myStr + String(myNum,BIN); 
    
    //This scans through the current row relative to the
    //10 bit binary number triggering the tPin if it 
    //comes across a '1'.
    for(int ix = 0; ix < 10; ix++) {
      myPntr = myStr[ix];
      if(myPntr == "1") {
        digitalWrite(tPin, HIGH); 
        delayMicroseconds(intDel);
        digitalWrite(tPin, LOW); 
      }
      digitalWrite(yPin, LOW); 
      digitalWrite(yPin, HIGH); 
    }
    digitalWrite(xPin, LOW); 
    digitalWrite(xPin, HIGH);  
  }
}

I don't know if something like the below code will work for you. I'm currently without my UNO so cannot confirm code works though it compiles okay. The UNO has 2 interrupt pins so if this works then duplicate code and attach to other interrupt pin so you have X and Y results from your memsic. I don't know if you need pullup resistors on the interrupt inputs so delete if not needed.
All the interrupt routine does (should do) is store current millis() value on a rising edge of the interrupt pin and subtract it from the millis() of the last rising edge to give you T2. If the edge is falling then it subtracts current millis() from last stored millis() to give you T1. It's then for the main loop code to determine what to do with it.

int InterruptPin = 2;	// Pin INT0 is connected to memsic 2125 x out
volatile long T0 = 0;	// Used internally by interrupt routine
volatile long T1 = 0;	// Memsic 2125 T1 duration (see http://www.parallax.com/dl/docs/prod/acc/memsickit.pdf) in milliseconds
volatile long T2 = 0;	// Memsic 2125 T2 duration in milliseconds

void setup()
{
    pinMode(InterruptPin, INPUT);	// Make interrupt pin input
    digitalWrite(InterruptPin, HIGH);	// *** Enable pullup resistors (is this needed?)
    attachInterrupt(0, pulse, CHANGE);	// Setup interrupt service routine
    Serial.begin(9600);
}

void loop()
{
    delay(1000);
    Serial.print("T1 = ");
    Serial.println(T1);
    Serial.print("T2 = ");
    Serial.println(T2);
}

//Interrupt routine
void pulse(){
    long temp = millis();
    if (InterruptPin == HIGH){	// Rising edge
        T2 = temp - T0;		// Subtract from last rising edge time to determine T2
        T0=temp;		// Store time
    }
    else {			// Falling edge
        T1 = temp - T0;		// Subtract from last rising edge to determine T1
    }
}

I just connected my UNO and loaded the interrupt sketch but it's not working as expected. Maybe some brighter minds than mine can figure out why. I only seem to get falling edge in interrupt routine.

EDIT:
Silly mistake, need to replace
if (nterruptPin == HIGH){ // Rising edge
with
if (digitalRead(InterruptPin) == HIGH){ // Rising edge

I don't know if something like the below code will work for you. I'm currently without my UNO so cannot confirm code works though it compiles okay. The UNO has 2 interrupt pins so if this works then duplicate code and attach to other interrupt pin so you have X and Y results from your memsic. I don't know if you need pullup resistors on the interrupt inputs so delete if not needed.
All the interrupt routine does (should do) is store current millis() value on a rising edge of the interrupt pin and subtract it from the millis() of the last rising edge to give you T2. If the edge is falling then it subtracts current millis() from last stored millis() to give you T1. It's then for the main loop code to determine what to do with it.

I think it is going to work. It makes a lot of sense since it just records the time the line changes, does a little math, then lets the uno go about the rest of it's business. Right now the code is set with your interrupt routine, and is definitely getting the right numbers. The flicker is next to nothing on the led matrix, which has a static image on display. The next thing to do is display the dot that moves according to the memsic readouts. Thanks Riva!

I did notice I can't use Serial.print(); though. At least not as many as I am using... I would like to be able to send the information over bluetooth to my android tablet for logging and charting. This may sound silly, but what are the chances that using one big serial print is faster than 8 smaller ones? What about baud rate, higher or lower?

Well Thanks again Riva, The whole thing went together just fine, and it is displaying a line that moves according to the x axis on the memsic. On to the y Axis, then a 2x2 dot.

I'm glad the code worked for you, luckily there are 2x hardware interrupts so should work fine with both X & Y. Not sure why Serial.print stops working for you though (or does it cause flicker?)

it causes a flicker every time I use more than 2 serial.prints with the baud rate set at 115200. 9600 gives off a nice dark pause with one statement. I still have to come up with how I am going to send the data to the tablet in the first place though. Since I can get away with at least 2 prints, I can atleast do something like

string xTx = "x" + accelerationX;
serial.println(xTx);
string yTx = "y" + accelerationY;
serial.println(yTx);

I'll have to look into it though because the arduino reference says something funny about assigning a string variable like this.

Here is the code so far:

int tPin = 4; //trigger pin, the pin that turns on the last stage transistor to allow electricity through the circuit the counters have pointed to
int xPin = 6; //x counter clock pin
int yPin = 8; //y counter clock pin
int r1Pin = 7; // counter 1 reset
int r2Pin = 5; // counter 2 reset
int intDel = 150; //trigger pin on time, higher times increase brightness, but also increase flicker
int intMillTime = 0;
int Framer = 0;

const int xaPin = 2;		// X output of the accelerometer
const int yaPin = 3;		// Y output of the accelerometer


// variables to contain the resulting accelerations
float accelerationX, accelerationY;

volatile float xT0 = 0;	// Used internally by interrupt routine
volatile float xT1 = 0;	// Memsic 2125 T1 duration (see http://www.parallax.com/dl/docs/prod/acc/memsickit.pdf) in microseconds
volatile float xT2 = 0;	// Memsic 2125 T2 duration in microseconds

volatile float yT0 = 0;	// Used internally by interrupt routine
volatile float yT1 = 0;	// Memsic 2125 T1 duration (see http://www.parallax.com/dl/docs/prod/acc/memsickit.pdf) in microseconds
volatile float yT2 = 0;	// Memsic 2125 T2 duration in microseconds

//green leads are clock
//white leads are reset
//inner black lead is trigger
//outer black lead is ground
//inner red wire is Vcc
//inner red wire is Vcc


//each array represents an image, each index is a row, 

int picUno[10] = {
  0, 204, 204, 204, 476, 0, 510, 252, 120, 0}; // maybe make the picture move accordingly... someday

int dot[] = {
  0,0,0,0,0,0,0,0,0,0,48, 48, 0,0,0,0,0,0,0,0,0,0,}; //beginning structure of the dot array. this could be all zeros
                                                     // but it this helps to see what is going on a little easier

void setup() {
  Serial.begin(115200);

  pinMode(xaPin, INPUT);
  pinMode(yaPin, INPUT);

  pinMode(tPin,OUTPUT);
  pinMode(xPin,OUTPUT);
  pinMode(yPin,OUTPUT);
  pinMode(r1Pin,OUTPUT);
  pinMode(r2Pin,OUTPUT);

  digitalWrite(r1Pin, HIGH); 
  digitalWrite(r2Pin, HIGH);
  delay(1);
  digitalWrite(r1Pin, LOW);
  digitalWrite(r2Pin, LOW);
  delay(1);
  digitalWrite(tPin,LOW); 

  intMillTime = millis();

  attachInterrupt(0, xRead, CHANGE);
  attachInterrupt(1, yRead, CHANGE);
}

void loop() {

  //Animation Timing
  int intMillNow = millis();
  int intTimeSpan = intMillNow - intMillTime;

  //Create and move the dot
  if(intTimeSpan > 10){

    accelerationY = ((((yT1 / 10) - 500) * 8) / 1000) ;
    int xer = accelerationY * 5 + 5;
    dot[10] = (pow(2,xer)+1)+(pow(2,xer+1));
    dot[11] = (pow(2,xer)+1)+(pow(2,xer+1));

    accelerationX = ((((xT1 / 10) - 500) * 8) / 1000) ;
    int yer = accelerationX * 5 -8;
    Framer = yer + 1;

    Serial.println(accelerationY);
    Serial.println(accelerationX);
    intMillTime = millis();
  }


  //Reset both counters
  digitalWrite(r2Pin, HIGH);
  digitalWrite(r2Pin, LOW);
  digitalWrite(r1Pin, HIGH); 
  digitalWrite(r1Pin, LOW);
  
  // Print the dot 
  for(int iy = 0; iy < 10; iy++){ 
    String myPntr;
  //this is where you decide which image you want. change 'dot' to picUno and 
  //keep Framer = 0 for a 10x10 image.
    int myNum = dot[iy - Framer];
    int zeros = 10 - String(myNum,BIN).length();
    String myStr;

    for (int i=0; i<zeros; i++) {
      myStr = myStr + "0";
    }

    myStr = myStr + String(myNum,BIN); 
    for(int ix = 0; ix < 10; ix++) {
      myPntr = myStr[ix];
      if(myPntr == "1") {
        digitalWrite(tPin, HIGH); 
        delayMicroseconds(intDel);
        digitalWrite(tPin, LOW); 
      }
      digitalWrite(yPin, LOW); 
      digitalWrite(yPin, HIGH); 
    }
    digitalWrite(xPin, LOW); 
    digitalWrite(xPin, HIGH);  
  }
}

void xRead(){
  long temp = micros();
  if (digitalRead(xaPin) == HIGH){	// Rising edge
    xT2 = temp - xT0;		// Subtract from last rising edge time to determine T2
    xT0=temp;		// Store time
  }
  else {			// Falling edge
    xT1 = temp - xT0;		// Subtract from last rising edge to determine T1
  }
}

void yRead(){
  long temp = micros();
  if (digitalRead(yaPin) == HIGH){	// Rising edge
    yT2 = temp - yT0;		// Subtract from last rising edge time to determine T2
    yT0=temp;		// Store time
  }
  else {			// Falling edge
    yT1 = temp - yT0;		// Subtract from last rising edge to determine T1
  }
}

and heres a couple videos about whats going on here.

Thanks again!

Hi neato3000,

Had a quick look at your code and have a couple of ideas to reduce flicker.
If the final purpose of the project is not speed critical then do you need to read accelerometer 100 time a second (if(intTimeSpan > 10){) reducing this should help reduce flicker.
Failing that then maybe only calculate and Serial.print one axis per run by using a flipflop variable.

Had a quick look at your code and have a couple of ideas to reduce flicker.
If the final purpose of the project is not speed critical then do you need to read accelerometer 100 time a second (if(intTimeSpan > 10){) reducing this should help reduce flicker.
Failing that then maybe only calculate and Serial.print one axis per run by using a flipflop variable.

Your right about the time span, I had set that at 10 just see the response, but it just makes the dot twitchy. Setting it some where between 50 and 75 is probably the best I've seen. With that, I don't think that the flip flop variable would work right since each axis would be polled 50ms from each other. I'd like them as close as possible. Next thing is to set the bluetooth up and make an android app that'll log and chart the information. Thanks again!