[Solved]Shiftout from Array not working

Hi there,

I am trying to shift out 16 bits of data to a MAX7219 that drives an 8by8 led array. If I do it with shiftOut function (two * 8bits), it works just fine, but whenever I try to do it this way, it just doesn't work. Seemingly everything works fine but whenever I upload it to the arduino or press the reset button, the MAX7219 either doesn't react at all or it does something completely random, but most of the time nothing happens...

Thanks in advance!

Code snippet for easier understanding:

int din = 4;
int cs = 3;
int clk = 2;

int displaytest [16] =    {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0};

void setup() {
  pinMode(din, OUTPUT);
  pinMode(cs, OUTPUT);
  pinMode(clk, OUTPUT);

  Serial.begin(9600);
  starting();
  digitalWrite(cs, LOW);
  digitalWrite(clk, LOW);

  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, displaytest[i]);
    Serial.println(displaytest[i]);
    clockit();
    sendit();
    }
}

void loop() {

}

int clockit(){
digitalWrite(clk, HIGH);
digitalWrite(clk, LOW);
}

int sendit(){
digitalWrite(cs, LOW);
digitalWrite(cs, HIGH);
digitalWrite(cs, LOW);
}

int starting(){
Serial.println("starting...");
}

Full code for those who are interested...:

int din = 4;
int cs = 3;
int clk = 2;

