Wave Shield in Kombination mit GPS - fail

Hallöle,

ich hab mich in den letzten Tagen mächtig rumgeärgert mit der Kombination aus dem Lady Ada Wave Shield und GPS (Libraries WaveHC und TinyGPS++ mit SoftwareSerial). Ich wollte Course und Entfernung als Sprache ausgeben. Alles läuft gut solange ich das eigentliche Sound-Abspielen auskommentiere. Mit Sound sind die Ergebnisse völlig unvorhersehbar. Manchmal bleibt mein Sketch schon im Setup stecken und ich sehe nicht warum (einen wirklichen Debugger gibt's für Arduino ja wohl nicht oder?). Gelegentlich läuft auch alles wie geplant, aber sehr selten.

Arduino ist ein Duemilanove (ATmega328P). Evtl. Speicherprobleme?

Hat da jemand schon mal Erfahrungen gemacht?

Debugger nicht umbedingt (ausser der Mega? Irgendwer hatte USB Debugger Support)
Aber es gibt auch noch Serial Monitor oder return "Debug".

Meine Glaskugel sagt, dein Sketch verursacht Speicherproblem!! Sketch?

Ich hab schon jede Menge Serial.print.
Sketch (eine Variante):

#include <SoftwareSerial.h>
#include <TinyGPS++.h>

#include <WaveHC.h>
#include <WaveUtil.h>

#include <SoftwareServo.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
 It requires the use of NewSoftSerial, and assumes that you have a
 4800-baud serial GPS device hooked up on pins 8(rx) / pin 3 of GPS module and 9(tx) / pin 4 of GPS module.
 GPS-Module 1 + 5 -> GND, 2 -> VIN
 */

/*
  * Pins used: GPS: 8,9 Servo: 7
 
 * What pins are used by the shield?
 
 * Pins 13, 12, 11 are always used by the SD card 
 * (they are the only pins that have a high speed SPI interface). 
 * Then there are 5 other pins used to talk to the DAC and SD card, 
 * but they can be set to connect to any arduino pin. 
 * However, by default, the library is configured 
 * to use pins 10 (for SD card) and pins 2, 3, 4 and 5 for the DAC. 
 
 * That means pins 6, 7, 8, 9 and the 6 analog in pins 
 * (also known as digital i/o pins 14-20) are available.
 
 */

static const int RXPin = 8, TXPin = 9;
static const int ServoPin = 7;

static const uint32_t GPSBaud = 4800;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

SoftwareServo myservo;

#define LED 13

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 volumes root directory
FatReader file;   // This object represent the WAV file for a pi digit or period
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time
/*
 * Define macro to put error messages in flash memory
 */
#define error(msg) error_P(PSTR(msg))

double LAT[] = {
  54.1, 54.2, 54.3, 54.4, 54.5, 54.6};
double LON[] = {
  12.1, 12.2, 12.3, 12.4, 12.5, 12.6};

int countStations = sizeof(LAT) / sizeof(double);
int nextStation = 0;

double lastDistance = 0.0;

void setup()
{
  pinMode(LED, OUTPUT);
  Serial.begin(9600);

  initServo();

  audioSetup();  
  gpsSetup();
  delay(1000);
  playcomplete("INTRO.WAV");
  delay(2000);
  playcomplete("GPSPREP.WAV");
  Serial.print(countStations);
  Serial.println(F(" Stations to find"));
  delay(10000);
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (ss.available() > 0) {
    if (gps.encode(ss.read())) {
      displayInfo();
    }
  }
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));

    while(true);
  }
}


void audioSetup()
{
  // AUDIO SETUP
  // PgmPrintln("Pi speaker");

  if (!card.init()) {
    error("Card init. failed!");
  }
  if (!vol.init(card)) {
    error("No partition!");
  }
  if (!root.openRoot(vol)) {
    error("Couldn't open dir");
  }

  // PgmPrintln("Files found:");
  // root.ls();
}

void gpsSetup() 
{
  ss.begin(GPSBaud);

  Serial.print(F("Started. TinyGPS++ Library version "));
  Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println();
}

