Shift registers and LED's

Ok. Please post your questions as a new thread.
You can start it by looking at TLC5940 and WS2803 for PWM controllers for LEDs.

I have been looking at the SPI code you wrote that I have been using on my matrix to display static characters, and even though I admit I still don't fully understand the intricacies of the cathode and anode switching in this circuit, I understand that all this i.e using SPI for data transmission and the ULN2803 for cathode sinking, is a very fast and efficient way of displaying on LED matrixes. I would still like to display some scolling text and although I think I understand the basic concept the actual implementation has me totally baffled. To be honest in desparation I found some other examples on the internet of how to scroll text using the two shift registers but no SPI and although they worked they were very inefficient taking up large amounts of memory to do relatively basic tasks.

I think that I previously said that if I can look at some code that performs the basic function of what I am after (scrolling text) it is easier for me to modify it's output and thus learn to understand a little more of how it works. Would it be possible for you to show me how to incorporate the following arrays into the code to scroll PEDRO"

B00000000, B00111000, B00100100, B00100100, B00111000, B00100000, B00100000, B00000000 //P

B00000000, B00111100, B00100000, B00111000, B00111000, B00100000, B00111100, B00000000 //E

B00000000, B00111000, B00100100, B00100100, B00100100, B00100100, B00111000, B00000000 //D

B00000000, B00111000, B00100100, B00100100, B00111000, B00101000, B00100100, B00000000 //R

B00000000, B00011000, B00100100, B00100100, B00100100, B00100100, B00011000, B00000000 //O

I hope you do not think that I am lazy ...just very challanged by all this 8)

Thanks again if you can help, Pedro.

byte letterP[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00100000, B00100000, B00000000 }; //P
byte letterE[8] = {B00000000, B00111100, B00100000, B00111000, B00111000, B00100000, B00111100, B00000000 }; //E
byte letterD[8] = {B00000000, B00111000, B00100100, B00100100, B00100100, B00100100, B00111000, B00000000 }; //D
byte letterR[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00101000, B00100100, B00000000 }; //R
byte letterO[8] = {B00000000, B00011000, B00100100, B00100100, B00100100, B00100100, B00011000, B00000000 }; //0

P E
00000000 00000000
00000000 00000000
01111110 01111110
01001000 01011010
01001000 01011010
00110000 01000010
00000000 00000000
00000000 00000000

(These might need rotating 90 degrees counterclockwise)

You have code that does SPI.transfer's with data from displayArray[] every 1mS or something, yes?
So we'll just move data thru that array.

Make a 40 letter storage array:

displayStore[0] = letterP[0];
displayStore[1] = letterP[1];
displayStore[2] = letterP[2];
displayStore[3] = letterP[3];
displayStore[4] = letterP[4];
displayStore[5] = letterP[5];
displayStore[6] = letterP[6];
displayStore[7] = letterP[7];

displayStore[8] = letterE[0];
displayStore[9] = letterE[1];
displayStore[10] = letterE[2];
displayStore[11] = letterE[3];
displayStore[12] = letterE[4];
displayStore[13] = letterE[5];
displayStore[14] = letterE[6];
displayStore[15] = letterE[7];

displayStore[16] = letterD[0];
displayStore[17] = letterD[1];
displayStore[18] = letterD[2];
displayStore[19] = letterD[3];
displayStore[20] = letterD[4];
displayStore[21] = letterD[5];
displayStore[22] = letterD[6];
displayStore[23] = letterD[7];

displayStore[24] = letterR[0];
displayStore[25] = letterR[1];
displayStore[26] = letterR[2];
displayStore[27] = letterR[3];
displayStore[28] = letterR[4];
displayStore[29] = letterR[5];
displayStore[30] = letterR[6];
displayStore[31] = letterR[7];

displayStore[32] = letterO[0];
displayStore[33] = letterO[1];
displayStore[34] = letterO[2];
displayStore[35] = letterO[3];
displayStore[36] = letterO[4];
displayStore[37] = letterO[5];
displayStore[38] = letterO[6];
displayStore[39] = letterO[7];

