I can't get the Wave Shield, PCA 9685 servo motors to work s

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

I can't get the Wave Shield, PCA 9685 servo motors to work s

Post by isaace »

I can't get my PMDC motors to run when I am using the following:
  • Arduino Uno
    PCA9685 with 8 servos
    Ada Fruit Wave Shield
    L298 H-bridge IC
    BitVoicer voice recognition library
    and a few other supporting hand built circuits...
I can get everything to work fine until I introduce the two PMDC's. Then my servos don't move. Please look at my code. I commented out the PMDC code, but you can see where I put it. This is a 4 foot tall talking humanoid robot that responds to voice command. Everything works, but the PMDC's. Obviously I am using the PMDC's for wheels, rather than actual legs. I am not that good of an engineer.

Regarding the PMDC pins, you can see what I used in the code (assembled in part from test code that I found.) The pins should be open, but they seem to interfere with the servos. Do I need to connect the PMDC's to the PCA?

Code: Select all

#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include <BitVoicer11.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

int led = 6;
BitVoicerSerial bvSerial = BitVoicerSerial(); //Stores true if the Audio Streaming Calibration tool is running
boolean sampleTest = false;  //Stores the data type retrieved by getData()
byte dataType = 0; //Sets up the pins and default variables

SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time
/*
int mot1ana = ;
int mot1a = 6;
int mot1b=8;
int motrana=;
int motra=;  // just changed from pin 11 (used by wave shield)
int motrb=;
*/
int degrees;
int ServoPulse(int degrees)
           {
                return map(degrees, 0, 180, SERVOMIN, SERVOMAX);
            }
            uint8_t HEAD = 0;
            uint8_t NECK = 1;
            uint8_t LST = 2;
            uint8_t LSB = 3;
            uint8_t RST = 4;
            uint8_t RSB = 5;
            uint8_t LELB = 6;
            uint8_t RELB = 7;
            uint8_t LHAND = 8;
            uint8_t RHAND = 9;            
                                                
            uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
            dir_t dirBuf;     // buffer for directory reads
            #define error(msg) error_P(PSTR(msg))



#define DEBOUNCE 5  // button debouncer

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
void play(FatReader &dir);
// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
void setup() {
  /*
pinMode(mot1ana,OUTPUT);
pinMode(mot1a,OUTPUT);
pinMode(mot1b,OUTPUT);
pinMode (motrana,OUTPUT);
pinMode (motra,OUTPUT);
pinMode (motrb,OUTPUT);
  */
  
pwm.begin();
             
pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  pinMode(led, OUTPUT);     

  
  bvSerial.setAudioInput(1);  
  Serial.begin(115200);  //Sets up the pinModes
  byte i;
  putstring_nl("WaveHC with ");
  Serial.print(NUMBUTTONS, DEC);
  putstring_nl("buttons");
  
  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
  
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }
  if (!card.init()) {         //play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
  card.partialBlockRead(true);
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
  
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
  
  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
  
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;
}

SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  byte index;

  for (index = 0; index < NUMBUTTONS; index++) {
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons

  }
}
void loop() {

  if (sampleTest == true)
  {
    bvSerial.BANNED(46);
  }
  if (bvSerial.engineRunning)
  {
    bvSerial.BANNED(46);
  }
}
void serialEvent()
{
  dataType = bvSerial.getData(); 
  if (dataType == BV_COMMAND)
      sampleTest = bvSerial.cmdData;
  if (dataType == BV_STATUS && bvSerial.engineRunning == true)
    bvSerial.startStopListening();
  

  if (dataType == BV_STR)

  if (bvSerial.strData == "hello"){
  playcomplete("hello.WAV");
  
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LHAND, 0, ServoPulse(90));
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));}

                  
  if (bvSerial.strData == "forward"){
  /*              
//analogWrite(motlana,500);  //Forward left
  digitalWrite(mot1a,HIGH);
  digitalWrite(mot1b,LOW);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);
  analogWrite(mot1ana,500);
  digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,HIGH);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);  
  
  
    analogWrite(motrana,500);  //Forward right
  digitalWrite(motra,HIGH);
  digitalWrite(motrb,LOW);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);
  analogWrite(motrana,500);
  digitalWrite(motra,LOW);
  digitalWrite(motrb,HIGH);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);  
*/
  }
