Having trouble using SPI and USB Serial port in same code

Hardware used:
Arduino Mega 2560, PS2 controller, Open Bench Logic Analyzer, laptop

Project Goal:
I am working on a project where I am polling data from a PS2 controller and trying to send the data collected back to a PC so it can be viewed on the serial monitor.

Problem:
The controller uses an SPI bus for its communication protocol. I started out just getting the SPI part working. Using a logic analyzer to spy on the data being passed back and forth, I have determined that I can successfully send a command to the controller and have it send back valid data over the SPI bus. Great!

The next step was to take the data that had been collected, organize it and send it over the Serial port (That is the USB / Serial port). This is where I ran into trouble. So the order of operations is Send a series of commands over SPI, analyze the data, send the data over the USB serial connection, repeat.

What I notice is this. With just the SPI code and data processing code present I am able to communicate just fine with the PS2 controller. Here is the working code below:

// This program attempts to poll data from a PS2 controller using SPI protocol, break that data up into useful chunks and send the chunks over the USB/Serial connection so the values
//can be viewed on the serial monitor
//17Apr12

#include <SPI.h>

void setup(){
  
  //Clock high when idle, data read on clock transition from hi to lo
  SPI.setDataMode(SPI_MODE3);
  //Clock to 500khz
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setBitOrder(LSBFIRST);
  SPI.begin();
  
  //Setup SS pins
  pinMode(SS, OUTPUT);
  digitalWrite(SS,HIGH);
  
  //Setup Serial to relay data back to Serial Monitor
  Serial.begin(9600);
}

void loop(){
    //Variable to hold data from controller
    int confirm = 0; int dataHi = 0; int dataLo = 0; int data =0; int goodData = 0; int garbage = 0;
  
  //Send 0x01, 0x42, 0x00 (18 times) This is a PS2 command to poll the controller
  
   digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x01);  //Should return 0x00
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     data = SPI.transfer(0x42);     //Return varies depending on mode the controller is in
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     confirm = SPI.transfer(0x00);   //Should return 0x5D
     //Serial.println(confirm);
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x00);    //Used to control motor in controller
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x00);    //Used to control motor in controller
   digitalWrite(SS,HIGH);
   
   for(int x = 0; x < 16; x++){       //Controller may spit back up to 16 more bytes, this is here as a dumb way to make sure all the bytes are clocked through
    digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x00);
    digitalWrite(SS,HIGH);
  }
  
  
     dataHi = (data & 0xF0) >> 4;    //Get high Nibble
     dataLo = data & 0xF;   //Get low nibble
     
     //Serial.print("data = "); Serial.print(data); Serial.println(" ");
     //Serial.print("dataHi = "); Serial.print(dataHi); Serial.println(" ");
     //Serial.print("dataLo = "); Serial.print(dataLo); Serial.println(" ");
    
      //Was this a valid read? Was the 3rd byte back 0x5D?
      if(confirm == 0x5D) {
      
        goodData = 1;
        //Serial.print("Did it read 0x5D? "); Serial.println(goodData); Serial.println(" ");
      
      }//end if
      
}//end loop

The next step is to uncomment the Serial.print commands so I can send that data back to the PC. Here it is:

// This program attempts to poll data from a PS2 controller using SPI protocol, break that data up into useful chunks and send the chunks over the USB/Serial connection so the values
//can be viewed on the serial monitor
//17Apr12

#include <SPI.h>

void setup(){
  
  //Clock high when idle, data read on clock transition from hi to lo
  SPI.setDataMode(SPI_MODE3);
  //Clock to 500khz
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setBitOrder(LSBFIRST);
  SPI.begin();
  
  //Setup SS pins
  pinMode(SS, OUTPUT);
  digitalWrite(SS,HIGH);
  
  //Setup Serial to relay data back to Serial Monitor
  Serial.begin(9600);
}

void loop(){
    //Variable to hold data from controller
    int confirm = 0; int dataHi = 0; int dataLo = 0; int data =0; int goodData = 0; int garbage = 0;
  
  //Send 0x01, 0x42, 0x00 (18 times) This is a PS2 command to poll the controller
  
   digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x01);  //Should return 0x00
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     data = SPI.transfer(0x42);     //Return varies depending on mode the controller is in
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     confirm = SPI.transfer(0x00);   //Should return 0x5D
     //Serial.println(confirm);
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x00);    //Used to control motor in controller
   digitalWrite(SS,HIGH);
   
   digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x00);    //Used to control motor in controller
   digitalWrite(SS,HIGH);
   
   for(int x = 0; x < 16; x++){       //Controller may spit back up to 16 more bytes, this is here as a dumb way to make sure all the bytes are clocked through
    digitalWrite(SS,LOW);
     garbage = SPI.transfer(0x00);
    digitalWrite(SS,HIGH);
  }
  
  
     dataHi = (data & 0xF0) >> 4;    //Get high Nibble
     dataLo = data & 0xF;   //Get low nibble
     
     Serial.print("data = "); Serial.print(data); Serial.println(" ");
     Serial.print("dataHi = "); Serial.print(dataHi); Serial.println(" ");
     Serial.print("dataLo = "); Serial.print(dataLo); Serial.println(" ");
    
      //Was this a valid read? Was the 3rd byte back 0x5D?
      if(confirm == 0x5D) {
      
        goodData = 1;
        Serial.print("Did it read 0x5D? "); Serial.println(goodData); Serial.println(" ");
      
      }//end if
      
}//end loop

When I run this second piece of code, I notice that my SPI bus stops working correctly. I seem to get no responses from the PS2 controller. I checked this with the logic analyzer and in the code (the if statement toward the end). However, the serial data is being sent over the USB port and I can read it on my serial monitor, but no SPI data is being received from the controller.

Any ideas on why this might be happening?

Thanks!

Just as a tip, you don't need the "garbage" variable. Just do this:

     SPI.transfer(0x00);    //Used to control motor in controller

Which version of the IDE are you using?

Nick, thanks for the tip. I wasn't sure if I needed to clear the data that way, but it's good to know I don't need to.

I am using version 1.0 of the IDE.

Well the serial prints use interrupts, and that might be throwing the timing out.

Do you need to bring SS low all the time? Do you have a link to the device?

I do need to bring SS low between each send. The device I’m using is a PlayStation 2 controller. I followed this tutorial for wiring the controller up and to learn the communication protocol:

So if the serial.prints are messing with the timing, perhaps I need to insert a delay after them. I’ll have to try that tonight.