displayStore[40] = 0;
displayStore[41] = 0;
displayStore[42] = 0;
displayStore[43] = 0;
displayStore[44] = 0;
displayStore[45] = 0;
displayStore[46] = 0;
displayStore[47] = 0;

And now every 1/2 second we'll move data from displayStore into displayArray to be shifted out:

currentStore = millis();
if (currentStore - previousStore >= elapsedStore){
previousStore = previous + elapsedStore;
storePointer = storePointer +1;
  if (storePointer == 41){storePointer = 0;} // reset to start of storage
//loop thru the 8 columns
  for (arrayPointer = 0; arrayPointer <8; arrayPointer = arrayPointer+1){ 
// and update the displayArray
  displayArray[arrayPointer] = storeArray[storePointer +arrayPointer]; // so [0] = storePointer + 0, [1] = sP +1 ...
  }
}
// now on next 1mS interval, the new data will get shifted out

There's better ways to do this, with the letter definitions being stored in program memory and accessed from there, but this gives you the basics of having an array that that gets put into the shift registers, and updating that array from somewhere else:
P E D R O blank...
123456712345671234567123456712345671234567
| | show these 8
| | then 1/2 second later these 8
| | then 1/2 second later these 8
| | and so on every 1/2 second
| | and after these go back to the beginning

I know that to you guys this is all second nature, but please humour me

These arrays are for each letter (P,E,D,R, and O)

byte letterP[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00100000, B00100000, B00000000 }; //P

The displayStore[0] = letterP[0]; to displayStore[8] = letterP[8];
allow that letter "P" to move across the display followed by the E, D, R, AND O.

The "displayStore into displayArray" code basically just tell all this how and when to happen. I rellise that this is possibly the most inept description possible but I am at my limit of understanding here (I do come from convict stock 8) )

To make your work here of use to me how do I incorporate it into the code that I am currently using? Thanks Pedro.

"The "displayStore into displayArray" code basically just tell all this how and when to happen."
Exactly. Its like having a buffer that the world sees, and you are deciding when to change that buffer.

Lets see the code you are currently using.

I am still using the code you initially supplied me with;

  // code to read data from an 8 byte array and display on 8x8 LED matrix with shift registers and current limit resistors driving anodes, 
// and shift register with high current drivers sinking common cathodes.
// SPI commands will be used to send the data out

// sequence: every xx milliseconds, turn off all cathodes
// set up anodes from data stored in an array
// turn on next cathode
// 
// while time is passing for the next set of anodes, do other stuff
// repeat

#include <SPI.h> // bring in SPI library

byte SSanodes = 9; // output latch for anodes shift register.  Can be any pin except 10,11,12,13.
byte SScathodes = 10; // output latch for cathodes shift register.  Pin D10 needs to be an output for SPI.
byte dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // load up some initial data
// dataArray[0] = B00000001
// dataArray[1] = B00000010
// dataArray[2] = B00000100
// dataArray[3] = B00001000
// dataArray[4] = B00010000
// dataArray[5] = B00100000
// dataArray[6] = B01000000
// dataArray[7] = B10000000

