Learning Arrays for a TIX Clock

Incase you havent heard of a TIX clock, this is what one looks like. Basically, it lights up the number of squares in an area according to the time. For example, here is a TIX clock displaying "12:34". Notice there are 1, 2, 3, and 4 segments lit up, respectively:

Here is my code:

int colPins[9];
int rowPins[3];
const int delayTime = 500; // in uS
int timeArray[3][9]; // [rows][columns]

void setup() 
{
  for (int i = 0; i < 9; i++) // set up column pins
  {
    colPins[i] = i;
    pinMode(colPins[i], OUTPUT);
  }
  for (int j = 0; j < 3; j++) // set up row pins
  {
    rowPins[j] = (j + 10);
    pinMode(rowPins[j], OUTPUT);
  }

  int time = 1559;

  int hours = time / 100;
  int hourstens = hours / 10;
  int hoursones = hours % 10;
  int hourstensarray[3];
  for (int a = 0; a < 3; a++)
    hourstensarray[a] = 0;
  for (int a = 0; a < hourstens; a++)
    hourstensarray[a] = 1;
  int hoursonesarray[9];
  for (int a = 0; a < 9; a++)
    hoursonesarray[a] = 0;
  for (int a = 0; a < hoursones; a++)
    hoursonesarray[a] = 1;

  int mins = time % 100;
  int minstens = mins / 10;
  int minsones = mins % 10;
  int minstensarray[6];
  for (int a = 0; a < 6; a++)
    minstensarray[a] = 0;
  for (int a = 0; a < minstens; a++)
    minstensarray[a] = 1;
  int minsonesarray[9];
  for (int a = 0; a < 9; a++)
    minsonesarray[a] = 0;
  for (int a = 0; a < minsones; a++)
    minsonesarray[a] = 1;

  timeArray[0][0] = hourstensarray[2];
  timeArray[0][1] = hoursonesarray[8];
  timeArray[0][2] = hoursonesarray[7];
  timeArray[0][3] = hoursonesarray[6];
  timeArray[0][4] = minstensarray[5];
  timeArray[0][5] = minstensarray[4];
  timeArray[0][6] = minsonesarray[8];
  timeArray[0][7] = minsonesarray[7];
  timeArray[0][8] = minsonesarray[6];
  timeArray[1][0] = hourstensarray[1];
  timeArray[1][1] = hoursonesarray[5];
  timeArray[1][2] = hoursonesarray[4];
  timeArray[1][3] = hoursonesarray[3];
  timeArray[1][4] = minstensarray[3];
  timeArray[1][5] = minstensarray[2];
  timeArray[1][6] = minsonesarray[5];
  timeArray[1][7] = minsonesarray[4];
  timeArray[1][8] = minsonesarray[3];
  timeArray[2][0] = hourstensarray[0];
  timeArray[2][1] = hoursonesarray[2];
  timeArray[2][2] = hoursonesarray[1];
  timeArray[2][3] = hoursonesarray[0];
  timeArray[2][4] = minstensarray[1];
  timeArray[2][5] = minstensarray[0];
  timeArray[2][6] = minsonesarray[2];
  timeArray[2][7] = minsonesarray[1];
  timeArray[2][8] = minsonesarray[0];
}

void loop() 
{
  for (int r = 0; r < 3; r++) // light the led if its corresponding timeArray value is 1
  {
    digitalWrite(rowPins[r], HIGH);
    for (int c = 0; c < 9; c++)
    {
      if (timeArray[r][c] = 1)
      {
        digitalWrite(colPins[c], HIGH);
        delayMicroseconds(delayTime);
        digitalWrite(colPins[c], LOW);
      }
    }
    digitalWrite(rowPins[r], LOW);
  }
}

I have pins 0-8 wired to columns 0-8, and pins 10-13 wired to rows 0-2 (LEDs driven by 2N2222's or 2N3904's). A 1 turns on the transistor.

I have tested (using Serial) the contents of timeArray at the very end of the setup loop, and it is loaded correctly, so I have a feeling my problem lies in the loop code (or something blatantly obvious - Ive made a few stupid mistakes already!). When I run this code, all the LEDs turn on. I only want the ones who's array value is 1 to turn on. I apologize if my code is redundant and does unnecessary things; Ive never made a matrix before so i wanted to have it as blown up as possible, to make sure I dont miss anything. Can anyone see what Im doing wrong?

You haven't assigned any values to colPins or rowPins so they will both be filled with zeros. This should do the trick...

