Wednesday, February 27, 2013

Dual Color Cadaces modules to Arduino

I have obtained several dual color Cadaces modules. I will be selling them on eBay soon. Here is a sign in red:
Here it is again this time in green. The green is not as bright as the red.
Here it is with both colors alternating.  They do not work correctly because the Arduino serial out does not support sending both the red and green data using the same clock.  What happens is the right most part of the previous color is dragged through the background.
Here is a picture of the working sign.  It was taken with my phone camera so the quality is lacking.  I wrote my own version of the serial output to support different data for red and green to get it to work.


Here is a better picture of the working sign.

Here is an updated schematic with the addition of "GSD" or Green Serial Data.


Here is the dual color code, note that I replaced serialout with my own code to do the same job:


//****************************************************//
//  Name    : Color Cadaces Driver                          //
//  Author  : Bob Davis                               //
//  Date    : 23 February, 2013                       //
//  Version : 1.0                                     //
//****************************************************//
// Pins for the row drivers
int row1Pin = 1;
int row2Pin = 2;
int row3Pin = 3;
int rowEnable = 4;
int rclockPin = 5;
int clockPin = 6;
int dataPin = 7;
int gdataPin = 8;
// Set the pins to output to the sign
void setup() {
  pinMode(row1Pin, OUTPUT);
  pinMode(row2Pin, OUTPUT);
  pinMode(row3Pin, OUTPUT);
  pinMode(rowEnable, OUTPUT);
  pinMode(rclockPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(gdataPin, OUTPUT);
}

//=== Character Array ===
// Characters are A, B, C, etc.  Only upper case, no symbols. 
byte alphabets[][8] = {
  {0, 04, 10, 17, 17, 31, 17, 17}, //A
  {0, 30, 17, 17, 30, 17, 17, 30}, //B
  {0, 14, 17, 16, 16, 16, 17, 14}, //C
  {0, 28, 18, 17, 17, 17, 18, 28}, //D
  {0, 31, 16, 16, 31, 16, 16, 31}, //E
  {0, 31, 16, 16, 31, 16, 16, 16}, //F
  {0, 14, 17, 16, 16, 19, 17, 14}, //G
  {0, 17, 17, 17, 31, 17, 17, 17}, //H
  {0, 14, 04, 04, 04, 04, 04, 14}, //I
  {0, 07, 02, 02, 02, 02, 10, 14}, //J
  {0, 17, 18, 20, 24, 20, 18, 17}, //K
  {0, 16, 16, 16, 16, 16, 16, 31}, //L
  {0, 10, 21, 21, 21, 17, 17, 17}, //M
  {0, 17, 25, 25, 21, 19, 19, 17}, //N
  {0, 14, 17, 17, 17, 17, 17, 14}, //O
  {0, 30, 17, 17, 30, 16, 16, 16}, //P
  {0, 14, 17, 17, 17, 17, 19, 15}, //Q
  {0, 30, 17, 17, 30, 20, 18, 17}, //R
  {0, 14, 17, 16, 14, 01, 17, 14}, //S
  {0, 31, 04, 04, 04, 04, 04, 04}, //T
  {0, 17, 17, 17, 17, 17, 17, 14}, //U
  {0, 17, 17, 17, 10, 10, 10, 04}, //V
  {0, 17, 17, 17, 21, 21, 21, 10}, //W
  {0, 17, 17, 10, 04, 10, 17, 17}, //X
  {0, 17, 10, 10, 04, 04, 04, 04}, //Y
  {0, 31, 8, 04, 02, 04, 8, 31}, //Z
  {0, 0, 21, 14, 31, 14, 21, 0}, //*
};
byte bitmap[][8] = {  //red characters
  {0, 0,0,0,0,0,0,0},
  {0,  4, 10, 17, 17, 31, 17, 17}, //A
  {0, 30, 17, 17, 30, 20, 18, 17}, //R
  {0, 28, 18, 17, 17, 17, 18, 28}, //D
  {0, 0,0,0,0,0,0,0},
  {0, 14, 04, 04, 04, 04, 04, 14}, //I
  {0, 17, 25, 25, 21, 19, 19, 17}, //N
  {0, 14, 17, 17, 17, 17, 17, 14}, //O
  {0, 0,0,0,0,0,0,0},
  {0, 14, 17, 16, 14, 01, 17, 14}, //S
  {0, 0,0,0,0,0,0,0},
  {0, 14, 17, 16, 16, 19, 17, 14}, //G
  {0, 17, 25, 25, 21, 19, 19, 17}, //N
  {0, 0,0,0,0,0,0,0},
};
byte gbitmap[][8] = {  //green characters
  {0, 0,0,0,0,0,0,0},
  {0,  4, 10, 17, 17, 31, 17, 17}, //A
  {0, 30, 17, 17, 30, 20, 18, 17}, //R
  {0, 0,0,0,0,0,0,0},
  {0, 17, 17, 17, 17, 17, 17, 14}, //U
  {0, 14, 04, 04, 04, 04, 04, 14}, //I
  {0, 0,0,0,0,0,0,0},
  {0, 14, 17, 17, 17, 17, 17, 14}, //O
  {0, 0,0,0,0,0,0,0},
  {0, 14, 17, 16, 14, 01, 17, 14}, //S
  {0, 14, 04, 04, 04, 04, 04, 14}, //I
  {0, 0,0,0,0,0,0,0},
  {0, 17, 25, 25, 21, 19, 19, 17}, //N
  {0, 0,0,0,0,0,0,0},
};
void RunSign()
{
  for (int row = 7; row > 0; row--)
  {
    // turn off display
    digitalWrite(rowEnable, HIGH);
    digitalWrite(rclockPin, LOW);
    // send serial data to display 14 = number of characters
    for (int character = 0; character < 14; character++)
    {
      for (int shiftbit = 5; shiftbit > -1; shiftbit--){
    if bitRead(gbitmap[character][row],shiftbit) digitalWrite(gdataPin, HIGH); else digitalWrite(gdataPin, LOW);
    if bitRead(bitmap[character][row],shiftbit) digitalWrite(dataPin, HIGH); else digitalWrite(dataPin, LOW);
    digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW);
      }
    }
    //latch the data
    digitalWrite(rclockPin, HIGH);
    // set up 74138 row sesection and turn display back on
    if bitRead(row,0) digitalWrite (row1Pin, HIGH); else digitalWrite(row1Pin, LOW); 
    if bitRead(row,1) digitalWrite (row2Pin, HIGH); else digitalWrite(row2Pin, LOW);
    if bitRead(row,2) digitalWrite (row3Pin, HIGH); else digitalWrite(row3Pin, LOW);
    digitalWrite(rowEnable, LOW);
    // Wait to see what we sent to the display ;
    delayMicroseconds(500);
  }


//=== L O O P ===
void loop() {
  RunSign();
}

Wednesday, February 20, 2013

Signature Electronic LED Sign to Arduino part 4

*** BREAKING NEWS!!! ***  The next batch of Cadaces modules are RED and GREEN in color.  This will require an updated adapter and updated software.  More to come as soon as I get it working!

Here are some additional pictures of the Arduino to Cadaces adapter.  Hopefully these are clear enough so you can make your own.  The two unused pins are for optional green LED's.


Several people have asked for a scrolling version of the software for the Cadaces modules to work with an Arduino processor.  So here it is:


//**************************************************************//
//  Name    : Scrolling Driver                                 //
//  Author  : Bob Davis                                         //
//  Date    : 2 January, 2013                                    //
//  Version : 1.0                                               //
//  Based on work of Hari Wiguna - http://g33k.blogspot.com/    //
//**************************************************************
// Pins for the row drivers, shift registers
int row1Pin = 1;
int row2Pin = 2;
int row3Pin = 3;
int rowEnable = 4;
int rclockPin = 5;
int clockPin = 6;
int dataPin = 7;

// Set the pins to output to the circuit
void setup() {
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(row1Pin, OUTPUT);
  pinMode(row2Pin, OUTPUT);
  pinMode(row3Pin, OUTPUT);
  pinMode(rowEnable, OUTPUT);
  pinMode(rclockPin, OUTPUT);
}

//=== B I T M A P ===
// Bits in this array represents one LED of the matrix
// 8 is number of rows, 10 is number of LED matrixes we have
byte bitmap[8][10]; 
// Change the 10 to however many matrices you want to use.
int numZones = sizeof(bitmap) / 8; 
// I will refer to each group of 8 columns as a Zone.
int maxZoneIndex = numZones-1;
int numCols = numZones * 8;

//=== F O N T ===
// Font courtesy of aspro648
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1203747843/22
// First char is @, next is A, B, etc.  Only upper case, no symbols.  
// The @ will display as space character.
byte alphabets[][5] = {
  {0,0,0,0,0},
  {31, 36, 68, 36, 31},
  {127, 73, 73, 73, 54},
  {62, 65, 65, 65, 34},
  {127, 65, 65, 34, 28},
  {127, 73, 73, 65, 65},
  {127, 72, 72, 72, 64},
  {62, 65, 65, 69, 38},
  {127, 8, 8, 8, 127},
  {0, 65, 127, 65, 0},
  {2, 1, 1, 1, 126},
  {127, 8, 20, 34, 65},
  {127, 1, 1, 1, 1},
  {127, 32, 16, 32, 127},
  {127, 32, 16, 8, 127},
  {62, 65, 65, 65, 62},
  {127, 72, 72, 72, 48},
  {62, 65, 69, 66, 61},
  {127, 72, 76, 74, 49},
  {50, 73, 73, 73, 38},
  {64, 64, 127, 64, 64},
  {126, 1, 1, 1, 126},
  {124, 2, 1, 2, 124},
  {126, 1, 6, 1, 126},
  {99, 20, 8, 20, 99},
  {96, 16, 15, 16, 96},
  {67, 69, 73, 81, 97},
};

//=== F U N C T I O N S ===
// This routine takes whatever is in the bitmap array and display it on the matrix
void RefreshDisplay()
{
  for (int row = 0; row < 8; row++) {
    //-- turn off the display --
    digitalWrite(rowEnable, HIGH); 
    //-- Shift out to each matrix (zone is 8 columns represented by one matrix)
    for (int zone = maxZoneIndex; zone >= 0; zone--) {
      shiftOut(dataPin, clockPin, MSBFIRST, bitmap[row][zone]);
    }
    digitalWrite(rclockPin, LOW); digitalWrite(rclockPin, HIGH);
    //-- turn the current row on --
    if bitRead(row,0) digitalWrite (row1Pin, HIGH); else digitalWrite(row1Pin, LOW);  
    if bitRead(row,1) digitalWrite (row2Pin, HIGH); else digitalWrite(row2Pin, LOW); 
    if bitRead(row,2) digitalWrite (row3Pin, HIGH); else digitalWrite(row3Pin, LOW);
    digitalWrite(rowEnable, LOW);
    //-- Wait a little bit to let humans see
    delayMicroseconds(500);
  }
}

// Converts row and colum to actual bitmap bit and turn it off/on
void Plot(int col, int row, bool isOn)
{
  int zone = col / 8;
  int colBitIndex = col % 8;
  byte colBit = 1 << colBitIndex;
  if (isOn)
    bitmap[row][zone] =  bitmap[row][zone] | colBit;
  else
    bitmap[row][zone] =  bitmap[row][zone] & (~colBit);
}

// Plot each character of the message, updated the display, shift bitmap left.
void AlphabetSoup()
{
  char msg[] = "ARDUINO LED SIGN";
//load in the characters
  for (int charIndex=(sizeof(msg)-1); charIndex >= 0 ; charIndex--)
  {
    int alphabetIndex = msg[charIndex] - '@';
    if (alphabetIndex < 0) alphabetIndex = 0;
    //-- Draw one character of the message --
    // Each character is only 5 columns wide
    for (int col = 5; col >= 0; col--)
    {
      for (int row = 0; row < 8; row++)
      {
        // Set the pixel to the alphabet for columns 0 thru 4
        bool isOn = 0;
        if (col<5) isOn = bitRead( alphabets[alphabetIndex][col], 7-row ) == 1;
        Plot( numCols-1, row, isOn); 
      }
      //-- The more times you repeat this loop, the slower we would scroll --
      for (int refreshCount=0; refreshCount < 50; refreshCount++)
        RefreshDisplay();
      //-- Shift the bitmap one column to left --
      for (int row=0; row<8; row++) //right shift
      {
        for (int zone=0; zone < numZones; zone++)
        {
          // This right shift would show a left scroll on display.
          bitmap[row][zone] = bitmap[row][zone] >> 1;  //right shift
          // Roll over lowest bit from the next zone as highest bit of this zone.
          if (zone < maxZoneIndex) bitWrite(bitmap[row][zone],7,bitRead(bitmap[row][zone+1], 0));
        }
      }
    }
  }
} 
//=== L O O P ===
void loop() {
  AlphabetSoup();
} 





Thursday, February 7, 2013

Going back to school at 56.

0n November 1 of 2012 I went to work as usual.  There was a strange announcement made for me to come to the main office area.  I hesitated for a second thinking to myself “Is this it?”  The request was so unusual that I could not help but think that I was about ready to be fired.  When I arrived I was escorted to the break area and it was totally empty. Then the new lady form HR showed up and she was very nervous.  By now I was sure that I knew what was about ready to happen.  I did what I had already done twice that day for two other people, I started reassuring her that everything was going to be alright, and there was no real problem.  Besides I was expecting this and I was ready to go.

I had worked there for 3 and ½ years.  There were currently about 35 employees and only 6 of them had been there longer than I had.  One of them was the boss’s wife.  It was the kind of place where you either move up to a better job elsewhere or you will get fired.  The president of the company regularly spied on everyone, reading their emails etc.  I even found a “keyboard logger” installed on my computer several times over the years.  I knew that you really had to “watch your back”. 

The same day that I lost my job I went looking for a new job and tried to apply for unemployment by visiting the “UI” (Unemployment Insurance) office.  I found out that you have to apply for unemployment on the Internet.  There are many pages of information that you have to fill out to apply.  I was turned down for unemployment three times.  The first time was because I was laid off on a Thursday.  Because I had “worked” 4 days that week I did not qualify for unemployment and I had to start the entire process all over again.  The next time I was denied benefits was because I was fired for “reasons other than lack of work”.  This time all I had to do was to appeal the decision and show that I was fired for no real reason at all.  Finally after a month of trying I was able to get unemployment.

Once on unemployment I was summoned to the unemployment office for counseling.  When I visited the unemployment office they said that there were several options available for me to pursue.  One of those options was to go back to school.  There was an underused $8000 grant available to go back to school.  This option even included an extension in the unemployment benefits.  The catch was that you had to take engineering classes to study for a degree in an engineering field.  Since I did not have a degree this sounded like a good option.  I did have 7 years of college level education, but none of the places where I had studied at offered a degree back when I went there.

I was told that I could take these classes at the local community college that was only about three blocks from my house.  I needed to sign up quickly as it was mid December.  There were three more problems I had to overcome.  One was that the actual engineering classes were at the main branch of the community college, over an hour drive away.  The next problem was that I had to take a test to get back into college, and the third problem was that it was now January; I would be starting in the second semester without taking the first semester classes that were a prerequisite.

I took the “Compass” test to test my ability in English and math.  It is taken on a computer.  The program seems to know how well you are doing and give you questions to find just where your abilities fall.  When I got to the math I knew I was in trouble. It only gave me a few math questions then it ended the test!  My test scores were 96 for reading, 95 for writing and 31 for math….  So I went to the library and read some books on calculus and retook the test a couple of weeks later.  This time I got a 75 in math so I would be able to start with college math and would not have to retake high school math all over.

The next problem was to get into the classes mid-term.  I had to contact the professor to talk with him to get permission to join the class, but he and almost everyone else was gone on Christmas vacation.  I tried calling and emailing the professor but did not get a response.  Someone finally gave me a form and told me to go to the first class a little early and talk with the professor there.  I did get an email response just hours before attending the class.  The professor thought I could handle it but by the time the class was over I was not very sure I could handle it!

The third problem was that the engineering classes were in Batavia, an hour drive away.  However the class scheduling was such that I could just go there on Monday and Wednesday and could attend two classes while I was there. 

It has now been almost a month and after the initial overload I am doing OK.  I am taking only 12 credits this semester and I would recommend anyone near my age should start with the minimum number of classes until they get used to college life.  Things have changed a lot since I was last taking college classes.