byte cathodePins[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // used to turn on 1 cathode at a time

unsigned long timeNow = 0;  // capture time
unsigned long previousTime = 0; // store previous time
unsigned long elapsedTime = 5; // time that each column will be on

byte anodeColumn = 0;  // keep track of column being driven

void setup(){
pinMode (SSanodes, OUTPUT);
pinMode (SScathodes, OUTPUT);

SPI.begin();  // commits 11,12,13 for hardware SPI transfer. Make sure shift registers have 0.1uF/100nF on their VCC pins to ground.
}

void loop(){

timeNow = millis(); // capture the current 'time'
if ((timeNow - previousTime)>= elapsedTime){  // display refresh time?
previousTime = previousTime + elapsedTime; //setup for next pass

// keep track of which column is being written
anodeColumn = anodeColumn+1;
if (anodeColumn == 8){anodeColumn = 0;}  // reset after going 0,1,2,3,4,5,6,7 >> 0

// turn off current cathode
digitalWrite (SScathodes, LOW);
SPI.transfer(0); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

// shift out next set of anodes
digitalWrite (SSanodes, LOW);
SPI.transfer(dataArray[anodeColumn]); // read data from the array and send it out
digitalWrite (SSanodes, HIGH);

// turn the next cathode on
digitalWrite (SScathodes, LOW);
SPI.transfer(cathodePins[anodeColumn]); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

} // end of time check

// make sure that all compiles & runs okay. If too flickery, decrease elapsedTime. Maybe even go to micros() instead of millis();

// next, add your code to read buttons, receive serial data, whatever your method for making updates to dataArray[x]
// for example, this should move the On LED in each row across the screen every 1/2 second
/*  add variable definitions as above
// timeNow already captured at the top of void loop
if ( (timeNow - previousShiftTime)>= elapsedShiftTime){
previousShiftTime = previousShiftTime + elapsedShiftTime;
tempArray = arrayData[0];  // store column 0
arrayData[0] = arrayData[1]; // column 0 becomes column 1
arrayData[1] = arrayData[2]; // 1 becomes 2
arrayData[2] = arrayData[3];
arrayData[3] = arrayData[4];
arrayData[4] = arrayData[5];
arrayData[5] = arrayData[6];
arrayData[6] = arrayData[7];
arrayData[7] = tempArray;  // finally 7 becomes what 0 was.
}
*/
// display will show the new data at the next display update interval

} // end void loop

I did try to incorporate your new code into what you had previously provided me with but due to my limited understanding it was a total flop.

Sorry to drop a note in here but stick with Pedro! I am in the same boat as you! I am waiting on another boat from China for my parts but I will be shadowing what you are doing.

@Crossroads thanks for the detail here it is truly helpful.

Buddy

Okay, you see the big section of comments

// next, add your code to read buttons, receive serial data, whatever your method for making updates to dataArray[x]
// for example, this should move the On LED in each row across the screen every 1/2 second
/*  add variable definitions as above
// timeNow already captured at the top of void loop
if ( (timeNow - previousShiftTime)>= elapsedShiftTime){
:
:
arrayData[6] = arrayData[7];
arrayData[7] = tempArray;  // finally 7 becomes what 0 was.
}
*/
// display will show the new data at the next display update interval

That's where the new stuff to update the array goes.
Take out the /* and */ , that's what starts & stops big sections of comments,
vs putting // on every line.
I don't have one of these wired up myself, so you migh have to adjust it some.

For example, I had to adjust the prior sketch to make the commented section compile.

3 variables had to be declared at the top

unsigned long previousShiftTime = 0;
unsigned long elapsedShiftTime = 500;
byte tempArray = 0;

and the names at the bottom had to be made consistent with the section that does the SPI.transfers

if ( (timeNow - previousShiftTime)>= elapsedShiftTime){
previousShiftTime = previousShiftTime + elapsedShiftTime;
tempArray = dataArray[0];  // store column 0
dataArray[0] = dataArray[1]; // column 0 becomes column 1
dataArray[1] = dataArray[2]; // 1 becomes 2
dataArray[2] = dataArray[3];
dataArray[3] = dataArray[4];
dataArray[4] = dataArray[5];
dataArray[5] = dataArray[6];
dataArray[6] = dataArray[7];
dataArray[7] = tempArray;  // finally 7 becomes what 0 was.
}

I generally do this stuff late at night and am not always consistent.
So for the new stuff I typed up last night, you will have to make the same kind of adjustments.

 // code to read data from an 8 byte array and display on 8x8 LED matrix with shift registers and current limit resistors driving anodes, 
// and shift register with high current drivers sinking common cathodes.
// SPI commands will be used to send the data out

// sequence: every xx milliseconds, turn off all cathodes
// set up anodes from data stored in an array
// turn on next cathode
// 
// while time is passing for the next set of anodes, do other stuff
// repeat

#include <SPI.h> // bring in SPI library

byte SSanodes = 9; // output latch for anodes shift register.  Can be any pin except 10,11,12,13.
byte SScathodes = 10; // output latch for cathodes shift register.  Pin D10 needs to be an output for SPI.
byte dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // load up some initial data
// dataArray[0] = B00000001
// dataArray[1] = B00000010
// dataArray[2] = B00000100
// dataArray[3] = B00001000
// dataArray[4] = B00010000
// dataArray[5] = B00100000
// dataArray[6] = B01000000
// dataArray[7] = B10000000

byte cathodePins[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // used to turn on 1 cathode at a time

unsigned long timeNow = 0;  // capture time
unsigned long previousTime = 0; // store previous time
unsigned long elapsedTime = 5; // time that each column will be on
unsigned long previousShiftTime = 0;
unsigned long elapsedShiftTime = 500;
byte tempArray = 0;

byte anodeColumn = 0;  // keep track of column being driven

void setup(){
pinMode (SSanodes, OUTPUT);
pinMode (SScathodes, OUTPUT);

SPI.begin();  // commits 11,12,13 for hardware SPI transfer. Make sure shift registers have 0.1uF/100nF on their VCC pins to ground.
}

void loop(){

timeNow = millis(); // capture the current 'time'
if ((timeNow - previousTime)>= elapsedTime){  // display refresh time?
previousTime = previousTime + elapsedTime; //setup for next pass

// keep track of which column is being written
anodeColumn = anodeColumn+1;
if (anodeColumn == 8){anodeColumn = 0;}  // reset after going 0,1,2,3,4,5,6,7 >> 0

// turn off current cathode
digitalWrite (SScathodes, LOW);
SPI.transfer(0); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

// shift out next set of anodes
digitalWrite (SSanodes, LOW);
SPI.transfer(dataArray[anodeColumn]); // read data from the array and send it out
digitalWrite (SSanodes, HIGH);

// turn the next cathode on
digitalWrite (SScathodes, LOW);
SPI.transfer(cathodePins[anodeColumn]); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

} // end of time check

// make sure that all compiles & runs okay. If too flickery, decrease elapsedTime. Maybe even go to micros() instead of millis();

// next, add your code to read buttons, receive serial data, whatever your method for making updates to dataArray[x]
// for example, this should move the On LED in each row across the screen every 1/2 second
//  add variable definitions as above
// timeNow already captured at the top of void loop
if ( (timeNow - previousShiftTime)>= elapsedShiftTime){
previousShiftTime = previousShiftTime + elapsedShiftTime;
tempArray = dataArray[0];  // store column 0
dataArray[0] = dataArray[1]; // column 0 becomes column 1
dataArray[1] = dataArray[2]; // 1 becomes 2
dataArray[2] = dataArray[3];
dataArray[3] = dataArray[4];
dataArray[4] = dataArray[5];
dataArray[5] = dataArray[6];
dataArray[6] = dataArray[7];
dataArray[7] = tempArray;  // finally 7 becomes what 0 was.
}

// display will show the new data at the next display update interval

} // end void loop

Now read all the comments, something like this should work

 // code to read data from an 8 byte array and display on 8x8 LED matrix with shift registers and current limit resistors driving anodes, 
// and shift register with high current drivers sinking common cathodes.
// SPI commands will be used to send the data out

// sequence: every xx milliseconds, turn off all cathodes
// set up anodes from data stored in an array
// turn on next cathode
// 
// while time is passing for the next set of anodes, do other stuff
// repeat

#include <SPI.h> // bring in SPI library

byte SSanodes = 9; // output latch for anodes shift register.  Can be any pin except 10,11,12,13.
byte SScathodes = 10; // output latch for cathodes shift register.  Pin D10 needs to be an output for SPI.
byte dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // load up some initial data
// dataArray[0] = B00000001
// dataArray[1] = B00000010
// dataArray[2] = B00000100
// dataArray[3] = B00001000
// dataArray[4] = B00010000
// dataArray[5] = B00100000
// dataArray[6] = B01000000
// dataArray[7] = B10000000

// define some letters
byte letterP[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00100000, B00100000, B00000000 }; //P
byte letterE[8] = {B00000000, B00111100, B00100000, B00111000, B00111000, B00100000, B00111100,  B00000000 };  //E
byte letterD[8] = {B00000000, B00111000, B00100100, B00100100, B00100100, B00100100, B00111000, B00000000 };   //D
byte letterR[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00101000, B00100100, B00000000 };   //R
byte letterO[8] = {B00000000, B00011000, B00100100, B00100100, B00100100, B00100100, B00011000, B00000000 };   //0
// define a big array to hold a message
byte displayStore[48];
// and pointers into array
byte storePointer = 0;
byte arrayPointer = 0;

byte cathodePins[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // used to turn on 1 cathode at a time

unsigned long timeNow = 0;  // capture time
unsigned long previousTime = 0; // store previous time
unsigned long elapsedTime = 5; // time that each column will be on
unsigned long previousShiftTime = 0;
unsigned long elapsedShiftTime = 500;
byte tempArray = 0;

byte anodeColumn = 0;  // keep track of column being driven

void setup(){
//put some data in the array of letters  
displayStore[0] = letterP[0];
displayStore[1] = letterP[1];
displayStore[2] = letterP[2];
displayStore[3] = letterP[3];
displayStore[4] = letterP[4];
displayStore[5] = letterP[5];
displayStore[6] = letterP[6];
displayStore[7] = letterP[7];

displayStore[8] = letterE[0];
displayStore[9] = letterE[1];
displayStore[10] = letterE[2];
displayStore[11] = letterE[3];
displayStore[12] = letterE[4];
displayStore[13] = letterE[5];
displayStore[14] = letterE[6];
displayStore[15] = letterE[7];

displayStore[16] = letterD[0];
displayStore[17] = letterD[1];
displayStore[18] = letterD[2];
displayStore[19] = letterD[3];
displayStore[20] = letterD[4];
displayStore[21] = letterD[5];
displayStore[22] = letterD[6];
displayStore[23] = letterD[7];

displayStore[24] = letterR[0];
displayStore[25] = letterR[1];
displayStore[26] = letterR[2];
displayStore[27] = letterR[3];
displayStore[28] = letterR[4];
displayStore[29] = letterR[5];
displayStore[30] = letterR[6];
displayStore[31] = letterR[7];

displayStore[32] = letterO[0];
displayStore[33] = letterO[1];
displayStore[34] = letterO[2];
displayStore[35] = letterO[3];
displayStore[36] = letterO[4];
displayStore[37] = letterO[5];
displayStore[38] = letterO[6];
displayStore[39] = letterO[7];

displayStore[40] = 0;
displayStore[41] = 0;
displayStore[42] = 0;
displayStore[43] = 0;
displayStore[44] = 0;
displayStore[45] = 0;
displayStore[46] = 0;
displayStore[47] = 0;  
  
pinMode (SSanodes, OUTPUT);
pinMode (SScathodes, OUTPUT);

SPI.begin();  // commits 11,12,13 for hardware SPI transfer. Make sure shift registers have 0.1uF/100nF on their VCC pins to ground.
}

void loop(){

timeNow = millis(); // capture the current 'time'
if ((timeNow - previousTime)>= elapsedTime){  // display refresh time?
previousTime = previousTime + elapsedTime; //setup for next pass

// keep track of which column is being written
anodeColumn = anodeColumn+1;
if (anodeColumn == 8){anodeColumn = 0;}  // reset after going 0,1,2,3,4,5,6,7 >> 0

// turn off current cathode
digitalWrite (SScathodes, LOW);
SPI.transfer(0); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

// shift out next set of anodes
digitalWrite (SSanodes, LOW);
SPI.transfer(dataArray[anodeColumn]); // read data from the array and send it out
digitalWrite (SSanodes, HIGH);

// turn the next cathode on
digitalWrite (SScathodes, LOW);
SPI.transfer(cathodePins[anodeColumn]); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

} // end of time check

// make sure that all compiles & runs okay. If too flickery, decrease elapsedTime. Maybe even go to micros() instead of millis();

// next, add your code to read buttons, receive serial data, whatever your method for making updates to dataArray[x]
// for example, this should move the On LED in each row across the screen every 1/2 second
//  add variable definitions as above
// timeNow already captured at the top of void loop
/*
if ( (timeNow - previousShiftTime)>= elapsedShiftTime){
previousShiftTime = previousShiftTime + elapsedShiftTime;
tempArray = dataArray[0];  // store column 0
dataArray[0] = dataArray[1]; // column 0 becomes column 1
dataArray[1] = dataArray[2]; // 1 becomes 2
dataArray[2] = dataArray[3];
dataArray[3] = dataArray[4];
dataArray[4] = dataArray[5];
dataArray[5] = dataArray[6];
dataArray[6] = dataArray[7];
dataArray[7] = tempArray;  // finally 7 becomes what 0 was.
}*/

if (timeNow - previousShiftTime >= elapsedShiftTime){
previousShiftTime = previousShiftTime + elapsedShiftTime;
storePointer = storePointer +1;
  if (storePointer == 41){storePointer = 0;} // reset to start of storage
//loop thru the 8 columns
  for (arrayPointer = 0; arrayPointer <8; arrayPointer = arrayPointer+1){ 
// and update the displayArray
  dataArray[arrayPointer] = displayStore[storePointer +arrayPointer]; // so [0] = storePointer + 0, [1] = sP +1 ...
  }
}
// now on next 1mS interval, the new data will get shifted out


// display will show the new data at the next display update interval

} // end void loop

Thanks so much for all this help Crossroads. Unfortunately for me it's off to work I go as it's Monday morning "down under" but as soon as I get home I will try out your new code and see how it goes, but I have complete confidence in your coding prowess

Thanks again Pedro (soon to be scrolling Pedro) 8)

At some point you're going to have to dig in & try it yourself Pedro.

Buddy, how's your coding? Are you able to help out here?

Crossroads,

I am sincerely grateful for all the help you have given me with this, and as I have previously said you are very generous with your time on this forum and I have no doubt that you do not have a great deal of spare time in your day . You are right I will have to dig in for myself and I have been trying to work my way through some simpler projects to try and develop some "coding prowess " of my own but it seems that I haven't been trying hard enough, or possibly this project is so far above what I can achieve that I am dreaming. That being said I will still try out the additions to the code that you have given me lately and hope that I can get it up and running. So once again a heart-felt sincere thank you Crossroads, from me and all on this forum ,

Pedro 8)

@Crossroads

Until I get all my parts I will be trailing behind you guys. My coding is getting MUCH better in here but until I can practice with my own components I will have to remain on the sidelines.

I do think it is wildly cool that I found Pedro's project here as it is an almost mirror image to my own plan.

I did have a question but I will wait until I have my parts and I will start a thread as I don't want to create a rabbit trail.

The one VERY COOL concept I got validated in this thread was the Binary notation of the character patterns. I had to laugh. I will be dating myself here but I used to write Assembler code way back in the day. In fact, I used to dream in Assembler. So using these Shift Registers is pretty great to me.

Later!

Buddy

Hi Buddy,

I think that I have about picked poor Crossroads mind to pieces with my unending requests for help on this project of mine. As you may have gathered from reading this thread, I know very little about Arduino, electronics and especially coding. But... if I can be of any help at all to you with this please feel free to ask, Pedro :slight_smile:

Just to clarify Crossroads I am not after any more advice but I thought that I would let you know that the latest code you generously did for me worked a treat. As you summised I did have to modify the arrays because as they were it was scrolling top to bottom and the P and R were upside down but after applying my "interlectual prowess" 8) I turned the display on it's side and rearranged the arrays so it's all good now. Thanks again and good luck with your projects Pedro.

Cool! Can you post a little clip of of working?
And to think that all my conjecturing actually worked as expected. Usually takes me a few tries with the actual hardware to get it to work.

No problem Crossroads.When I get home this afternoon I will will do a short video of "our matrix" 8) I know how to upload a video to my Utube channel but how do I post a video to to his forum (other than posting a link to Youtube or whatever) I see that some people post a " thumbnail" showing a Utube player screen that you can just click play on rather than going through links to other sites etc. In the meantime as this is the only thing I have available right now here is a link to the 3 x 3 x3 cube that you recently helped me with;

Pedro.

Cool I didn't realise that just posting a link on this page would bring up this player screen :slight_smile: Well that answers that question, and enjoy a bit of Jeff Beck and Cubemation, Pedro.

Neat!