int colPins[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int rowPins[3] = { 10, 11, 12 };

They are set up right under the void setup() line.

EDIT: It seems like the following line is always returning true. I never get a serial output from the else loop (I removed wires from pins 0 and 1).

if (timeArray[r]
c** ** = 1)[/b]      {        digitalWrite(colPins[c], HIGH);        delayMicroseconds(delayTime);        digitalWrite(colPins[c], LOW);        //Serial.println("timeArray = 1");      }      else      {        digitalWrite(colPins[c], LOW);        Serial.println("timeArray = 0");      }[/quote]** **

that should be:
if (timeArray[r] [glow]== [/glow]1)

Wow, see, told you itd be something simple!

My next question is about randomization. Id like to randomly fill the array, instead of going from 0 -> max. Id also like to display a new random pattern every couple seconds or so. Im working on hooking up an RTC (DS1307) so until thats implemented, Im keeping time as an int. How do I fill an array randomly?

They are set up right under the void setup() line

Dang! Sorry about that.

Here is some pseudocode for one way to do this

Create a function to display each digit, something like –

void showDigit int digit, int startColumn, int maxValue)
{
for( int i=0; i < digit; i++)
{
int pos = getFreeRandomVal(maxValue);
int row = count % rowSize ;
digitalWrite(rowPins[row], HIGH);
digitalWrite(colPins[startCol + (pos / rowSize)], HIGH);
}
}

In loop, call the function with the digit to display, the colum that digit starts in, and the maximum value of that digit.

void loop()
{
// code to get the hours and minutes here?.
showDigitt(Hour / 10,0, 2); // 1 for 12 hour clock, 2 for 24 hours
showDigitt(Hour % 10,1,9);
showDigitt(Minute / 10,4,5);
showDigit(Minute % 10,6,9);
}

// a function to get a value less than or equal to the maximum value that has not already been returned
int getFreeRandomVal(maxValue)
{

you could use an array or a bitmask to hold candidate values to be selected by the random function

The range of available values should be reset for each call to showDigit
}

Maybe I can redeam myself this time...

I think this needs to be [10] instead of [9]...

  int hoursonesarray[9];

How do I fill an array randomly?

This should fit well with what you already have...

  for (int a = 0; a < 9; a++)
    hoursonesarray[a] = 0;

  for (int a = 0; a < hoursones; a++)
  {
    int b;
    do
    {
      b = random( 0, 10 );
    }
    while ( hoursonesarray[b] == 1 )

    hoursonesarray[b] = 1;
  }

and here is a sketch (untested) that uses the software DateTime library from the playground that should display hours, minutes and seconds using random leds.

#include <DateTime.h>

const int firstPin = 0; // first pin to use, make this 2 on board using hardware serial) 
const int rowSize = 3;  // number of leds in a row
const int colSize = 12; // total number of columns 

int colPins[colSize];
int rowPins[rowSize];

int freeValues; // stores a bitmask used for random values

// a function to get a value less than or equal to the maximum value that has not already been returned
int  getFreeRandomVal(int maxValue)
{
    int value;
    do
    {
       value = random(maxValue);
    } 
    while(bitRead(freeValues, value) == 0 );
    bitClear(freeValues, value);
    return value;      
}  
  

void showDigit( int digit, int startColumn, int maxValue)
{
  freeValues = 0B111111111; //set all 9 bits
  for( int i=0; i < digit; i++)
  {
      int  pos = getFreeRandomVal(maxValue);
      int row = pos % rowSize ;
      digitalWrite(rowPins[row], HIGH);       
      digitalWrite(colPins[startColumn + (pos / rowSize)], HIGH);   
  }  
}

void setup()
{

  for (int i = 0; i < colSize; i++) // set up column pins
  {
    colPins[i] = i + firstPin;
    pinMode(colPins[i], OUTPUT);
  }
  for (int j = 0; j < rowSize; j++) // set up row pins
  {
    rowPins[j] = (j + colSize);
    pinMode(rowPins[j], OUTPUT);
  }
   DateTime.sync(0);  // start the clock 
}

void loop()
{
  DateTime.available();
  showDigit(DateTime.Hour / 10,0,2);
  showDigit(DateTime.Hour % 10,1,9);  
  showDigit(DateTime.Minute / 10,4,5);
  showDigit(DateTime.Minute % 10,6,9);  
  showDigit(DateTime.Second / 10,9,5);
  showDigit(DateTime.Second % 10,12,9);   
  delay(1000);
}

Here's what Ive come up with, from random code snippets doodled in class:

long previousMillis = 0;
int colPins[9] = {2,3,4,5,6,7,8,9,10};
int rowPins[3] = {11,12,13};
int ht, ho, mt, mo;
int i = 0;
const int delayTime = 100; // in uS
int timeArray[3][9]; // [rows][columns]
int time = 1200;

int interval = 2000; // update speed in mS

void setup() 
{
  Serial.begin(9600);
  for (int i = 0; i < 9; i++) // set up column pins
    pinMode(colPins[i], OUTPUT);
  for (int j = 0; j < 3; j++) // set up row pins
    pinMode(rowPins[j], OUTPUT);
  Serial.println("Enter time, one digit per line,");
  Serial.println("   without colon, to display:");
}

void loop() 
{
  while (i < 4)
  {
    if (Serial.available() > 0)
    {
      if (i == 0)
      {
        ht = Serial.read() - 48;
        Serial.print("Echo: ");
        Serial.println(ht);
      }
      if (i == 1)
      {
        ho = Serial.read() - 48;
        Serial.print("Echo: ");
        Serial.println(ho);
      }
      if (i == 2)
      {
        mt = Serial.read() - 48;
        Serial.print("Echo: ");
        Serial.println(mt);
      }
      if (i == 3)
      {
        mo = Serial.read() - 48;
        Serial.print("Echo: ");
        Serial.println(mo);
        Serial.print("Display this time: ");
        Serial.print(ht);
        Serial.print(ho);
        Serial.print(":");
        Serial.print(mt);
        Serial.print(mo);
      }
      i++;
    }
  }
  /*
ht = 1;
   ho = 3;
   mt = 2;
   mo = 7;
   */
  if (millis() - previousMillis > interval)
  { 
    previousMillis = millis();  
    LoadArrays();
  }
  for (int r = 0; r < 3; r++) // light the led if its corresponding timeArray value is 1
  {      
    digitalWrite(rowPins[r], HIGH);
    for (int c = 0; c < 9; c++)
    {
      if (timeArray[r][c] == 1)
        digitalWrite(colPins[c], HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(colPins[c], LOW);
    }
    digitalWrite(rowPins[r], LOW);
  } 
}


void LoadArrays()
{
  int hourstensarray[3] = {0,0,0};
  int hoursonesarray[9] = {0,0,0,0,0,0,0,0,0};
  int minstensarray[6] = {0,0,0,0,0,0};
  int minsonesarray[9] = {0,0,0,0,0,0,0,0,0};

  // randomly fill tens
  int done = 0;
  while (done < ht)
  {
    int i = random(3);
    if (hourstensarray[i] == 0)
    {
      hourstensarray[i] = 1;
      done++;
    }
  }
  // randomly fill ones
  done = 0;
  while (done < ho)
  { 
    int i = random(9);
    if (hoursonesarray[i] == 0)
    {
      hoursonesarray[i] = 1;
      done++;
    }
  }
  // randomly fill tens
  done = 0;
  while (done < mt)
  { 
    int i = random(6);
    if (minstensarray[i] == 0)
    {
      minstensarray[i] = 1;
      done++;
    }
  }
  // randomly fill ones
  done = 0;
  while (done < mo)
  { 
    int i = random(9);
    if (minsonesarray[i] == 0)
    {
      minsonesarray[i] = 1;
      done++;
    }
  }

  timeArray[0][0] = hourstensarray[2];
  timeArray[0][1] = hoursonesarray[8];
  timeArray[0][2] = hoursonesarray[7];
  timeArray[0][3] = hoursonesarray[6];
  timeArray[0][4] = minstensarray[5];
  timeArray[0][5] = minstensarray[4];
  timeArray[0][6] = minsonesarray[8];
  timeArray[0][7] = minsonesarray[7];
  timeArray[0][8] = minsonesarray[6];
  timeArray[1][0] = hourstensarray[1];
  timeArray[1][1] = hoursonesarray[5];
  timeArray[1][2] = hoursonesarray[4];
  timeArray[1][3] = hoursonesarray[3];
  timeArray[1][4] = minstensarray[3];
  timeArray[1][5] = minstensarray[2];
  timeArray[1][6] = minsonesarray[5];
  timeArray[1][7] = minsonesarray[4];
  timeArray[1][8] = minsonesarray[3];
  timeArray[2][0] = hourstensarray[0];
  timeArray[2][1] = hoursonesarray[2];
  timeArray[2][2] = hoursonesarray[1];
  timeArray[2][3] = hoursonesarray[0];
  timeArray[2][4] = minstensarray[1];
  timeArray[2][5] = minstensarray[0];
  timeArray[2][6] = minsonesarray[2];
  timeArray[2][7] = minsonesarray[1];
  timeArray[2][8] = minsonesarray[0];
}

And here's a video:

Nice. I like it.