16bit register STP16CP05 driving problems

Hi,

I have been building an alphanumeric 1 digit display out a 16 segments led drive: STP16CP05.
The 16 segments display (42x55cm) is made out of fairy light segments hooked up to 16 relays driven by the STP16CP05.

Here is the code I use:

int sdiPin = 2;
int clkPin = 5;
int lePin = 4;
int oePin = 3;

//int glyph = 0;

byte alpha[26][16] = { 
{0,1,0,1,0,0,0,0,1,0,1,1,1,1,1,0},
{1,1,0,1,0,0,0,0,0,1,0,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1},
{1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0},
{1,1,0,1,0,0,0,0,0,0,1,1,1,1,0,1},
{0,1,0,1,0,0,0,0,1,0,0,0,1,1,1,0},
{1,0,0,0,0,0,1,0,0,1,1,1,0,0,0,1},
{0,0,0,0,0,0,1,0,0,1,1,1,0,1,0,1},
{0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0},
{1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1},
{0,0,0,1,0,1,0,1,1,0,0,0,1,1,0,0},
{0,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0},
{1,0,0,1,0,0,0,0,1,0,1,1,1,1,0,1},
{0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,0},
{1,0,0,1,1,0,0,0,1,0,1,1,1,1,0,1},
{0,1,0,0,1,0,0,0,1,0,1,1,1,1,1,0},
{1,1,0,1,0,0,0,0,0,0,1,1,1,0,1,1},
{0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0},
{1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,1},
{0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0},
{0,0,1,1,1,0,0,0,1,0,0,0,1,1,0,0},
{0,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0},
{1,0,1,0,0,1,0,0,0,0,1,1,0,0,0,1} };
//-----------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(":setup:");
  
  pinMode(sdiPin, OUTPUT);
  pinMode(clkPin, OUTPUT);
  pinMode(lePin, OUTPUT);
  pinMode(oePin, OUTPUT); 
    
  digitalWrite(sdiPin, LOW);
  digitalWrite(clkPin, LOW);
  digitalWrite(lePin, LOW);
  digitalWrite(oePin, HIGH);   
}
//-----------------------------------------
void loop()
{  
  delay(1000);
  int i;
  int glyph = 16;
  
  Serial.println("-sdi-");
  //for(i = 0; i < 16; i++)
  while(i < 16)
  {  
        delay(100); // pause inbetween data       
    digitalWrite(sdiPin, alpha[glyph][i]); // data out - SDI
        Serial.print(alpha[glyph][i],BIN);
        delayMicroseconds(8); // Tsetup_D 
    digitalWrite(clkPin, HIGH);        
        delayMicroseconds(13); // Twclk + Thold ---> 10+3
    digitalWrite(clkPin, LOW); 
    i++;    
  }   
  Serial.println(" ");
  //--  
  delay(5); // Tsetup_L
  //--
  digitalWrite(lePin, HIGH);
      Serial.println("-le-");
      delayMicroseconds(10); // Twlat
  digitalWrite(lePin, LOW);
  //--
  delayMicroseconds(500); // Tsetup_3
  //--
      Serial.println("-oe-");
  digitalWrite(oePin, LOW);
      delay(2000); // display time
  digitalWrite(oePin, HIGH);
  //--
  /*
  glyph++;
  if ( glyph > 26 ) { glyph = 0; }
  */
}

The STP16CP05 datasheet can be found here:
stm.com/stonline/products/literature/ds/12568/stp16cp05.pdf

Basically the problem I have is that it take a couple cycles for the system to actually settle and display the right glyph instead of lighting up random segments.

I have been checking and re-checking my code and the different timing to send the 16bits of data to the chip and can’t find where the glitch is.
If anybody got any idea what could cause the problem or any experience with similar chip, I would really appreciate.

Thanks!

Where do you initialise "i"?

You can't assume that "int i;" will set any initial value, unless preceeded by the modifier "static".

Shouldn't you be resetting it to zero somewhere?

Why is the "for (i = 0..." loop commented out?

BTW, 416 bytes of table is a bit wasteful for only 52 bytes worth of data.