int scanlimit [16] =      {0,0,0,0,1,0,1,1,0,0,0,0,0,1,1,1};
int decodeMode [16] =     {0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0};
int shutdownas [16] =     {0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1};
int displaytest [16] =    {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0};
int setintensity [16] =   {0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,1};
int line1 [16] =          {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1};
int line2 [16] =          {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0};
int line3 [16] =          {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0};
int line4 [16] =          {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
int line5 [16] =          {0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0};
int line6 [16] =          {0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0};
int line7 [16] =          {0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0};
int line8 [16] =          {0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0};

void setup() {
  pinMode(din, OUTPUT);
  pinMode(cs, OUTPUT);
  pinMode(clk, OUTPUT);

  Serial.begin(9600);
  starting();
  digitalWrite(cs, LOW);
  digitalWrite(clk, LOW);

  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, scanlimit[i]);
    clockit();
    sendit();
    Serial.println(scanlimit[i]);
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, decodeMode[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, shutdownas[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, displaytest[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, setintensity[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line1[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line2[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line3[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line4[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line5[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line6[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line7[i]);
    clockit();
    sendit();
    }
  for(int i = 0 ; i <= 15 ; i++){
    digitalWrite(din, line8[i]);
    clockit();
    sendit();
    }
}

void loop() {

}

int clockit(){
digitalWrite(clk, HIGH);
digitalWrite(clk, LOW);
}

int sendit(){
digitalWrite(cs, LOW);
digitalWrite(cs, HIGH);
digitalWrite(cs, LOW);
}

int starting(){
Serial.println("starting...");
}
int scanlimit [16] =      {0,0,0,0,1,0,1,1,0,0,0,0,0,1,1,1};
int decodeMode [16] =     {0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0};
int shutdownas [16] =     {0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1};
int displaytest [16] =    {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0};
int setintensity [16] =   {0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,1};
int line1 [16] =          {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1};
int line2 [16] =          {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0};
int line3 [16] =          {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0};
int line4 [16] =          {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
int line5 [16] =          {0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0};
int line6 [16] =          {0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0};
int line7 [16] =          {0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0};
int line8 [16] =          {0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0};

The first question is why are you using 416 bytes to store 26 bytes of data?

The obvious second question is why are you resisting using shiftOut()?

int sendit(){
digitalWrite(cs, LOW);
digitalWrite(cs, HIGH);
digitalWrite(cs, LOW);
}

You lied. You said this function (and several others) would return an int. But they don't.

PaulS:

int scanlimit [16] =      {0,0,0,0,1,0,1,1,0,0,0,0,0,1,1,1};

int decodeMode [16] =    {0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0};
int shutdownas [16] =    {0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1};
int displaytest [16] =    {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0};
int setintensity [16] =  {0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,1};
int line1 [16] =          {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1};
int line2 [16] =          {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0};
int line3 [16] =          {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0};
int line4 [16] =          {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
int line5 [16] =          {0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0};
int line6 [16] =          {0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0};
int line7 [16] =          {0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0};
int line8 [16] =          {0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0};



The first question is why are you using 416 bytes to store 26 bytes of data?

The obvious second question is why are you resisting using shiftOut()?



int sendit(){
digitalWrite(cs, LOW);
digitalWrite(cs, HIGH);
digitalWrite(cs, LOW);
}



You lied. You said this function (and several others) would return an int. But they don't.

As you can probably tell I am not an expert at programming, it's only a hobby, hence the functions that should return integers...

I want to store my code like this because it is easier to understand than 0x0F...

But besides that the shiftOut function does the following, according to wiring_shift.c in Arduino\hardware\arduino\avr\cores\arduino:

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
	uint8_t i;

	for (i = 0; i < 8; i++)  {
		if (bitOrder == LSBFIRST)
			digitalWrite(dataPin, !!(val & (1 << i)));
		else	
			digitalWrite(dataPin, !!(val & (1 << (7 - i))));
			
		digitalWrite(clockPin, HIGH);
		digitalWrite(clockPin, LOW);		
	}
}

so basically the same as mine and my question is why my version doesn't work...?

I want to store my code like this because it is easier to understand than 0x0F...

Perhaps you want to piss away even more memory, then, and use long. Or long long.

Or, who knows, maybe byte, and waste only half as much memory.

But besides that the shiftOut function does the following:

It writes a bit, and toggles the clock pin once, for each bit to be sent. Your code toggles the cs pin and the clock pin, for every bit to be sent. Why the difference?

You don't HAVE to use hexadecimal notation. You could use binary notation when defining the values.

At least to be, 0b10101010 is just as obvious as 1,0,1,0,1,0,1,0.

I want to store my code like this because it is easier to understand than 0x0F...

int scanlimit [16] = {0,0,0,0,1,0,1,1, 0,0,0,0,0,1,1,1};

You could use:

const byte scanlimit [] = {0b00001011, 0b00000111};

PaulS:
Perhaps you want to piss away even more memory, then, and use long. Or long long.

Or, who knows, maybe byte, and waste only half as much memory.
It writes a bit, and toggles the clock pin once, for each bit to be sent. Your code toggles the cs pin and the clock pin, for every bit to be sent. Why the difference?

You don't HAVE to use hexadecimal notation. You could use binary notation when defining the values.

At least to be, 0b10101010 is just as obvious as 1,0,1,0,1,0,1,0.

Thank you very much sendit(); should be outside of the loop, omg how did I not notice that, Thank you very much!!!

larryd:
int scanlimit [16] = {0,0,0,0,1,0,1,1, 0,0,0,0,0,1,1,1};

You could use:

const byte scanlimit [] = {0b00001011, 0b00000111};

PaulS:
Perhaps you want to piss away even more memory, then, and use long. Or long long.

Or, who knows, maybe byte, and waste only half as much memory.
It writes a bit, and toggles the clock pin once, for each bit to be sent. Your code toggles the cs pin and the clock pin, for every bit to be sent. Why the difference?

You don't HAVE to use hexadecimal notation. You could use binary notation when defining the values.

At least to be, 0b10101010 is just as obvious as 1,0,1,0,1,0,1,0.

So I could store 0x01 as 0b00000001 if I understand that correctly, thank you for pointing this out, I didn't know that before...! Thank you both very much!

Wow, you are doing it the hard way.
I'd recommend using SPI.transfer

digitalWrite (ssPin, LOW);
SPI.transfer (registerAddress);
SPI.transfer (dataToSend);
digitalWrite (ssPin, HIGH);

MAX7219 works great with the default 4 MHz SPI clock, Mode 0, and MSBfirst, so you don't even need to address those.
Use pin 10 for ssPin with a '328P.

Make it a function if you want.
Register address will be 0x00 and 0x09 to 0x0F. You would generally call 5 of them in setup() to get the MAX7219 ready.
Then registers 0x01 to 0x08 to send the array data.
dataToSend will be one of the values needed for the control registers,
or the value to be displayed for a digit or for the column of the 8x8 array..

CrossRoads:
Wow, you are doing it the hard way.
I'd recommend using SPI.transfer

digitalWrite (ssPin, LOW);

SPI.transfer (registerAddress);
SPI.transfer (dataToSend);
digitalWrite (ssPin, HIGH);




MAX7219 works great with the default 4 MHz SPI clock, Mode 0, and MSBfirst, so you don't even need to address those.
Use pin 10 for ssPin with a '328P.

Make it a function if you want.
Register address will be 0x00 and 0x09 to 0x0F. You would generally call 5 of them in setup() to get the MAX7219 ready.
Then registers 0x01 to 0x08 to send the array data.
dataToSend will be one of the values needed for the control registers,
or the value to be displayed for a digit or for the column of the 8x8 array..

Thank you for your suggestion, I like doing it this way because I know exactly what my code does, I am always trying to avoid pre-written code if at all possible... Also I think I learn more this way, as I already told PaulS I am not an expert, I am a soon to be college student in either electronic engineering or mechatronics, but as of right now I am on my own to figure out stuff like this... :slight_smile: But still appreciate your suggestion, also my code works now that I moved "sendit();" out of the for loop, It was trying to tell the MAX7219 to write the shifted in bits into ram after each bit that has been sent, which is silly, I guess I was too tired yesterday to notice my mistake...

So I could store 0x01 as 0b00000001 if I understand that correctly,

0x01, 0b00000001 and come to that 1 are all stored in exactly the same way, as 8 bits in a byte. It would be more correct to say that you can choose how those 8 bits are represented in the program