A set of fresh eyes

Hey everybody.

I am still working on getting my STP16DP05B1R's to play well with my Arduino. For some background: I developed a little project to run 200 LEDs in a chain from my Arduino using shift registers. Things are going pretty well, and I can chain them together just fine. The LEDs react pretty much the way I want them to (to data coming in from Processing). I am just running into a bizarre problem. It would seem that I can drive 8 LEDs from each register (pins 0-7) but there is no activity on pins 8-15.

I checked the output voltage on each pin, and it looks like pins 0-7 are outputting variating positive voltage, but I am getting variating negative readings from 8-15. Is that normal? Can anybody shine a little light on that one for me?

At this point, I'm sure that I'm just missing something stupid, but I've been staring at this thing for so long that I figure a fresh set of eyes might just do the trick. It's likely quite simple. Please bear in my that I don't really know much about programming, but I am deeply interested in learning -- most of this has been brute force trial and error.

Let's take a look. The comments from the ShiftOut tutorial have been left intact for the most part, for clarity.

int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

//holders for infromation you're going to pass to shifting function
byte data1;
byte data2;
byte data3;
byte data4;
byte data5;
byte data6;
byte data7;
byte data8;
byte data9;
byte data10;
byte data11;
byte data12;
byte dataArray1[16];
byte dataArray2[16];
byte dataArray3[16];
byte dataArray4[16];
byte dataArray5[16];
byte dataArray6[16];
byte dataArray7[16];
byte dataArray8[16];
byte dataArray9[16];
byte dataArray10[16];
byte dataArray11[16];
byte dataArray12[16];

int amp;

void setup() {

  pinMode(latchPin, OUTPUT);
  Serial.begin(9600);

  // chip 1 Array
  //Arduino doesn't seem to have a way to write binary straight into the code 
  //so these values are in HEX.  Decimal would have been fine, too. 

  dataArray1[0] = 0xFFFF; //1111111111111111
  dataArray1[1] = 0xFFFE; //1111111111111110
  dataArray1[2] = 0xFFFC; //1111111111111100
  dataArray1[3] = 0xFFF8; //1111111111111000
  dataArray1[4] = 0xFFF0; //1111111111110000
  dataArray1[5] = 0xFFE0; //1111111111100000
  dataArray1[6] = 0xFFC0; //1111111111000000
  dataArray1[7] = 0xFF80; //1111111110000000
  dataArray1[8] = 0xFF00; //1111111100000000
  dataArray1[9] = 0xFE00; //1111111000000000
  dataArray1[10] = 0xF800; //1111100000000000
  dataArray1[11] = 0xF000; //1111000000000000
  dataArray1[12] = 0xE000; //1110000000000000
  dataArray1[13] = 0xC000; //1100000000000000
  dataArray1[14] = 0x8000; //1000000000000000
  dataArray1[15] = 0x0000; //0000000000000000

    // chip 2 Array
  dataArray2[16] = 0xFFFF; //1111111111111111
  dataArray2[17] = 0xFFFE; //1111111111111110
  dataArray2[18] = 0xFFFC; //1111111111111100
  dataArray2[19] = 0xFFF8; //1111111111111000
  dataArray2[20] = 0xFFF0; //1111111111110000
  dataArray2[21] = 0xFFE0; //1111111111100000
  dataArray2[22] = 0xFFC0; //1111111111000000
  dataArray2[23] = 0xFF80; //1111111110000000
  dataArray2[24] = 0xFF00; //1111111100000000
  dataArray2[25] = 0xFE00; //1111111000000000
  dataArray2[26] = 0xF800; //1111100000000000
  dataArray2[27] = 0xF000; //1111000000000000
  dataArray2[28] = 0xE000; //1110000000000000
  dataArray2[29] = 0xC000; //1100000000000000
  dataArray2[30] = 0x8000; //1000000000000000
  dataArray2[31] = 0x0000; //0000000000000000

// truncated for space
  
}