sorry, the for loop should not have been commented (was messing around late last night)… so it is actually like:

for(i = 0; i < 16; i++)
  {  
        delay(100); // pause inbetween data       
    digitalWrite(sdiPin, alpha[glyph][i]); // data out - SDI
        Serial.print(alpha[glyph][i],BIN);
        delayMicroseconds(8); // Tsetup_D 
    digitalWrite(clkPin, HIGH);        
        delayMicroseconds(13); // Twclk + Thold ---> 10+3
    digitalWrite(clkPin, LOW);
  }

But even with this code, it still doesn’t behave like it should… the it displays the right glyph only every now and then… and I can’t understand why…

Regarding the waste of memory, I am aware of this… I previously used word data for each glyph and a tweak shiftout() function to send the 16bits… but this was not working properly either, so I went back to a more straight forward version to try and debug it…

BTW, the relay I am using are these:
http://www.datasheetcatalog.org/datasheets2/51/510918_1.pdf

When the relays are not active, the current goes through 180R 3W resistors.

In any case, I still have no luck in making this work… all data (in my opinion) are sent in the right order with correct timings…
Could the shift register hold partial data of the previously sent sequence?
Could the arduino output not reach the 0 or 1 logic levels properly?
It just seem odd to me that it works fine 1 in about 10 times…

thanks

OK, does the trace data make sense? Is it consistent? If it isn't consistent, does it become consistent if you disconnect the external circuits? Do you need back EMF protection on the relays? Is the relay power supply up to the job?

Your delays are in microseconds, but the timings in the datasheet are in nanoseconds; 1000 times faster - is there a MINIMUM clock speed issue here?

all the data traced via the serial make sense and are consistent even with the external circuit disconnected.

Not sure what you mean by "EMF protection".. (haven't done proper electronic in a while....)

All is powered by a wall mount AC/DC supply set to 9V. Everything seems to be working fine and the relays can hold the position for ever.

However, it seem that if I don't use the oe pin of the ST chip, keeping it to low all the time, the system does settle after about 4 or 5 cycles. But if the oe pin is used, the system goes funny all the time and only displays the right glyph every now and then...... weird?

I didn't think the delays being in µs would matter. I just tried speeding it up 100 or 1000 times but this does not solve anything. But I don't really mind at which speed the system work...

cheers.

I just tried speeding it up 100 or 1000 times

You can’t speed it up any more without removing the “delayMicroseconds” calls completely.

According to the datasheet, when LE is high, so should CLK. Yours is low, since it was taken low with the last of the 16 bits.

It is starting to work better, thanks for your help.

The best way I managed to get it to work better is with the following code:

int sdiPin = 2;
int clkPin = 5;
int lePin = 4;
int oePin = 3;

int glyph = 0;

byte alpha[26][16] = { 
{0,1,0,1,0,0,0,0,1,0,1,1,1,1,1,0},
{1,1,0,1,0,0,0,0,0,1,0,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1},
{1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0},
{1,1,0,1,0,0,0,0,0,0,1,1,1,1,0,1},
{0,1,0,1,0,0,0,0,1,0,0,0,1,1,1,0},
{1,0,0,0,0,0,1,0,0,1,1,1,0,0,0,1},
{0,0,0,0,0,0,1,0,0,1,1,1,0,1,0,1},
{0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0},
{1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1},
{0,0,0,1,0,1,0,1,1,0,0,0,1,1,0,0},
{0,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0},
{1,0,0,1,0,0,0,0,1,0,1,1,1,1,0,1},
{0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,0},
{1,0,0,1,1,0,0,0,1,0,1,1,1,1,0,1},
{0,1,0,0,1,0,0,0,1,0,1,1,1,1,1,0},
{1,1,0,1,0,0,0,0,0,0,1,1,1,0,1,1},
{0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0},
{1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,1},
{0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0},
{0,0,1,1,1,0,0,0,1,0,0,0,1,1,0,0},
{0,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0},
{1,0,1,0,0,1,0,0,0,0,1,1,0,0,0,1} };
//-----------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(":setup:");
  
  pinMode(sdiPin, OUTPUT);
  pinMode(clkPin, OUTPUT);
  pinMode(lePin, OUTPUT);
  pinMode(oePin, OUTPUT); 
    
  digitalWrite(sdiPin, LOW);
  digitalWrite(clkPin, LOW);
  digitalWrite(lePin, LOW);
  //digitalWrite(oePin, HIGH);   
  digitalWrite(oePin, LOW);   
}
//-----------------------------------------
void loop()
{  
  //int glyph = 1;
  delay(100);
  
  Serial.println("-sdi-");
  Serial.print(glyph,DEC);
  Serial.print(": ");  
  
  for(int i = 0; i < 16; i++)
  {     
    digitalWrite(sdiPin, alpha[glyph][i]); // data out - SDI
        Serial.print(alpha[glyph][i],BIN);
        delayMicroseconds(8); // Tsetup_D 
    digitalWrite(clkPin, HIGH);        
        delayMicroseconds(13); // Twclk + Thold ---> 10+3
    if ( i != 15)
      digitalWrite(clkPin, LOW);
  }   
  Serial.println(" ");
  //--  
  delay(5); // Tsetup_L
  //--
  digitalWrite(lePin, HIGH);
      Serial.println("-le-");      
      delayMicroseconds(10); // Twlat      
  digitalWrite(lePin, LOW);  
  //--
  delayMicroseconds(500); // Tsetup_3  
  //--
  digitalWrite(clkPin, LOW);
  
      Serial.println("-oe-");
  //digitalWrite(oePin, LOW);
      delay(2000); // display time
  //digitalWrite(oePin, HIGH);
  //--  
  glyph++;
  if ( glyph >= 26 ) { glyph = 0; }  
}