//  if (bvSerial.strData == "hi")  
//  playcomplete("hello.wav");
  if (bvSerial.strData == "name"){
  playcomplete("name.wav");
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
                                    pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
  }
  
    if (bvSerial.strData == "bye"){
  playcomplete("bye.WAV");
  
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));

                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
                  
    }
  if (bvSerial.strData == "sorry"){
  playcomplete("sorry.WAV");
  
  
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
  }
    if (bvSerial.strData == "bored"){
  playcomplete("bored.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
  }
    if (bvSerial.strData == "ican"){
  playcomplete("ican.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
    }
  if (bvSerial.strData == "no"){
  playcomplete("no.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
  }
    if (bvSerial.strData == "yes"){
  playcomplete("yes.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
    } 
        if (bvSerial.strData == "saw"){
  playcomplete("saw.WAV");
                                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
    } 
  byte i;

}

void playcomplete(char *name) {
  playfile(name);
  
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.print(name); return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }
  
  // ok time to play! start playback
  wave.play();
}

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

What pins are you using? You only define 2 of them in the posted code. The PCA9685 requires A4 (SDA) and A5 (SCL) only.

Code: Select all

/*
int mot1ana = ;
int mot1a = 6;
int mot1b=8;
int motrana=;
int motra=;  // just changed from pin 11 (used by wave shield)
int motrb=;
*/

Code: Select all

  /*
pinMode(mot1ana,OUTPUT);
pinMode(mot1a,OUTPUT);
pinMode(mot1b,OUTPUT);
pinMode (motrana,OUTPUT);
pinMode (motra,OUTPUT);
pinMode (motrb,OUTPUT);
  */

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Oops. I forgot. The last time I was messing with it, I removed most of the pin numbers to see if I can get at least one of the DC motors to run. Even with the code you can see below, it did not work even on one motor. I was using the open digital pins described in the Adafruit Wave Shield tutorial found on your website (https://learn.adafruit.com/adafruit-wav ... rduino/faq).

It does say that the six analog pins are not used by the shield. Would those work? How would I write that in the code for a PMDC?

Isaac

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

The PCA9685 requires A4 (SDA) and A5 (SCL) only. So A0-A3 and the digital pins not used by the wave shield should all be free to use.

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Ok, I tried using the analog pins and it worked fine on some h-bridge test code that I wrote, but when I tried it in my robot code, there were two problems:

1. "'motlana' was not declared in this scope." I did declare it, so I don't know why I am getting that error.
2. Once I comment out the "analogWrite(motlana,500);" line, then when I program the robot, I get nothing when I give it the FORWARD command. The servos don't actuate, nor do any wave files play.

Here is my current robot code:

Code: Select all

#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include <BitVoicer11.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

int led = 6;
BitVoicerSerial bvSerial = BitVoicerSerial(); //Stores true if the Audio Streaming Calibration tool is running
boolean sampleTest = false;  //Stores the data type retrieved by getData()
byte dataType = 0; //Sets up the pins and default variables

SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

int mot1ana = A0;
int mot1a = A1;
int mot1b=A2;;
/*int motrana=;
int motra=;  // just changed from pin 11 (used by wave shield)
int motrb=;
*/
int degrees;
int ServoPulse(int degrees)
           {
                return map(degrees, 0, 180, SERVOMIN, SERVOMAX);
            }
            uint8_t HEAD = 0;
            uint8_t NECK = 1;
            uint8_t LST = 2;
            uint8_t LSB = 3;
            uint8_t RST = 4;
            uint8_t RSB = 5;
            uint8_t LELB = 6;
            uint8_t RELB = 7;
            uint8_t LHAND = 8;
            uint8_t RHAND = 9;            
                                                
            uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
            dir_t dirBuf;     // buffer for directory reads
            #define error(msg) error_P(PSTR(msg))



#define DEBOUNCE 5  // button debouncer

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
void play(FatReader &dir);
// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
void setup() {
  
pinMode(mot1ana,OUTPUT);
pinMode(mot1a,OUTPUT);
pinMode(mot1b,OUTPUT);
/*pinMode (motrana,OUTPUT);
pinMode (motra,OUTPUT);
pinMode (motrb,OUTPUT);
  */
  
pwm.begin();
             
pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  pinMode(led, OUTPUT);     

  
  bvSerial.setAudioInput(1);  
  Serial.begin(115200);  //Sets up the pinModes
  byte i;
  putstring_nl("WaveHC with ");
  Serial.print(NUMBUTTONS, DEC);
  putstring_nl("buttons");
  
  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
  
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }
  if (!card.init()) {         //play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
  card.partialBlockRead(true);
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
  
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
  
  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
  
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;
}

SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  byte index;

  for (index = 0; index < NUMBUTTONS; index++) {
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons

  }
}
void loop() {

  if (sampleTest == true)
  {
    bvSerial.BANNED(46);
  }
  if (bvSerial.engineRunning)
  {
    bvSerial.BANNED(46);
  }
}
void serialEvent()
{
  dataType = bvSerial.getData(); 
  if (dataType == BV_COMMAND)
      sampleTest = bvSerial.cmdData;
  if (dataType == BV_STATUS && bvSerial.engineRunning == true)
    bvSerial.startStopListening();
  

  if (dataType == BV_STR)

  if (bvSerial.strData == "hello"){
  playcomplete("hello.WAV");
  
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LHAND, 0, ServoPulse(90));
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));}

                  
  if (bvSerial.strData == "forward"){
                
analogWrite(motlana,500);  //Forward left
  digitalWrite(mot1a,HIGH);
  digitalWrite(mot1b,LOW);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);
  analogWrite(mot1ana,500);
  digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,HIGH);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);  
  
