SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By cvoss42
#71528
I'm attempting to interface an arduino with the "button pad controller" using spi. I can't seem to get the controller to respond.

Here is my code. If anyone has any ideas what I'm doing wrong, I would much appreciate the help! Thanks!
Code: Select all
#define SCK_PIN 13 // Clock
#define MISO_PIN 12
#define MOSI_PIN 11
#define SS_PIN 10 // Control Signal
 
byte red[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte green[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte blue[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte buttons[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 
//---------------------------------------
// SETUP AND LOOP
//---------------------------------------
 
// Set up Everything
void setup() {
  setupSPI();
}
 
// Loop
void loop() {
  
  digitalWrite(SS_PIN, HIGH);
  for(int i = 0; i < 16; i++)
  {
   transfer(red[i]); 
  }
  for(int i = 0; i < 16; i++)
  {
   transfer(green[i]); 
  }
  for(int i = 0; i < 16; i++)
  {
   transfer(blue[i]); 
  }
  for(int i = 0; i < 16; i++)
  {
   transfer(buttons[i]); 
  }
  digitalWrite(SS_PIN, LOW);
  delayMicroseconds(500);
 
}
 
//---------------------------------------
// SPI DATA
//---------------------------------------
 
void setupSPI()
{ 
 pinMode(SCK_PIN, OUTPUT);
 pinMode(MOSI_PIN, OUTPUT);
 pinMode(MISO_PIN, INPUT);
 pinMode(SS_PIN, OUTPUT);
 
 modeSPI(0);
 }
 
// Set SPI mode
void modeSPI(byte config)
{
  byte tmp;
 
  // enable SPI master with configuration byte specified
  SPCR = 0;
  SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR);
  tmp = SPSR;
  tmp = SPDR;
}
 
// transfer a byte
byte transfer(byte value)
{
 SPDR = value;
while(!(SPSR & (1<<SPIF))) ;
return SPDR;
}
By ryowens84
#71589
Try sending something besides '0' for the color values. It may in fact be working, but if the SPI board receives all 0's it won't turn any of the LED's on. Try '4' or '5' in all of the positions of one color.

I'll try and look into this a little more later, to make sure you're correctly setting up all of your data lines.
By cvoss42
#71664
Figured out the problem: spi clock is too fast on arduino's built in spi. Had to hand-code an spi system to transfer out data.
By frank26080115
#71671
cvoss42 wrote:Figured out the problem: spi clock is too fast on arduino's built in spi. Had to hand-code an spi system to transfer out data.
you can adjust the SPI speed using the SPR bits in SPCR
By ryowens84
#71672
Ah, I hadn't thought of that. If that's the case though, you could also change this line in your modeSPI function:
Code: Select all
SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR); 
to this:
Code: Select all
SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR)|(1<<SPR1);
That last bit setting slows the SPI clock down by dividing it by 16.
By cvoss42
#71674
Sadly, that only gets me down to 250khz and I need it down to 50khz.
By buchacho
#74427
cvoss42, can you post your implementation of SPI?
By j45ch
#79996
ok,
here's my implementation of the handmade bitbanging SPI for the buttonpad
on an arduino, a duemilanove w/ ATMega 168 in my case.

it works.

what doesn't work as advertised are the 256 levels of color.
there are only 9 color-levels per channel!
AND as stated elsewhere the board doesn't support multiple button-presses per row.
If you can live with that, it's a fine board, even if the buttons are bit large.
(i use it as a extension to a real monome 128).

here's the code, just the SPI function, the rest is left as an exercise for the reader.

cheers

/*j
Code: Select all
// maximum SCK frequency of 50 Khz -> minimum 20 usec per clock cycle
void readWriteSPI(void) 
{ 
	int j;
	int state;
	char input = 0;
	char buttonstate = 0;
	int t1 = 20;
	int t2 = 5;
	int t3 = 20;
	int t4 = 400;
	TIMSK0 |= (1 << TOIE0); // reactivate overflow interrupt for timer 1 
    // it's needed by delay(...)
											
	digitalWrite(SPICLOCK, HIGH);			// signal start of transmission
	delayMicroseconds(t1); 					// Chip select to clock start t1
	digitalWrite(SLAVESELECT, HIGH);		// signal start of transmission
	delayMicroseconds(t1); 					// Chip select to clock start t1
	digitalWrite(SPICLOCK, LOW);			 // signal start of transmission
	delayMicroseconds(t2); 					// data setup time t2 / 2
	for(i = 0; i < 64; i++) {
		input = data[i];
		buttonstate = 0; 					// reset button for accumulating
		for(j = 0; j < 8; j++) {
			state = ((input >> j) & 1);
			if(state == 1){
				digitalWrite(DATAIN, HIGH); // now set the bit
			}else if(state == 0){
				digitalWrite(DATAIN, LOW); 	// now set the bit
			}
			delayMicroseconds(t2); 			// data setup time t2
			digitalWrite(SPICLOCK, HIGH);	// activate rising clockedge
			delayMicroseconds(t2); 			// Data latch time t2 -> t3/2			
			state = digitalRead(DATAOUT);	// now read in the button bit
			buttonstate += state;// * (1 << j);	// accumulate to byte
			delayMicroseconds(t2); 			// Data latch time t2 -> t3/2
			digitalWrite(SPICLOCK, LOW);	// end cycle
			delayMicroseconds(t2); 			// data setup time t2 / 2
		}
		if(buttonstate == 8) {
			buttons[i % 16] = 0;
		} else {
			buttons[i % 16] = 1;		
		}
	}
	digitalWrite(SPICLOCK, LOW);				
	delayMicroseconds(t1); 
	digitalWrite(SLAVESELECT, LOW);
	delayMicroseconds(t4); 	        		// mandatory pause before resending data
  
	TIMSK0 &= ~(1 << TOIE0);				// and switch the interrupt off.

}
By Adilson
#109466
Hi folks

I am truly new to Arduino and I am quite sure I am doing something wrong trying to use the tips you are providing here. My code is like this:
Code: Select all
#define SCK_PIN 13 // Clock
#define MISO_PIN 12
#define MOSI_PIN 11
#define SS_PIN 10 // Control Signal

byte matriz[64] = {255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // red
                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // green
                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // blue
                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // botoes
                  
byte buttons[16];

void setup() 
{
  setupSPI();
  Serial.begin(9600); 
}

void loop() 
{
  
  byte i;
  
  readWriteSPI(matriz);
  delay(10);
  for (i=0; i<16; i++)
  {
    Serial.print(buttons[i]);
  }
}

void readWriteSPI(byte data[64])
{
   int j,i;
   int state;
   char input = 0;
   char buttonstate = 0;
   int t1 = 20;
   int t2 = 5;
   int t3 = 20;
   int t4 = 400;
   TIMSK0 |= (1 << TOIE0); // reactivate overflow interrupt for timer 1
    // it's needed by delay(...)
                                 
   digitalWrite(SCK_PIN, HIGH);         // signal start of transmission
   delayMicroseconds(t1);                // Chip select to clock start t1
   digitalWrite(SS_PIN, HIGH);          // signal start of transmission
   delayMicroseconds(t1);                // Chip select to clock start t1
   digitalWrite(SCK_PIN, LOW);          // signal start of transmission
   delayMicroseconds(t2);                // data setup time t2 / 2
   for(i = 0; i < 16; i++) {
      input = data[i];
      buttonstate = 0;                // reset button for accumulating
      for(j = 0; j < 8; j++) {
         state = ((input >> j) & 1);
         if(state == 1){
            digitalWrite(MOSI_PIN, HIGH); // now set the bit
         }else if(state == 0){
            digitalWrite(MOSI_PIN, LOW);    // now set the bit
         }
         delayMicroseconds(t2);          // data setup time t2
         digitalWrite(SCK_PIN, HIGH);   // activate rising clockedge
         delayMicroseconds(t2);          // Data latch time t2 -> t3/2         
         state = digitalRead(MISO_PIN);   // now read in the button bit
         buttonstate += state;// * (1 << j);   // accumulate to byte
         delayMicroseconds(t2);          // Data latch time t2 -> t3/2
         digitalWrite(SCK_PIN, LOW);   // end cycle
         delayMicroseconds(t2);          // data setup time t2 / 2
      }
      if(buttonstate == 8) {
         buttons[i % 16] = 0;
      } else {
         buttons[i % 16] = 1;      
      }
   }
   digitalWrite(SCK_PIN, LOW);            
   delayMicroseconds(t1);
   digitalWrite(SS_PIN, LOW);
   delayMicroseconds(t4);                  // mandatory pause before resending data
   
   TIMSK0 &= ~(1 << TOIE0);            // and switch the interrupt off.

}

void setupSPI()
{
  pinMode(SCK_PIN, OUTPUT);
  pinMode(MOSI_PIN, OUTPUT);
  pinMode(MISO_PIN, INPUT);
  pinMode(SS_PIN, OUTPUT);
}
And I can't get an reaction from this keyboard. Can anyone please tell me what am I doing wrong? TIA
By Adilson
#111756
havard wrote:Hi Adilson,

Did you get your buttonpad to work? Here's my simple example. Only blinks all the LEDs at once, but should demonstrate the timings well.
http://hblok.net/blog/posts/2010/10/17/ ... roller_spi

Now I'm looking for somebody to update the firmware, to have full 24 bit color depth.
Thanks, I'll check it out as soon as I have some time.
I contacted the Sparkfun's support about the Arduino interface but the person who answered said they are overwhelmed and this is not priority but the full 24 bit color may be. Perhaps we should email them for it.
By havard
#111780
Adilson wrote: Thanks, I'll check it out as soon as I have some time.
I contacted the Sparkfun's support about the Arduino interface but the person who answered said they are overwhelmed and this is not priority but the full 24 bit color may be. Perhaps we should email them for it.
I posted the same question in this thread:
viewtopic.php?f=14&t=24252

Have a look at the source code (linked from the product pages) for the firmware for both products (the button pad and the 8x8 RGB matrix). It's interesting how each of them get part of it right, yet leave some aspect of the color depth out, so that it is limited.

For the button pad, I'm wondering if it is enough to adjust the COLOR_DEPTH (currently 7) upwards. Perhaps it could be 63, or even 255. I'd like to put the firmware code under some "unit test" or simulation, to understand it better. Also, I'm hoping to get my hands on an AVR programmer, so I can update the board.

Regards,
Havard