Tuesday, May 28, 2013

Silent Radio LED sign, removing the three Green LED arrays

I decided to saw off the three Green LED arrays.  To my surprise, I lost three columns of the red Arrays as well as clock and data.  To get the clock and data going again I had to tap into the first 4015 clock and data in.  To fix the three missing columns I had to tap into the first three outputs of the first 4015 and route them through inverters and resistors to the first three columns.  You can see those mods in the picture below.

Then I also added 82 ohm resistors across the 100 ohm resistors to get a little more brightness.  They can be seen in this picture.

Wednesday, May 15, 2013

16 by 40 Dual Color LED Sign being sold on eBay Part 2

I have finally made the sign work! It takes a slight trick in the code to send the serial bit to the 4015's for the rows.  It is " if (row= =0) digitalWrite(OutEnable, LOW);" in the code.

Here is what it looked like when it first came to life.  I was sending the code for making a smiley face.


This is what it looks like with an Arduino running the code that is listed below.

This is what it looks like connected to an Arduino Pins 1-6, and a 5 volt 2.5 amp AC adapter.  For the schematic and pin connections see my older post on this sign.


Here is the code to make it work;
//********************************************//
//  Name    : LED 24x40 array Driver    
//  Author  : Bob Davis                           
//  Date    : 12 May, 2013                   
//  Version : 1.0                                
//********************************************//
// Pins for the clocks and data
int TCLK = 1;
int TSerial = 5;
int BCLK = 6;
int BSerial = 3;
int Strobe = 4;
int OutEnable = 2;

// arrays to say Arduino
byte Tbitmap[][8] = {  //red characters
  {0,  4, 10, 17, 17, 31, 17, 17}, //A
  {0, 0,0,0,0,0,0,0},
  {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
};
byte Bbitmap[][8] = {  //green characters
  {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
};
// Set the pins to output to the array
void setup() {
  pinMode(TCLK, OUTPUT);
  pinMode(TSerial, OUTPUT);
  pinMode(BCLK, OUTPUT);
  pinMode(BSerial, OUTPUT);
  pinMode(Strobe, OUTPUT);
  pinMode(OutEnable, OUTPUT);
}
void loop() {
  for (int row = 0; row < 8; row++){   //there are actually 16 rows
    for (int character = 7; character >=0; character--){
      for (int shiftbit = 0; shiftbit < 6; shiftbit++){
      digitalWrite(TSerial, HIGH); 
      digitalWrite(BSerial, HIGH);
      if bitRead(Tbitmap[character][row],shiftbit) digitalWrite(TSerial, LOW); 
      if bitRead(Bbitmap[character][row],shiftbit) digitalWrite(BSerial, LOW); 
      digitalWrite(TCLK, HIGH); 
      digitalWrite(TCLK, LOW);
      digitalWrite(BCLK, HIGH); 
      digitalWrite(BCLK, LOW);
      }   }
    digitalWrite(OutEnable, HIGH);  // turns off display
    if (row==0) digitalWrite(OutEnable, LOW);  // turns on display
    //latch the data
    digitalWrite(Strobe, LOW);  
    digitalWrite(Strobe, HIGH);
    digitalWrite(OutEnable, LOW);  // turns on display
    delay(.5);   
}  }  

Thursday, May 9, 2013

Dual Color Scrolling LED sign using Cadaces modules and Arduino.

A lot of people have requested that I write a dual color scrolling program for the Cadaces modules.  Well I have done that!  I have also reversed the scrolling by turning the sign over.  Turn the sign over so that the Arduino now connects on the left side.  This also uses the new quick and easy connection pinout.

Here is a link to the video on YouTube:
http://youtu.be/znCA6V8arLw

Here is the code (If blogger will let me upload it).

//**************************************************************//
//  Name    : Cadaces dual color Scrolling                      //
//  Author  : Bob Davis                                         //
//  Date    : 2 May, 2013                                      //
//  Version : 1.0                                               //
//  Based on work of Hari Wiguna - http://g33k.blogspot.com/    //
//****************************************************************
// Pins for the row and data drivers
int row1Pin = 2;
int row2Pin = 7;
int row3Pin = 1;
int rowEnable = 8;
int rclockPin = 6;
int clockPin = 3;
int dataPin = 5;
int gdataPin = 4;   

// 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);
  pinMode(gdataPin, 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.
byte gbitmap[8][10]; // Change the 10 to however many matrices you want to use.
int numZones = sizeof(bitmap) / 8; 
//int numZones = sizeof(gbitmap) / 8; 
// I will refer to each group of 8 columns (represented by one matrix) 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 we've setup 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--) {
     for (int shiftbit = 7; shiftbit > -1; shiftbit--){
      digitalWrite(gdataPin, LOW);
      digitalWrite(dataPin, LOW);
      if bitRead(gbitmap[row][zone],shiftbit) digitalWrite(gdataPin, HIGH); 
      if bitRead(bitmap[row][zone],shiftbit) digitalWrite(dataPin, HIGH); 
      digitalWrite(clockPin, HIGH); 
      digitalWrite(clockPin, LOW);
     } 
    }       
    digitalWrite(rclockPin, LOW); 
    digitalWrite(rclockPin, HIGH);
    //-- turn the current row on NOTE - INVERTED high=on --
    digitalWrite(row1Pin, HIGH);  
    digitalWrite(row2Pin, HIGH);  
    digitalWrite(row3Pin, HIGH);  
    if bitRead(row,0) digitalWrite (row1Pin, LOW);  
    if bitRead(row,1) digitalWrite (row2Pin, LOW);  
    if bitRead(row,2) digitalWrite (row3Pin, LOW);
    digitalWrite(rowEnable, LOW);
    
    //-- Wait a little bit to let humans see what we've pushed out onto the matrix ;
    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);
}
void GPlot(int col, int row, bool isOn)
{
  int zone = col / 8;
  int colBitIndex = col % 8;
  byte colBit = 1 << colBitIndex;
  if (isOn)gbitmap[row][zone] = gbitmap[row][zone] | colBit;
  else gbitmap[row][zone] = gbitmap[row][zone] & (~colBit);
}