// GPS Helper
void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);

    Serial.println();

    double distance =
      gps.distanceBetween(gps.location.lat(), gps.location.lng(), LAT[nextStation], LON[nextStation]);
    double courseTo =
      gps.courseTo(
    gps.location.lat(),
    gps.location.lng(),
    LAT[nextStation],
    LON[nextStation]);
    Serial.print(F("Distance (m) to Station "));
    Serial.print(nextStation);
    Serial.print(" : ");
    Serial.println(distance);

    if (lastDistance == 0.0) {
      lastDistance = distance;
    }

    if (lastDistance > distance) {
      playcomplete("HOT.WAV");
    } 
    else {
      playcomplete("COLD.WAV");
    }

    if (distance < 20.0) {
      // FOUND
      Serial.print(F("Station "));
      Serial.print(nextStation);
      Serial.println(F(" found"));

      lastDistance = 0.0;
      nextStation++;
      if (nextStation == countStations) {
        unlockDoor();
      } 
      else {

        //        char filename[12];
        //        strcpy(filename, "FOUND");
        //        char buffer[2];
        //        itoa(nextStation-1, buffer, 10);
        //        strcat(filename, buffer);
        //        strcat(filename, ".WAV");
        //        strcat(filename, "\0");
        //        playcomplete(filename);
      }

    } 
    else {
      /*
      char distbuffer[10];
       dtostrf(distance, 6, 0, distbuffer);
       for (int i = 0; i < sizeof(distbuffer) - 1; i++) {
       speaknum(distbuffer[i]);
       }
       */
      Serial.print(F("Course to Station: "));

      const char* course = gps.cardinal(courseTo);
      Serial.println(course);
      Serial.println();

      char filename[7];
      strcpy(filename, course);
      strcat(filename, ".WAV");
      strcat(filename, "\0");
      playcomplete(filename);

      delay(10000);

      lastDistance = distance;

    }
  }
  else
  {
    Serial.println(F("INVALID"));
    playcomplete("WAITGPS.WAV");
  }

}

/////////////////////////////////// AUDIO HELPERS

char filename[13];

void speaknum(char c) {
  uint8_t i=0;

  // copy flash string for 'period' to filename
  strcpy_P(filename, PSTR("P.WAV"));

  if ('0' <= c && c <= 'Z') {
    // digit - change 'P' to digit
    filename[0] = c;
    i = 1;
  } 
  else if (c != '.') {
    // error if not period
    return;
  }
  playcomplete(filename);
}

/*
 * print error message and halt
 */
void error_P(const char *str) {
  PgmPrint("Error: ");
  SerialPrint_P(str);
  sdErrorCheck();
  while(1);
}
/*
 * print error message and halt if SD I/O error
 */
void sdErrorCheck(void) {
  if (!card.errorCode()) return;
  PgmPrint("\r\nSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  PgmPrint(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
/*
 * Play a file and wait for it to complete
 */
void playcomplete(char *name) {
  ss.end();
  playfile(name);
  while (wave.isplaying);

  // see if an error occurred while playing
  sdErrorCheck();
  delay(100);
  ss.begin(GPSBaud);
}
/*
 * Open and start playing a WAV file
 */
void playfile(char *name) {
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  if (!file.open(root, name)) {
    PgmPrint("Couldn't open file ");
    Serial.print(name); 
    return;
  }
  if (!wave.create(file)) {
    PgmPrintln("Not a valid WAV");
    return;
  }
  // ok time to play!
  wave.play();
}

//// UNLOCK //////
void unlockDoor() {
  playcomplete("FOUND.WAV");
  delay(100);

  ss.end();
  SoftwareServo myservo;

  myservo.attach(ServoPin);  // attaches the servo on pin 7 to the servo object 

  myservo.write(45);
  for (int i = 0; i < 2000; i++) {
    SoftwareServo::refresh();
    delay(10);
  }

  delay(1000);
  myservo.write(0);
  for (int i = 0; i < 10; i++) {
    SoftwareServo::refresh();
    delay(10);
  }
  myservo.detach();

  while(true);
}


void initServo() {
  myservo.attach(ServoPin);  // attaches the servo on pin 7 to the servo object 
  myservo.write(0);
  for (int i = 0; i < 10; i++) {
    SoftwareServo::refresh();
    delay(10);
  }
  myservo.detach();
}

Auf jedenfall auch einen ganzen Haufen an delays! Das dauert ja eine halbe Ewigkeit beim Start. Du kannst wegen der Seriellen Ausgabe anfangen, dass F-Makro zu setzen.

Serial.print(F("tesdt"));

Die ganzen Delays hab ich drin weil ich dachte ich lasse den Methoden in den Libs etwas Zeit (oder einfach weil ich warten will bevor die nächste Soundausgabe passiert). Mit weniger Delay gibt es aber die gleichen Effekte.

Das F-Makro hab ich doch (fast) überall drin.

Oh, dann hab ich genau die Stelle gefunden, wo es nicht war! Ist eines ohne.

Das ist aber kaum der Grund für das merkwürdige Verhalten oder?

Alles läuft gut solange ich das eigentliche Sound-Abspielen auskommentiere. Mit Sound sind die Ergebnisse völlig unvorhersehbar. Manchmal bleibt mein Sketch schon im Setup stecken und ich sehe nicht warum

Wenn sich im RAM was gegenseitig überschreibt, kommt gerne "völlig unvorhersehbar" raus.