0

Building a 9x9 LED matrix and facing following 2 problems in Arduino code,

The current code displays 2 images (using byte arrays and then using bitRead) one by one, each for a certain duration of seconds. Persistence of vision is obtained by a delay of 300ms. There is a subroutine called upon in the main loop function with arguments of desired byte array and duration. I want to control the images by using 2 push buttons (push button1 and it displays 1st image until button2 is pressed, push button2 and second image is displayed until button1 is pressed). But the scanning algorithm exits the scan routine upon completion of the given input duration and restarts the routine with new argument (byte array of image2). I WANT THE IMAGE TO BE RETAINED ON THE MATRIX UNTIL BUTTON IS PRESSED. Can't figure out how to accomplish this.

If i nest the routine in a DO WHILE loop, then my problem is that how will the buttons be read from the main loop? Because I believe as long as the subroutine is being executed, main loop will be halted. (or I am totally wrong in this assumption?)

Reference code which I intend to manipulate. (Here its for an 8x8 Matrix. Thats not an issue)

byte bigHeart[] = {
    B01100110,
    B11111111,
    B11111111,
    B11111111,
    B01111110,
    B00111100,
    B00011000,
    B00000000};

byte smallHeart[] = {
    B00000000,
    B00000000,
    B00010100,
    B00111110,
    B00111110,
    B00011100,
    B00001000,
    B00000000};

const int columnPins[] = { 2, 3, 4, 5, 6, 7, 8, 9};
const int rowPins[] = { 10,11,12,15,16,17,18,19};

void setup() {
    for (int i = 0; i < 8; i++)
    {
        pinMode(rowPins[i], OUTPUT); // make all the LED pins outputs
        pinMode(columnPins[i], OUTPUT);
        digitalWrite(columnPins[i], HIGH); // disconnect column pins from Ground
    }
}

void loop() {
    int pulseDelay = 800 ; // milliseconds to wait between beats
    show(smallHeart, 80); // show the small heart image for 100 ms
    show(bigHeart, 160); // followed by the big heart for 200ms
    delay(pulseDelay); // show nothing between beats
}

// routine to show a frame of an image stored in the array pointed to by the
// image parameter.
// the frame is repeated for the given duration in milliseconds
void show( byte * image, unsigned long duration)
{
    unsigned long start = millis(); // begin timing the animation
    while (start + duration > millis()) // loop until the duration period has passed
    {
        for(int row = 0; row < 8; row++)
        {
            digitalWrite(rowPins[row], HIGH); // connect row to +5 volts
            for(int column = 0; column < 8; column++)
            {
                boolean pixel = bitRead(image[row],column);
                if(pixel == 1)
                {
                    digitalWrite(columnPins[column], LOW); // connect column to Gnd
                }
                delayMicroseconds(300); // a small delay for each LED
                digitalWrite(columnPins[column], HIGH); // disconnect column from Gnd
            }

            digitalWrite(rowPins[row], LOW); // disconnect LEDs
        }
    }
}
4
  • 1
    Why don't you show the code rather than trying to explain it? That would make it easier for others to help you!
    – jfpoilpret
    Feb 4, 2015 at 17:54
  • Place the button tests inside the Do...WHILE Loops Feb 5, 2015 at 1:23
  • Code added @jfpoilpret Feb 5, 2015 at 10:45
  • @RussellMcMahon I am using a push button. And i dont want to keep the button pressed to display its associated image. Just one time push and leave. Feb 5, 2015 at 10:46

1 Answer 1

1

OK. Figured out a solution which is working for me. Upon reading a forum on Arduino.cc. That stated a nice analogy to handle this issue.

You have something to heat up on stove while also waiting for an important email which you have to respond to immediately. (You only have a PC in the farthest corner of house at which you have to monitor your outlook :D) How will you do both tasks simultaneously? Run the stove for 10seconds, go to PC to check email, return to stove, run it again for 10 seconds, then again go to PC to check email. Do this until you get the email or your food gets hot enough.

To implement this in our program. I read the states of 2 buttons at start of the main loop. Store their values in 2 variables. Then check the values to check if some button is pressed. if value A is 1 and B is 0, call function A, if A is 0 and B is 1 call function B. The called function comprises of the scan routine. So when called, it performs 1 scan and comes back to the main loop. If no button was pressed meanwhile, the variables have same values, so the same function is called again and it performs the 2nd scan. if a button was pressed meanwhile, then 2nd function is called instead of the 1st one. The speed of all this is enough so that the user does not experience any delays, neither Arduino misses a button pressed while executing the scan.

The LEDs started to flicker when I implemented this code. So I further reduced the delay in the scan routine (time for which each LED is lit before turning it off and lighting the next one) from 300 microsecond to 100 and all went fine. My matrix of 64 LEDs is working fine however I assume that if matrix goes beyond some 100 LEDs then problems like delay or flickering or reduced brightness may arise.

Here is the complete code

byte img1[] = {
    B01100110,
    B11111111,
    B11111111,
    B11111111,
    B01111110,
    B00111100,
    B00011000,
    B00000000
};

byte img2[] = {
    B00000000,
    B01100110,
    B01100110,
    B00000000,
    B00011000,
    B10000001,
    B01000010,
    B00111100
};

const int rowPins[] = {13,12,11,10,9,8,7,6};
const int columnPins[] = {5,4,3,2,14,15,16,17};

const int but1 = 18;
const int but2 = 19;

int but1State = 0;
int but2State = 0;
int but1Now;
int but2Now;

int value1;
int value2;

void setup() {

    for (int i = 0; i<8; i++){
        pinMode(rowPins[i], OUTPUT);
        pinMode(columnPins[i], OUTPUT);
        digitalWrite(columnPins[i], HIGH); 
    }

    pinMode(but1, INPUT);
    pinMode(but2, INPUT);

    but1State = digitalRead(but1);
    but2State = digitalRead(but2);
}

void loop() {

    but1Now = digitalRead(but1);
    delay(5);
    int but1Now1 = digitalRead(but1);

    if(but1Now == but1Now1) 
    {
        if(but1Now != but1State)
        {
            value1 = 1;
            value2 = 0;
            //show(img2);
        }

        but1State = but1Now;
    }

    but2Now = digitalRead(but2);
    delay(5);
    int but2Now1 = digitalRead(but2);

    if(but2Now == but2Now1) 
    {
        if(but2Now != but2State)
        {
            value1 = 0;
            value2 = 1;
            //show(img2);
        }

        but2State = but2Now;
    }

    if(value1 == 1)
    {
        show(img1);
    }

    if(value2 == 1)
    {
        show(img2);
    }
}

void show(byte*image) {

    for(int row = 0; row<8; row++) 
    {
        digitalWrite(rowPins[row], HIGH);

        for(int col=0; col<8; col++) 
        { 
            boolean pixel = bitRead(image[row],col);

            if(pixel == 1) 
            {
                digitalWrite(columnPins[col], LOW);
            }

            delayMicroseconds(150);
            digitalWrite(columnPins[col], HIGH);
        }

        digitalWrite(rowPins[row], LOW);
    }
}
2
  • 1
    Please, PLEASE format your code. Feb 10, 2015 at 13:50
  • But that's not what you actually do, is it? You turn on the audio notificaiton so you don't have to constantly check if the email is there, you get notified when it is. Same with the stove. You set a timer and you let it work until the timer goes off. See what I'm getting at?
    – Jasmine
    Feb 10, 2015 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.