/*  
    analogWrite(motrana,500);  //Forward right
  digitalWrite(motra,HIGH);
  digitalWrite(motrb,LOW);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);
  analogWrite(motrana,500);
  digitalWrite(motra,LOW);
  digitalWrite(motrb,HIGH);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);  
*/
  }
//  if (bvSerial.strData == "hi")  
//  playcomplete("hello.wav");
  if (bvSerial.strData == "name"){
  playcomplete("name.wav");
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
                                    pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
  }
  
    if (bvSerial.strData == "bye"){
  playcomplete("bye.WAV");
  
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));

                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
                  
    }
  if (bvSerial.strData == "sorry"){
  playcomplete("sorry.WAV");
  
  
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
  }
    if (bvSerial.strData == "bored"){
  playcomplete("bored.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
  }
    if (bvSerial.strData == "ican"){
  playcomplete("ican.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
    }
  if (bvSerial.strData == "no"){
  playcomplete("no.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
  }
    if (bvSerial.strData == "yes"){
  playcomplete("yes.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100));  
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  delay(500);
    } 
        if (bvSerial.strData == "saw"){
  playcomplete("saw.WAV");
                                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70));  
                  pwm.setPWM(RSB, 0, ServoPulse(90));  
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                  
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180));  
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
    } 
  byte i;

}

void playcomplete(char *name) {
  playfile(name);
  
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.print(name); return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }
  
  // ok time to play! start playback
  wave.play();
}



For the record, this is my h-bridge test code:

Code: Select all

int mot1ana = A0;
int mot1a = A1;
int mot1b=A2;;
//int motrana=0;
//int motra=11;
//int motrb=10;

