Easy Transfer Virtual Wire + Dagu Wild Thumper Motor Controller + Rugged Audio

I’m currently using a PS2 controller and arduino with a cheap RF tx along with the Easy Transfer Virtual Wire library to send integers such as stick positions and stuff to an RF rx connected to a Dagu Wild Thumper Motor controller (basically Arduino Nano Atmega 168). Everything seems to work great.

However, I also want sound out of my robot so I purchased a Rugged Audio Shield (http://ruggedcircuits.com/html/rugged_audio_shield.html) that I figured I could send signals or interrupts to with the processing power of the motor controller. So far I can get the motor controller functionality to work with the PS2 controller coming in wirelessly with the Easy Transfer Virtual Wire method, and I can get the Rugged Audio Shield to play audio files if I load the motor shield specifically for that, but I can’t get them to both work.

The Rugged Audio Shield uses the SPI library and I am using the ICSP pins on the motor controller board to interface with the shield since some of the default digital pins for SPI are hardwired to h bridges. Does the ET library interfere with this functionality somehow? I don’t know if there is some kind of serial issue occurring or what. The Rugged Audio Shield has an SD card, but all of the processing is done with an onboard atmega, I figure I just have to send library commands from an arduino to tell it to play files. I left out some of the battery check stuff in the code, but this is where I am stuck. It will currently loop the audio file over and over but will not take inputs from the controller anymore. Any ideas? Thanks a lot

#include "IOpins.h"

#include "Constants.h"
#include <VirtualWire.h>
#include <EasyTransferVirtualWire.h>
#include <SPI.h>
#include <RAS.h> // Rugged Audio Shield library

RAS RAS;



//create object
EasyTransferVirtualWire ET; 
struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  //Struct can't be bigger then 26 bytes for VirtualWire version
  
  //int blinks;
  //int pause;
  int left_stick_x;
  int left_stick_y;
  int right_stick_x;
  int right_stick_y;
};

//give a name to the group of data
SEND_DATA_STRUCTURE mydata;
//

void setup(void)

  ET.begin(details(mydata));
  
  // Initialise the IO and ISR
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000);	 // Bits per sec

  vw_rx_start();       // Start the receiver PLL running
  
  randomSeed(analogRead(0));
// 
  
  //Serial.begin(9600);
  //Serial.println("RC Mode Initialized");
  
   pinMode(SSpin, OUTPUT);
   RAS.begin();
   //Serial.begin(38400);
   RAS.InitSD();
   delay(100);
   RAS.OutputEnable();
   //Serial.println("RAS Initialized");
  
  
  
}


void loop()
{
  //------------------------------------------------------------ Check battery voltage and current draw of motors ---------------------


  delay(1000);

  // Don't bother trying to play a WAV file if we don't even have an SD card!
  RAS.ReadInfo();
  if (RAS.IsSDCardInserted()) {
    for(i;i<3;i++){
    // We have an SD card inserted. Try to play a WAV file.
    RAS.PlayWAV("snowblwr.WAV");
    }
    // Wait for the file to stop playing by checking the state and waiting for it to be Idle
    do {
      delay(100);
      if (RAS.GetState() == STATE_IDLE) break;
    } while (1);

    // Was playing the file successful? or did we have an error?
    {
      uint16_t error = RAS.GetLastError();

      //if (error) {
      //  Serial.println(RAS.InterpretError(error));
      //} else {
      //  Serial.println("Played snowblwr.WAV");
      //}
    }
  }

void RCmode()
{
//  //------------------------------------------------------------ Code for RC inputs ---------------------------------------------------------
//
  if(ET.receiveData()){

  Leftmode=2;
  Rightmode=2;

    if (106 < mydata.left_stick_y < 150)  LeftPWM=0;
    if (106 < mydata.right_stick_y < 150)  RightPWM=0;
    //Forward
    if (150 < mydata.left_stick_y) 
    {
     Leftmode=2;
     LeftPWM=(mydata.left_stick_y-128)*2;
    }
    if (150 < mydata.right_stick_y)
    {
     Rightmode=2;
     RightPWM=(mydata.right_stick_y-128)*2;
    }
    
    //Reverse
    if (106 > mydata.left_stick_y)
    {
     Leftmode=0;
     LeftPWM=(255-mydata.left_stick_y*2);
    }  
    if (106 > mydata.right_stick_y)
    {
     Rightmode=0;
     RightPWM=(255-mydata.right_stick_y*2); 
    }
  }
}

Is this really needed ?

while (1);

the do/while loop prevents it from restarting the play while its already playing

yea looking at this in a different format has helped. I pasted that example in there from the RAS site to play the file, but its essentially stuck in that do loop.

I was able to get it work by simplifiying it a bit

RAS RAS;

//create object
EasyTransferVirtualWire ET; 
struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  //Struct can't be bigger then 26 bytes for VirtualWire version
  
  //int blinks;
  //int pause;
  int left_stick_x;
  int left_stick_y;
  int right_stick_x;
  int right_stick_y;
};