void loop() {

  if (Serial.available()) { // begin LED drive code
    amp = Serial.read();

    //load the light sequence you want from array

    if (amp <= 15){
      data1 = dataArray1[amp];
      data2 = dataArray2[31];
      data3 = dataArray3[47];
      data4 = dataArray4[63];
      data5 = dataArray5[79];
      data6 = dataArray6[95];
      data7 = dataArray7[111];
      data8 = dataArray8[127];
      data9 = dataArray9[143];
      data10 = dataArray10[159];
      data11 = dataArray11[175];
      data12 = dataArray12[191];

      //ground latchPin and hold low for as long as you are transmitting
      digitalWrite(latchPin, 0);
      //move 'em out
      shiftOut(dataPin, clockPin, data12);
      shiftOut(dataPin, clockPin, data11);
      shiftOut(dataPin, clockPin, data10);
      shiftOut(dataPin, clockPin, data9);
      shiftOut(dataPin, clockPin, data8);
      shiftOut(dataPin, clockPin, data7);
      shiftOut(dataPin, clockPin, data6);
      shiftOut(dataPin, clockPin, data5);
      shiftOut(dataPin, clockPin, data4);
      shiftOut(dataPin, clockPin, data3);
      shiftOut(dataPin, clockPin, data2);   
      shiftOut(dataPin, clockPin, data1);
      //return the latch pin high to signal chip that it 
      //no longer needs to listen for information
      digitalWrite(latchPin, 1);  
    } 
    if (amp >= 16  && amp < 32){ 
      data1 = dataArray1[0];
      data2 = dataArray2[amp];
      data3 = dataArray3[47];
      data4 = dataArray4[63];
      data5 = dataArray5[79];
      data6 = dataArray6[95];
      data7 = dataArray7[111];
      data8 = dataArray8[127];
      data9 = dataArray9[143];
      data10 = dataArray10[159];
      data11 = dataArray11[175];
      data12 = dataArray12[191];

      //ground latchPin and hold low for as long as you are transmitting
      digitalWrite(latchPin, 0);
      //move 'em out
      shiftOut(dataPin, clockPin, data12);
      shiftOut(dataPin, clockPin, data11);
      shiftOut(dataPin, clockPin, data10);
      shiftOut(dataPin, clockPin, data9);
      shiftOut(dataPin, clockPin, data8);
      shiftOut(dataPin, clockPin, data7);
      shiftOut(dataPin, clockPin, data6);
      shiftOut(dataPin, clockPin, data5);
      shiftOut(dataPin, clockPin, data4);
      shiftOut(dataPin, clockPin, data3);
      shiftOut(dataPin, clockPin, data2);   
      shiftOut(dataPin, clockPin, data1);
      //return the latch pin high to signal chip that it 
      //no longer needs to listen for information
      digitalWrite(latchPin, 1);  
    } 
   // truncated for space
  }
}

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  // This shifts 8 bits out MSB first, 
  //on the rising edge of the clock,
  //clock idles low

  //internal function setup
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  //clear
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  //for each bit in the byte myDataOut
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that %00000001 or "1" will go through such
  //that it will be pin Q0 that lights. 
  for (i=15; i>=0; i--)  { // THIS IS SOMETHING TO WATCH
    digitalWrite(myClockPin, 0);
    //if the value passed to myDataOut and a bitmask result 
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000 
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {      
      pinState= 0;
    }
    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  //stop
  digitalWrite(myClockPin, 0);
}

I don't have a handle on arrays yet, but again, this setup works for 8 LEDs per chip for one reason or another.

Thanks everyone. I can link to the datasheet if you think that would be useful.

At the beginning of your sketch you are declaring 12 arrays with a size of 16 elements. Later you index them with value exceeding 15.

For example when you initialize dataArray2 you start your index from 16 instead of 0. For each of your arrays the index should range from 0 to 15 otherwise you memory is corrupted. Remember that C don't control if an array index is out of bound at run time.

I totally get it now, thank you so much.

Ok, actually, that info does clarify a few things conceptually, but the negative voltage problem remains on the chips even after the changes to my code to reflect the above advice (thanks, man!).

I have the feeling there is something lurking in the datasheet that I'm not seeing because I'm not experienced enough. Here's the datasheet for whoever is interested.

http://www.st.com/stonline/products/literature/ds/13093.pdf

Hmm... well, what I have so far is pretty cool :slight_smile:

You're also putting 16-bit values into arrays of "bytes" (which are 8bits):

byte dataArray1[16];
      :
  dataArray1[0] = 0xFFFF; //1111111111111111

The last post is correct, hope I don't break this down too far for ya but in case it helps... you've stumbled upon a couple of the biggest pitfalls in arudino coding for beginners. Trying to reference an index of an array beyond it's boundaries and writing too much data to a byte type both cause all kinds of craziness...

You declared a variable as 'byte', or actually an array, which is just essentially a bunch of variables with the same name of the same type, 'byte'. A byte contains 8 bits, with binary values ranging from 00000000 to 11111111.

When you jam 0xFFFF in there, you're overwriting memory outside the bounds of the 8 bytes you're supposed to be writing to causing untold strangeness in your app which is essentially impossible to debug. You tried to cram 16 bits where only 8 fit.

Try just manually putting 8 bit values into the registers and see how that goes. I'm sure it'll fire right up and then you'll see how you need to change your code to only put 8 bits in a byte instead of writing 16 and essentially causing your app to act unpredictable (what a modern windows PC would consider a program 'crash')

A byte contains 8 bits, with binary values ranging from 00000000 to 11111111.
When you jam 0xFFFF in there, you're overwriting memory outside the bounds of the 8 bytes

Well, no. C compilers don't DO that; they'll just truncate the 0xFFFF to 0xFF instead; there are very clear rules about how to handle assignments between mis-matched types.

(OTOH, C will allow you to put things in an array either before or after the end of the array. This is also carefully defined, though it will seem odd to programmers used to other languages..

byte myarray[2];
myarray[0] = 0xFFFF;  // puts 0xFF in myarray[0]
myarray[10] = 0x12;   // puts 0x12 someplace random

oh, thanks for setting me straight westfw. I suppose it's still unpredictable behavior, but I thought the first case overwrote memory just like going beyond the declared length of the array.

Not that I want to run into this case, but that's good to know! Did this get your straighten out Vamos?

Yep, and indeed I was seeing the effects of what westfw was talking about. Really good to know. All I had to do was change bytes to integers and that worked swell (in addition to changing the range of the array definitions to 16).

The best part is, I know what the hell that means now!!

Thanks all. I have some groovy video which will get posted in the next fews days and I'll pm a link when I get the chance.

It is nice to explain things and have them apparently understood instead of just followed, and it seems to happen relatively frequently within the Arduino community, which I take as a good sign!