void setup() {
pinMode(mot1ana,OUTPUT);
pinMode(mot1a,OUTPUT);
pinMode(mot1b,OUTPUT);
//pinMode (motrana,OUTPUT);
//pinMode (motra,OUTPUT);
//pinMode (motrb,OUTPUT);
}

void loop() {
  analogWrite(mot1ana,500);  //Forward left
  digitalWrite(mot1a,HIGH);
  digitalWrite(mot1b,LOW);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);
  analogWrite(mot1ana,500);
  digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,HIGH);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);  
  
  /*
    analogWrite(motrana,500);  //Forward right
  digitalWrite(motra,HIGH);
  digitalWrite(motrb,LOW);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);
  analogWrite(motrana,500);
  digitalWrite(motra,LOW);
  digitalWrite(motrb,HIGH);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);  
  */
}

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

You have an awful lot going on there and a lot of libraries. You may be running into memory problems. This guide has some good tips on diagnosing memory problems and optimizing memory usage: http://learn.adafruit.com/memories-of-an-arduino

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Can I go to a bigger chip?

Could I replace my 328 with an ATMEGA8515-16PU?

I'm currently using a 328 on an Uno. I am not scared of soldering up a board. I do it all the time, but I haven't used the 8515 chip. Would the 8515 take an Uno bootloader?

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

The 8518 has even less memory than the 328:
http://www.atmel.com/images/doc2512.pdf

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Oh, I didn't notice that. Can I just go with a bigger chip with more memory?

But maybe it isn't a memory issue. Now when I compile, my IDE says: "Binary sketch size: 21,636 bytes (of a 32,256 byte maximum)"

That doesn't sound like a memory problem to me.

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

There is more than one kind of memory. SRAM is the usual problem. Please see this guide for details: http://learn.adafruit.com/memories-of-an-arduino

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Thanks for the tutorial. I think it helped and it was a good education, but I'm still not there yet. I followed its recommendation and looked for libraries that I was not using. I commented out the first three and the robot works fine (still without the PMDC's). I don't remember why I ever put those three libraries in there in the first place. If I comment out the all of the PMDC code it will work on the servos and voice. If I don't comment out the PMDC code, it will still upload fine, but I get nothing when I use Bitvoicer.

Could the problem be that I am running all of the servos through a PCA, but the PMDC's are running directly off the pins on the micro (and through an L298 h-bridge, powered with 12 volts)? Remember, my PMDC's work wonderfully when using the h-bridge test code I displayed earlier.

Again, thanks for all of your help. I am so close.



Code: Select all

#include <FatReader.h>
// #include <SdReader.h>
// #include <avr/pgmspace.h>
// #include "WaveUtil.h"
#include "WaveHC.h"
#include <BitVoicer11.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

int led = 6;
BitVoicerSerial bvSerial = BitVoicerSerial(); //Stores true if the Audio Streaming Calibration tool is running
boolean sampleTest = false;  //Stores the data type retrieved by getData()
byte dataType = 0; //Sets up the pins and default variables

SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

int mot1ana = A0;
int mot1a = A1;
int mot1b=A2;;
/*int motrana=;
int motra=;  // just changed from pin 11 (used by wave shield)
int motrb=;
*/
int degrees;
int ServoPulse(int degrees)
           {
                return map(degrees, 0, 180, SERVOMIN, SERVOMAX);
            }
            uint8_t HEAD = 0;
            uint8_t NECK = 1;
            uint8_t LST = 2;
            uint8_t LSB = 3;
            uint8_t RST = 4;
            uint8_t RSB = 5;
            uint8_t LELB = 6;
            uint8_t RELB = 7;
            uint8_t LHAND = 8;
            uint8_t RHAND = 9;           
                                               
            uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
            dir_t dirBuf;     // buffer for directory reads
            #define error(msg) error_P(PSTR(msg))