//give a name to the group of data
SEND_DATA_STRUCTURE mydata;
//

void setup()
{

 ET.begin(details(mydata));
  
  // Initialise the IO and ISR
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000);   // Bits per sec

  vw_rx_start();       // Start the receiver PLL running
  
  randomSeed(analogRead(0));

  

   pinMode(SSpin, OUTPUT);
   RAS.begin();
   RAS.InitSD();
   delay(100);
  
  
}


void loop()
{
  //------------------------------------------------------------ Check battery voltage and current draw of motors ---------------------

   
   if (i==500)
   {
    RAS.OutputEnable();
    delay(5000);
    RAS.PlayWAV("snowblwr.WAV");
   }
}

if (i==500)

How is this possible, when you have nothing updating i ?

oh sorry I added an i=i++. Also tried a couple other inputs to make sure I could trigger it. One thing I tried was to make it so if the stick level was above a threshold to trigger the play. This resulted in the throttle working, but the audio did not play until I let go of the throttle…it was likely trying to start itself over and over again, so in a situation like this I will likely still need a method of checking if the play has completed, most likely with an if statement instead of a loop. Thanks for the help

edit: yup this works great. Won’t play if wav is already playing

if (RightPWM > 120)
{
if (RAS.GetState() == STATE_IDLE)
{
RAS.OutputEnable();
delay(100);
RAS.PlayWAV(“snowblwr.WAV”);
}
}

New question. I only had the right motors connected, now the left motors seem to be stuck on and only turn off when I decelerate completely. This is new behavior I'm wondering may be related to pin layout but I'm not sure. Maybe someone can explain what is happening.

On the Wild Thumper motor shield, some of the pins used for arduino SPI are hardwired to certain locations so I've been using the ICSP to talk to the Rugged Audio Shield:

define LmotorA 3 // Left motor H bridge, input A

define LmotorB 11 // Left motor H bridge, input B

define RmotorA 5 // Right motor H bridge, input A

define RmotorB 6 // Right motor H bridge, input B

define RCleft 0 // Digital input 0

define RCright 1 // Digital input 1

define S0 2 // Servo output 00

define S1 4 // Servo output 01

define S2 7 // Servo output 02

define S3 8 // Servo output 03

define S4 9 // Servo output 04

define S5 10 // Servo output 05

define S6 12 // Servo output 06

define A1 1 // Analog input 01

define A2 2 // Analog input 02

define A3 3 // Analog input 03

define A4 4 // Analog input 04

define A5 5 // Analog input 05

define Battery 0 // Analog input 00

define RmotorC 6 // Analog input 06

define LmotorC 7 // Analog input 07

define Charger 13 // Low=ON High=OFF

Arduino SPI pinout:

** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4

I'm wondering if data from the MOSI pin is trying to drive the H bridge. I used a voltmeter to continuity check the D pins with the ICSP header and there is no connection. Does using the SPI library force D11 to output MOSI data? Since D11 and MOSI on the ICSP aren't shorted, where is the data coming from on the ICSP MOSI pin? Is it possible to disable the SPI pin assignment to the D pins and only have it come out the ICSP header? Thanks