Like you advise, I avoid putting CLK back to 0 at the last of the 16bits (putting it back to 1 before LE didn’t seems to work properly).

So, it all goes through the 26 characters and display “most” of them correctly. I am still having random characters to display random segments sequence or not at all. When only displaying 1 character, I also still have sometimes random sequences before settling on the proper character.

Also, using OE still seems to mess things up…

I don’t understand why you’ve left CLK high; it is usually the edge that is important, not the state.

How about this:

for(int i = 0; i < 16; i++)
  {
    digitalWrite(sdiPin, alpha[glyph][i]); // data out - SDI
        Serial.print(alpha[glyph][i],BIN);
        delayMicroseconds(8); // Tsetup_D
    digitalWrite(clkPin, HIGH);
        delayMicroseconds(13); // Twclk + Thold ---> 10+3
    digitalWrite(clkPin, LOW);
  }
  Serial.println(" ");
  //--
  delay(5); // Tsetup_L
  //--
  digitalWrite(lePin, HIGH);
    digitalWrite(clkPin, HIGH);
      Serial.println("-le-");
      delayMicroseconds(10); // Twlat
  digitalWrite(lePin, LOW);
  digitalWrite(clkPin, LOW);
  //--
  delayMicroseconds(500); // Tsetup_3
  //--
  digitalWrite(clkPin, LOW);
...etc

Thanks for your code, just tried it but no luck, this does not solve my problem and no glyph at all are showing properly.
I even tried to set LE and CLK to 1 at the same time using port manipulation on PORTD, but this doesn’t work either.

I know it does not make sense to keep CLK to 1 and agree it shouldn’t have to be.
However, I don’t think that CLK needs to be to 1 when LE is, because the datasheet itself differs between fig.8 (p10) and fig.10 (p12).

I am basically running out of ideas here…

Could there be noise on the CLK or SDI causing the chip to mis-read the data?

Could the datasheet be wrong (doubt it)?
Doe anybody have any experience with this STP16CP05 chip?

Could the relay not be given enough intensity causing them to be unstable (I am using a 200R resistor for the intensity regulation) and the relays are powered by the 5V. But this would not explain why sometimes everything lights up instead of just a couple segments…

I suppose I would need an oscilloscope to find out exactly what is going on with each component…