#define DEBOUNCE 5  // button debouncer

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
void play(FatReader &dir);
// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end;
  extern int  *__brkval;
  int free_memory;
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval);
  }
  return free_memory;
}

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
void setup() {
 
pinMode(mot1ana,OUTPUT);
pinMode(mot1a,OUTPUT);
pinMode(mot1b,OUTPUT);
/*pinMode (motrana,OUTPUT);
pinMode (motra,OUTPUT);
pinMode (motrb,OUTPUT);
  */
 
pwm.begin();
             
pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  pinMode(led, OUTPUT);     

 
  bvSerial.setAudioInput(1); 
  Serial.begin(115200);  //Sets up the pinModes
  byte i;
  putstring_nl("WaveHC with ");
  Serial.print(NUMBUTTONS, DEC);
  putstring_nl("buttons");
 
  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
 
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }
  if (!card.init()) {         //play with 8 MHz spi (default faster!) 
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
  card.partialBlockRead(true);
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part))
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
 
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
 
  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
 
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;
}

SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  byte index;

  for (index = 0; index < NUMBUTTONS; index++) {
    currentstate[index] = digitalRead(buttons[index]);   // read the button
   
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons

  }
}
void loop() {

  if (sampleTest == true)
  {
    bvSerial.BANNED(46);
  }
  if (bvSerial.engineRunning)
  {
    bvSerial.BANNED(46);
  }
}
void serialEvent()
{
  dataType = bvSerial.getData();
  if (dataType == BV_COMMAND)
      sampleTest = bvSerial.cmdData;
  if (dataType == BV_STATUS && bvSerial.engineRunning == true)
    bvSerial.startStopListening();
 

  if (dataType == BV_STR)

  if (bvSerial.strData == "hello"){
  playcomplete("hello.WAV");
 
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  pwm.setPWM(RSB, 0, ServoPulse(90)); 
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LHAND, 0, ServoPulse(90));
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                 
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                 
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180)); 
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));}

                 
  if (bvSerial.strData == "forward"){
               
analogWrite(motlana,500);  //Forward left
  digitalWrite(mot1a,HIGH);
  digitalWrite(mot1b,LOW);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200);
  analogWrite(mot1ana,500);
  digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,HIGH);
  delay(200);
    digitalWrite(mot1a,LOW);
  digitalWrite(mot1b,LOW);
  delay(200); 
 
/* 
    analogWrite(motrana,500);  //Forward right
  digitalWrite(motra,HIGH);
  digitalWrite(motrb,LOW);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200);
  analogWrite(motrana,500);
  digitalWrite(motra,LOW);
  digitalWrite(motrb,HIGH);
  delay(200);
    digitalWrite(motra,LOW);
  digitalWrite(motrb,LOW);
  delay(200); 
*/
  }