// Plot each character of the message one column at a time, updated the display, shift bitmap left.
void AlphabetSoup()
{
//load in the characters
  char msg[] = "AR U NO LED SIGN ";  
  char gmsg[] = "A D I O LED SIGN ";
  for (int charIndex=0; charIndex < (sizeof(msg)-1); charIndex++)
  {
    int alphabetIndex = msg[charIndex] - '@';
    int galphabetIndex = gmsg[charIndex] - '@';
    if (alphabetIndex < 0) alphabetIndex = 0;
    if (galphabetIndex < 0) galphabetIndex = 0;
    //-- Draw one character of the message --
    for (int col = 0; col < 6; 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); 
        isOn = 0;
        if (col<5) isOn = bitRead( alphabets[galphabetIndex][col], 7-row ) == 1;
        GPlot( 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
          gbitmap[row][zone] = gbitmap[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));
          if (zone < maxZoneIndex) bitWrite(gbitmap[row][zone], 7, bitRead(gbitmap[row][zone+1], 0));
        }
      }
    }
  }
} 
//=== L O O P ===
void loop() {
  AlphabetSoup();
} 

Silent Radio LED sign to Arduino Continued



I am playing with the Silent Radio LED sign once again.  There are two problems to fix, the brightness and the scrolling. 

Working on the brightness problem, I know that the 4017 design did not work well because there was no way to turn off the sign while updating the shift registers.  As a result I went back to having the Arduino directly drive the TIP120 drivers.  Another possible solution might be to use an ULN2003’s as a level shifter.  That would require a 6 or 7 volt power supply as well.  I wanted to stay with a 5 volt power supply.  I have observed that the Cadaces modules use 22 ohm current limiting resistors.  The Silent Radio signs use 100 ohm resistors.  Maybe changing the resistors is a better solution?  Here is the schematic.
 This is what it looks like, the Arduino is underneath the circuit board.

On the scrolling issue, I have suspects that the sign scrolls backwards because it is upside down.  So I changed two lines of code so the sigh would work upside down and viola, it works.  It now scrolls from right to left like it should have been doing.

Here is the code to make it work.

//**************************************************************//
//  Name    : Silent Radio Driver                               //
//  Author  : Bob Davis                                         //
//  Date    : 25 April, 2011                                    //
//  Version : 1.0                                               //
//  Based on work of Hari Wiguna - http://g33k.blogspot.com/    //
//****************************************************************
// Pins for the row drivers
int row1Pin = 1;
int row2Pin = 2;
int row3Pin = 3;
int row4Pin = 4;
int row5Pin = 5;
int row6Pin = 6;
int row7Pin = 7;

// Pins for column shift registers
int clockPin = 8;
int dataPin = 9;

// 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(row4Pin, OUTPUT);
  pinMode(row5Pin, OUTPUT);
  pinMode(row6Pin, OUTPUT);
  pinMode(row7Pin, OUTPUT);
}

//=== B I T M A P ===
//Bits in this array represents one LED of the matrix
// 8 is # of rows, 7 is # of LED matrix we have
byte bitmap[8][12]; // Change the 7 to however many matrices you want to use.
int numZones = sizeof(bitmap) / 8; 
// I will refer to each group of 8 columns (represented by one matrix) 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 lower 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 we've setup in the bitmap array and display it on the matrix
void RefreshDisplay()
{
  for (int row = 0; row < 8; row++) {
    //-- turn off the display --
    digitalWrite(row1Pin, LOW);  
    digitalWrite(row2Pin, LOW);  
    digitalWrite(row3Pin, LOW);  
    digitalWrite(row4Pin, LOW);  
    digitalWrite(row5Pin, LOW);  
    digitalWrite(row6Pin, LOW);  
    digitalWrite(row7Pin, LOW); 
    //-- 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]);
    }

    //-- turn the current row on --
    if (row == 1) digitalWrite (row7Pin, HIGH);  
    if (row == 2) digitalWrite (row6Pin, HIGH);  
    if (row == 3) digitalWrite (row5Pin, HIGH);  
    if (row == 4) digitalWrite (row4Pin, HIGH);  
    if (row == 5) digitalWrite (row3Pin, HIGH);  
    if (row == 6) digitalWrite (row2Pin, HIGH);  
    if (row == 7) digitalWrite (row1Pin, HIGH);  

    //-- Wait a little bit to let humans see what we've pushed out onto the matrix --
    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 one column at a time, updated the display, shift bitmap left.
void AlphabetSoup()
{
  char msg[] = "ARDUINO LED SIGN ";
  for (int charIndex=0; charIndex < (sizeof(msg)-1); 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 = 0; col < 6; 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++)
      {
//        for (int zone=numZones; zone > 0; zone--)
        for (int zone=0; zone < numZones; zone++)
        {
          // This right shift would show a left scroll on display.
          bitmap[row][zone] = bitmap[row][zone] >> 1;
          
          // 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();
}