//  if (bvSerial.strData == "hi") 
//  playcomplete("hello.wav");
  if (bvSerial.strData == "name"){
  playcomplete("name.wav");
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  pwm.setPWM(RSB, 0, ServoPulse(90)); 
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                 
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                 
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180)); 
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
                                    pwm.setPWM(NECK, 0, ServoPulse(90));                 
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180)); 
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
  }
 
    if (bvSerial.strData == "bye"){
  playcomplete("bye.WAV");
 
                  pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  pwm.setPWM(RSB, 0, ServoPulse(90)); 
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));

                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                 
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                 
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180)); 
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
                  pwm.setPWM(RELB, 0, ServoPulse(50));
                 
    }
  if (bvSerial.strData == "sorry"){
  playcomplete("sorry.WAV");
 
 
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100)); 
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  delay(500);
  }
    if (bvSerial.strData == "bored"){
  playcomplete("bored.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100)); 
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  delay(500);
  }
    if (bvSerial.strData == "ican"){
  playcomplete("ican.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100)); 
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  delay(500);
    }
  if (bvSerial.strData == "no"){
  playcomplete("no.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100)); 
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  delay(500);
  }
    if (bvSerial.strData == "yes"){
  playcomplete("yes.WAV");
                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  delay(200);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(50));
                  delay(300);
                  pwm.setPWM(NECK, 0, ServoPulse(80));
                  pwm.setPWM(RST, 0, ServoPulse(20));
                  delay(500);
                  pwm.setPWM(RST, 0, ServoPulse(00));
                  pwm.setPWM(LSB, 0, ServoPulse(100));  // Keep close to 90, so it doesn't hit itself
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(60));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(100)); 
                  delay(500);
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  delay(500);
    }
        if (bvSerial.strData == "saw"){
  playcomplete("saw.WAV");
                                    pwm.setPWM(HEAD, 0, ServoPulse(90));
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LST, 0, ServoPulse(70)); 
                  pwm.setPWM(RSB, 0, ServoPulse(90)); 
                  delay(100);
                  pwm.setPWM(HEAD, 0, ServoPulse(70));
                  pwm.setPWM(NECK, 0, ServoPulse(90));
                  delay(100);
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  pwm.setPWM(LSB, 0, ServoPulse(180));  // Keep between 90 and 180, so it doesn't hit itself
                  delay(200);
                  pwm.setPWM(LELB, 0, ServoPulse(100));
                 
                  delay(150);
                  pwm.setPWM(LELB, 0, ServoPulse(130));
                  delay(150);
                  pwm.setPWM(RELB, 0, ServoPulse(90));
                  pwm.setPWM(NECK, 0, ServoPulse(90));                 
                  pwm.setPWM(RELB, 0, ServoPulse(0));
                  pwm.setPWM(LST, 0, ServoPulse(180)); 
                  delay(500);
                  pwm.setPWM(LSB, 0, ServoPulse(100));   // Keep close to 90, so it doesn't hit itself
                  pwm.setPWM(LHAND, 0, ServoPulse(60));
                  pwm.setPWM(NECK, 0, ServoPulse(120));
                  delay(500);
                  pwm.setPWM(LHAND, 0, ServoPulse(180));
    }
  byte i;

}

void playcomplete(char *name) {
  playfile(name);
 
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.print(name); return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }
 
  // ok time to play! start playback
  wave.play();
}

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

I'm not familiar with the Bitvoicer library. What pins does that use? And if it is allocating significant SRAM bufers, you may still have a memory problem,

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Bitvoicer is not hardware. It is a voice recognition library and GUI. It basically comes in two parts: the library and a GUI interface (so yes, your Arduino board has to be connected to the PC or Apple and it is not compatible with Linux). It is extremely easy to use and I have built several projects with it, but I don't believe the Bitvoicer library interferes with any pins. My last Bitvoicer project was a 4 foot humanoid with 12 servos. I could give it voice commands (through my laptop) and it would move the head and different limbs accordingly. My computer was connected, because I needed it for the GUI and microphone.

This project is different, in that I am using the wave shield, the PCA, more servos, the PMDC and a better power supply for it all. So this time, the robot moves AND talks back. Now I just want it to drive around the room when I tell it to.

For more information on Bitvoicer, see: http://www.bitsophia.com/BitVoicer.aspx

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by adafruit_support_bill »

Bitvoicer is not hardware. It is a voice recognition library and GUI.
But how much SRAM does it require? This still sounds like a memory problem to me.

Use the freeRam() function from the memory tutorial to find out how much you have left:
https://learn.adafruit.com/memories-of- ... ree-memory

User avatar
isaace
 
Posts: 48
Joined: Mon Sep 08, 2014 11:18 pm

Re: I can't get the Wave Shield, PCA 9685 servo motors to wo

Post by isaace »

Ok, I just got a response from Bitsofia. They are the creators of the bitvoicer library and GUI. This is what they said.

We just checked the RAM usage of our library using the MemoryFree library (http://playground.arduino.cc/Code/AvailableMemory) and it is reporting 90 bytes with the BitVoicerSerial class instantiated.

Calling our library functions may increase the RAM usage mostly based on the size of passed variables.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”