DATALOGGING ON WAVESHIELD CODE HELP

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

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
Coldsoldier
 
Posts: 6
Joined: Wed Sep 17, 2014 5:44 pm

DATALOGGING ON WAVESHIELD CODE HELP

Post by Coldsoldier »

Hello, I ordered the wave shields and its works wonderful. I have no problem programming the wave-shield to play my audio based on my sensor input. I also don't have any problems logging data to the SD card from the wave shield. I do have an issue when I try to combine both. I understand the arduino does not have enough resources to carry out playing audio and writing to the SD card at the same time. That isn't my goal. What I want would be a program that would record the sensor input, and when the audio is activated, stops collecting, lets the audio play out, and once the audio is done playing, continues to log data to the card. I tried just combining my code from my past project (data-logger on wave shield, sensor based waveshield audio player) but I noticed that my code sent me into the negative RAM area. My code is very messy, and to shorten it, I tried to reduce/eliminate many strings. I got it down to about -113, but I still keep getting a lot of problems. I have not gotten it to work once. Any help would be appreciated.

I essentially copied code from the tutorials, and played around with them to get it to to work on the data-logger and audio wave shield. I'm only marginally experienced in programming, so keep that in mind.

(Also, although the code specifies multiple buttons, I am currently only using one sensor input in A0. The knock-sensor. I did not change it because it did not affect the RAM. I used it originally because it was given as an example)
Thank you!

Code: Select all

#include <SD.h>
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"

 
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
 
  // for Piezo
const int ledPin = 13;      // led connected to digital pin 13
const int knockSensor = A0; // the piezo is connected to analog pin 0
const int threshold = 205;
const int conthreshold = 820; // threshold value to decide when the detected sound is a knock or not
int CS_pin = 10; //For datalogger
int pow_pin = 8;


// these variables will change:
int sensorReading = 0;      // variable to store the value read from the sensor pin
int ledState = LOW;                  // variable for reading the pin status
  
 
#define DEBOUNCE 5  // button debouncer
 
// 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("I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
 
void setup() {
  //pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
 Serial.begin(9600); 
// use the serial port
 
  byte i;
  
  // set up serial port
  Serial.begin(9600);
  //putstring_nl("WaveHC with ");
  //putstring_nl("buttons");
  
  putstring("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!
  
  // Set the output pins for the DAC control. This pins are defined in the library
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, INPUT);
  pinMode(8, OUTPUT);
  
  //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
  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!
  }
  
  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);
 
// Now we will look for a FAT partition!
  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("f2");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  
  // Lets tell the user about what we found
  putstring("Partition");
  Serial.print(part, DEC);
  putstring("FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
  
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
  
  Serial.println("Intializing failed");
  pinMode(CS_pin, OUTPUT);
  
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin, HIGH);   
  
  if(!SD.begin(CS_pin))            // data-logger code
  {
    Serial.println("Failed");
    //return;
  }
  Serial.println("Ready");
    
  
  // 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()
{
  
}
 
void loop(){
  //digitalWrite(8,HIGH);
  Serial.println(sensorReading);
  sensorReading = analogRead(knockSensor);  // read input value
   if (sensorReading >= 820) {            // check if the input is HIGH
    Serial.println("ExtremeDanger");
       // Make scary eyes
    Serial.println("Playing");
       // SSSSSSSSS.... That's a nice everything you have
    playcomplete("case5.wav");
     delay(100);
      Serial.println("NXT");
       // End Movement
       // Explode
       //Serial.println("time to explode");
       //playcomplete("explode.wav");
       // Go back to sleep
       Serial.println("next");
      delay(100);
      
      // We only want to print on the output change, not state
      //pirState = HIGH;
    
  /* /*else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
 
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }*/
}
delay(100);
      
      if ( sensorReading > 103 && sensorReading < 250){
        Serial.println("D1");
        playcomplete("case1.wav");
        delay(100);
        Serial.println("Player informed");
      }
      
      if ( sensorReading > 250 && sensorReading < 410){
        Serial.println("20Gs detected");
        playcomplete("case2.wav");
        delay(100);
        Serial.println("Player informed. Back to data collection");
      }
      
      if ( sensorReading > 410 && sensorReading < 615){
       Serial.println("d40");
      playcomplete("case3.wav");
      delay(100);
      Serial.println("NXT");
      }
      
      if ( sensorReading > 615 && sensorReading < 820){
        Serial.println("d60");
        playcomplete("case4.wav");
        delay(100);
        Serial.println("NXT");
      }
      
    String dataString = String(sensorReading);
  File dataFile = SD.open("log.txt", FILE_WRITE);  //writing to file
  if(dataFile)
  {
    dataFile.println(dataString);
    dataFile.close();
    Serial.println(dataString);              // data-logger code
  }
  else
  {
    Serial.println("Failed");
  }
  
  
  delay(1000);  
      
}
 
// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
  // call our helper to find and play this name
  playfile(name);
  while (wave.isplaying) {
  // do nothing while its playing
  }
  // 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: 88087
Joined: Sat Feb 07, 2009 10:11 am

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by adafruit_support_bill »

Pin definitions and constant values do not need to be integers. Integers require SRAM storage. You can use a #define instead.

You also have quite a few literal strings that could be moved to Flash with the "F()" macro. See this tutorial for more tips on optimizing memory. http://learn.adafruit.com/memories-of-an-arduino

User avatar
Coldsoldier
 
Posts: 6
Joined: Wed Sep 17, 2014 5:44 pm

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by Coldsoldier »

Thank you. I looked at the tutorial and I was able to vastly increase my RAM through F() and some string manipulation. I decided to start over and use my working input wave shield code as the base. I am still however getting trouble. According to my code, I have 629 RAM with just my input based wave shield. Once I import the SD header though this drops down to 23 and I immediately start getting problems. It will simply start re-printing "Free RAM 23" over and over again. I don't understand whats happening. When running only the SD data logger I have 1139 RAM available. So it seems I should have considerably more when I combine the two. Is it maybe the way I combine my code?

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

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by adafruit_support_bill »

Reading and writing to the SD card is done in block units of 512 bytes. The 512 byte block read/write buffer needs to be in SRAM. Two files open at the same time would require two buffers. Given that you only have 2048 bytes of SRAM to start with, it goes pretty quickly when you start doing file i/o.

User avatar
Coldsoldier
 
Posts: 6
Joined: Wed Sep 17, 2014 5:44 pm

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by Coldsoldier »

Is my beginning goal (to store input on card, then stop, and play audio file when activated) still possible to do? I am looking into using PROGMEM but I am not sure if it would yield a large enough increase in RAM.

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

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by adafruit_support_bill »

I think it is possible. But I'm not sure how easy it would be. I think the trick is to get SD and WaveHC to take turns sharing the same buffer.
It might be an easier task to start with WaveRP which is designed for both recording and playback and incorporates the SD library:
https://code.google.com/p/waverp/

User avatar
Coldsoldier
 
Posts: 6
Joined: Wed Sep 17, 2014 5:44 pm

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by Coldsoldier »

Thank you for this. I've been working and trying to use the WaveRP to do what I need but i keep running into problems. The closest I've come is being able to open up a file on the SD card. After that, it usually fails and gives me a "error: Missed data record" or "can't open: case1.wave". I'm really having trouble finding a way to stop the program from logging to the SD when I want to play a wav.file from the SD and then restarting the logData over. In my code, I use the WaveRecordandPlay program as the base and use the dataLogger example found on the sdfat library as an add on. It's been challenging, but fun nonetheless. Where am I going wrong?

Edit: I was able to get the intial case1.wav to play upon startup but I still get the ("error: Missed data record")

Code: Select all

/**
 * Example Arduino record/play sketch for the Adafruit Wave Shield.
 * For best results use Wave Shield version 1.1 or later.
 *
 * The SD/SDHC card should be formatted with 32KB allocation units/clusters.
 * Cards with 2GB or less should be formatted FAT16 to minimize file
 * system overhead. If possible use SDFormatter from
 * www.sdcard.org/consumers/formatter/
 *
 * The user must supply a microphone preamp that delivers 0 - vref volts
 * of audio signal to the analog pin.  The preamp should deliver vref/2
 * volts for silence.
 *
 */
#include <SdFat.h>
#include <WaveRP.h>
#include <SdFatUtil.h>
#include <ctype.h>
// record rate - must be in the range 4000 to 44100 samples per second
// best to use standard values like 8000, 11025, 16000, 22050, 44100
#define RECORD_RATE 22050
//#define RECORD_RATE 44100
//

#define FILE_BASE_NAME "DATA"
// max recorded file size.  Size should be a multiple of cluster size.
// the recorder creates and erases a contiguous file of this size.
// 100*1024*1024 bytes - about 100 MB or 150 minutes at 11025 samples/second
#define MAX_FILE_SIZE 104857600UL  // 100 MB
//#define MAX_FILE_SIZE 1048576000UL // 1 GB
//
// Analog pin connected to mic preamp
#define MIC_ANALOG_PIN 2
//

const uint8_t chipSelect = SS;
// Voltage Reference Selections for ADC
//#define ADC_REFERENCE ADC_REF_AREF  // use voltage on AREF pin
 #define ADC_REFERENCE ADC_REF_AVCC  // use 5V VCC
//
const uint32_t SAMPLE_INTERVAL_MS = 200;
int sensorInput = A0;
// print the ADC range while recording if > 0
// print adcMax,adcMin if > 1
#define DISPLAY_RECORD_LEVEL 1
//
// print file info - useful for debug
#define PRINT_FILE_INFO 0
//
// print bad wave file size and SD busy errors for debug
#define PRINT_DEBUG_INFO 1


//------------------------------------------------------------------------------
// global variables
Sd2Card card;           // SD/SDHC card with support for version 2.00 features
SdVolume vol;           // FAT16 or FAT32 volume
SdFile root;            // volume's root directory
SdFile file;            // current file
WaveRP wave;            // wave file recorder/player
int16_t lastTrack = -1; // Highest track number
uint8_t trackList[32];
 char stopMode = Serial.println("Hit detected");
// bit list of used tracks
//------------------------------------------------------------------------------
// print error message and halt
void error(char* str) {
  PgmPrint("error: ");
  Serial.println(str);
  if (card.errorCode()) {
    PgmPrint("sdError: ");
    Serial.println(card.errorCode(), HEX);
    PgmPrint("sdData: ");
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}
//------------------------------------------------------------------------------

SdFat sd;

// Log file.


// Time in micros for next data record.
uint32_t logTime;

//==============================================================================
// User functions.  Edit writeHeader() and logData() for your requirements.

const uint8_t ANALOG_COUNT = 4;
//------------------------------------------------------------------------------
// Write data header.
void writeHeader() {
  file.print(F("micros"));
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.print(F(",adc"));
    file.print(i, DEC);
  }
  file.println();
}
//------------------------------------------------------------------------------
// Log a data record.
void logData() {
  uint16_t data[ANALOG_COUNT];
  
  // Read all channels to avoid SD write latency between readings.
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    data[i] = analogRead(i);
  }
  // Write data to file.  Start with log time in micros.
  file.print(logTime);
  
  // Write ADC data to CSV record.
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.write(',');
    file.print(data[i]);
  }
  file.println();
}
//==============================================================================
// Error messages stored in flash.
#define error(msg) error_P(PSTR(msg))
//------------------------------------------------------------------------------
void error_P(const char* msg) {
  sd.errorHalt_P(msg);}
//------------------------------------------------------------------------------
// clear all bits in track list
void listClear(void)  {
  memset(trackList, 0, sizeof(trackList));
}
//------------------------------------------------------------------------------
// return bit for track n
uint8_t listGet(uint8_t n) {
  return (trackList[n >> 3] >> (n & 7)) & 1;
}
//------------------------------------------------------------------------------
// print list of tracks in ten columns with each column four characters wide
void listPrint(void) {
  PgmPrintln("\nTrack list:");
  uint8_t n = 0;
  uint8_t nc = 0;
  do {
    if (!listGet(n)) continue;
    if (n < 100) Serial.print(' ');
    if (n < 10) Serial.print(' ');
    Serial.print(n, DEC);
    if (++nc == 10) {
      Serial.println();
      nc = 0;
    } else {
      Serial.print(' ');
    }
  } while (n++ != 255);
  if (nc) Serial.println();
}
//------------------------------------------------------------------------------
// set bit for track n
void listSet(uint8_t n) {
  trackList[n >> 3] |= 1 << (n & 7);
}
//------------------------------------------------------------------------------
// Nag user about power and SD card
void nag(void) {
  PgmPrintln("\nTo avoid USB noise use a DC adapter");
  PgmPrintln("or battery for Arduino power.\n");
  uint8_t bpc = vol.blocksPerCluster();
  PgmPrint("BlocksPerCluster: ");
  Serial.println(bpc, DEC);
  uint8_t align = vol.dataStartBlock() & 0X3F;
  PgmPrint("Data alignment: ");
  Serial.println(align, DEC);
  PgmPrint("sdCard size: ");
  Serial.print(card.cardSize()/2000UL);PgmPrintln(" MB");
  if (align || bpc < 64) {
    PgmPrintln("\nFor best results use a 2 GB or larger card.");
    PgmPrintln("Format the card with 64 blocksPerCluster and alignment = 0.");
    PgmPrintln("If possible use SDFormater from www.sdcard.org/consumers/formatter/");
  }
  if (!card.eraseSingleBlockEnable()) {
    PgmPrintln("\nCard is not erase capable and can't be used for recording!");
  }
}
//------------------------------------------------------------------------------
// check for pause resume
void pauseResume(void) {
  if (!Serial.available()) return;
  uint8_t c = Serial.read();
  while (Serial.read() >= 0) {}
  if (c == 's') {
    wave.stop();
  } else if (c == 'p') {
    wave.pause();
    while (wave.isPaused()) {
      PgmPrintln("\nPaused - type 's' to stop 'r' to resume");
      while (!Serial.available()) {}
      c = Serial.read();
      if (c == 's') wave.stop();
      if (c == 'r') wave.resume();
    }
  }
}
//------------------------------------------------------------------------------
// play all files in the root dir
void playAll(void) {
  dir_t dir;
  char name[13];
  uint8_t np = 0;
  root.rewind();
  while (root.readDir(&dir) == sizeof(dir)) {
    //only play wave files
    if (strncmp_P((char *)&dir.name[8], PSTR("WAV"), 3)) continue;
    // remember current dir position
    uint32_t pos = root.curPosition();
    // format file name
    SdFile::dirName(dir, name);
    if (!playBegin(name)) continue;
    PgmPrintln(", type 's' to skip file 'a' to abort");
    while (wave.isPlaying()) {
      if (Serial.available()) {
        uint8_t c = Serial.read();
        while (Serial.read() >= 0) {}
        if (c == 's' || c == 'a') {
          wave.stop();
          file.close();
          if (c == 'a') return;
        }
      }
    }
    file.close();
    // restore dir position
    root.seekSet(pos);
  }
}
//------------------------------------------------------------------------------
// start file playing
uint8_t playBegin(char* name) {
  if (!file.open(&root, name, O_READ)) {
    PgmPrint("Can't open: ");
    Serial.println(name);
    return false;
  }
  if (!wave.play(&file)) {
    PgmPrint("Can't play: ");
    Serial.println(name);
    file.close();
    return false;
  }
#if PRINT_FILE_INFO
  Serial.print(wave.bitsPerSample, DEC);
  PgmPrint("-bit, ");
  Serial.print(wave.sampleRate/1000);
  PgmPrintln(" kps");
#endif // PRINT_FILE_INFO
#if PRINT_DEBUG_INFO
  if (wave.sdEndPosition > file.fileSize()) {
    PgmPrint("play Size mismatch,");
    Serial.print(file.fileSize());
    Serial.print(',');
    Serial.println(wave.sdEndPosition);
  }
#endif // PRINT_DEBUG_INFO
  PgmPrint("Playing: ");
  Serial.print(name);
  return true;
}
//------------------------------------------------------------------------------
// play a file
void playFile(char* name) {

  if (!playBegin(name)) return;
  PgmPrintln(", type 's' to stop 'p' to pause");
  while (wave.isPlaying()) {
    pauseResume();
  }
  file.close();
#if PRINT_DEBUG_INFO
  if (wave.errors()) {
    PgmPrint("busyErrors: ");
    Serial.println(wave.errors(), DEC);
  }
#endif // PRINT_DEBUG_INFO
}
//-----------------------------------------------------------------------------
void recordManualControl(void) {
  PgmPrintln("Recording - type 's' to stop 'p' to pause");
  uint8_t nl = 0;
  while (wave.isRecording()) {
#if DISPLAY_RECORD_LEVEL > 0
    wave.adcClearRange();
    delay(500);
#if DISPLAY_RECORD_LEVEL > 1
    Serial.print(wave.adcGetMax(), DEC);
    Serial.print(',');
    Serial.println(wave.adcGetMin(), DEC);
#else // #if DISPLAY_RECORD_LEVEL > 1
    Serial.print(wave.adcGetRange(), DEC);
    if (++nl % 8) {
      Serial.print(' ');
    } else {
      Serial.println();
    }
#endif // DISPLAY_RECORD_LEVEL > 1
#endif // DISPLAY_RECORD_LEVEL > 0
    // check for pause/stop
    pauseResume();
  }
}
//-----------------------------------------------------------------------------
#define SAR_TIMEOUT 4
#define SAR_THRESHOLD 40
void recordSoundActivated(void) {
  uint32_t t;
  wave.pause();
  uint8_t n = 0;
  wave.adcClearRange();
  PgmPrintln("Recording - type 's' to stop");
  while (1) {
    if (wave.adcGetRange() >= SAR_THRESHOLD) {
      if (wave.isPaused()) {
        wave.resume();
        Serial.print('r');
        if (++n % 40 == 0) Serial.println();
      }
      t = millis();
      wave.adcClearRange();
    } else if (!wave.isPaused()) {
      if ((millis() - t) > 1000*SAR_TIMEOUT) {
        wave.pause();
        Serial.print('p');
        if (++n % 40 == 0) Serial.println();
      }
    }
    if (Serial.read() == 's') {
      wave.stop();
      return;
    }
  }
}
//------------------------------------------------------------------------------
// scan root directory for track list and recover partial tracks
void scanRoot(void) {
  dir_t dir;
  char name[13];
  listClear();
  root.rewind();
  lastTrack = -1;
  while (root.readDir(&dir) == sizeof(dir)) {
    // only accept TRACKnnn.WAV with nnn < 256
    if (strncmp_P((char *)dir.name, PSTR("TRACK"), 5)) continue;
    if (strncmp_P((char *)&dir.name[8], PSTR("txt"), 3)) continue;
    int16_t n = 0;
    uint8_t i;
    for (i = 5; i < 8 ; i++) {
      char c = (char)dir.name[i];
      if (!isdigit(c)) break;
      n *= 10;
      n += c - '0';
    }
    // nnn must be three digits and less than 256
    if (i != 8 || n > 255) continue;
    if (n > lastTrack) lastTrack = n;
    // mark track found
    listSet(n);
    if (dir.fileSize != MAX_FILE_SIZE) continue;
    // try to recover untrimmed file
    uint32_t pos = root.curPosition();
    if (!trackName(n, name)
      || !file.open(&root, name, O_READ |O_WRITE)
      || !wave.trim(&file)) {
      if (!file.truncate(0)) {
        PgmPrint("Can't trim: ");
        Serial.println(name);
      }
    }
    file.close();
    root.seekSet(pos);
  }
}
//------------------------------------------------------------------------------
// delete all tracks on SD
void trackClear(void) {
  char name[13];
  while (Serial.read() >= 0) {}
  PgmPrintln("Type Y to delete all tracks!");
  while (!Serial.available()) {}
  if (Serial.read() != 'Y') {
    PgmPrintln("Delete all canceled!");
    return;
  }
  for (uint16_t i = 0; i < 256; i++) {
    if (!listGet(i)) continue;
    if (!trackName(i, name)) return;
    if (!SdFile::remove(&root, name)) {
      PgmPrint("Delete failed for: ");
      Serial.println(name);
      return;
    }
  }
  PgmPrintln("Deleted all tracks!");
}
//------------------------------------------------------------------------------
// delete a track
void trackDelete(int16_t track) {
  char name[13];
  if (!trackName(track, name)) return;
  while (Serial.read() >= 0) {}
  PgmPrint("Type y to delete: ");
  Serial.println(name);
  while (!Serial.available()) {}
  if (Serial.read() != 'y') {
    PgmPrintln("Delete canceled!");
    return;
  }
  if (SdFile::remove(&root, name)) {
    PgmPrintln("Deleted!");
  } else {
    PgmPrintln("Delete failed!");
  }
}
//------------------------------------------------------------------------------
// format a track name in 8.3 format
uint8_t trackName(int16_t number, char* name) {
  if (0 <= number && number <= 255) {
    strcpy_P(name, PSTR("TRACK000.txt"));
    name[5] = '0' + number/100;
    name[6] = '0' + (number/10)%10;
    name[7] = '0' + number%10;
    return true;
  }
  PgmPrint("Invalid track number: ");
  Serial.println(number);
  return false;
}
//------------------------------------------------------------------------------
// play a track
void trackPlay(int16_t track) {
  char name[13];
  if (!trackName(track, name)) return;
  playFile(name);
}
//------------------------------------------------------------------------------
// record a track
/*void trackRecord(int16_t track, uint8_t mode) {
  char name[13];
  if (track < 0) track = lastTrack + 1;
  if (!trackName(track , name)) return;
  if (file.open(&root, name, O_READ)) {
    PgmPrint("Track already exists. Use '");
    Serial.print(track);
    Serial.print("d' to delete it.");
    file.close();
    return;
  }
  PgmPrint("Creating: ");
  Serial.println(name);
  if (!file.createContiguous(&root, name, MAX_FILE_SIZE)) {
    PgmPrintln("Create failed");
    return;
  }
  
  
  if(!wave.record(&file, RECORD_RATE, MIC_ANALOG_PIN, ADC_REFERENCE)) {
    PgmPrintln("Record failed");
    file.remove();
    return;
  }
  if (mode == 'v') {
    recordSoundActivated();
  } else {
    recordManualControl();
  }
  // trim unused space from file
  wave.trim(&file);
  file.close();
#if PRINT_DEBUG_INFO
  if (wave.errors() ){
    PgmPrint("busyErrors: ");
    Serial.println(wave.errors(), DEC);
  }
#endif // PRINT_DEBUG_INFO
}*/



//void fileLog(void){
 // Serial.println("log1");
  //if (!file.createContiguous(&root, name, MAX_FILE_SIZE)) {
    //PgmPrintln("Create failed");
    //return;
  //}
//==============================================================================
// Standard Arduino setup() and loop() functions
//------------------------------------------------------------------------------
// setup Serial port and SD card
void setup(void) {
    char stopMode = Serial.println("Hit detected");
  const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
  char fileName[13] = FILE_BASE_NAME "00.CSV";
  Serial.begin(9600);
  //while (!Serial) {} // wait for Leonardo
  delay(1000);
  //delay(10);
  PgmPrint("\nFreeRam: ");
  Serial.println(FreeRam());
  if (!card.init()) error("card.init");
  if (!vol.init(&card)) error("vol.init");
  if (!root.openRoot(&vol)) error("openRoot");
 // nag();*/
  //int sensorReading = analogRead(sensorInput);
  // nag user about power and SD card
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
  
  // Find an unused file name.
  if (BASE_NAME_SIZE > 6) {
    error("FILE_BASE_NAME too long");
  }
  while (sd.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } else {
      error("Can't create file name");
    }
  }
  if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) error("file.open");
  do {
    delay(10);
  } while (Serial.read() >= 0);
  
  Serial.print(F("Logging to: "));
  Serial.println(fileName);
 // Serial.println(F("Type any character to stop"));
  
  // Write data header.
  writeHeader();
  
  // Start on a multiple of the sample interval.
  logTime = micros()/(1000UL*SAMPLE_INTERVAL_MS) + 1;
  logTime *= 1000UL*SAMPLE_INTERVAL_MS;
}

//------------------------------------------------------------------------------
// loop to play and record files.
void loop() {
 if (file.isOpen()) file.close();
 int sensorReading = analogRead(sensorInput);
 if (sensorReading > 100){
   char stopMode;
    Serial.println(FreeRam());
    playFile("case1.wav");
    delay(1000);
  }delay(1000);
 
  
 logTime += 1000UL*SAMPLE_INTERVAL_MS;
 

/*if (!stopMode)
 {
   Serial.println("It works?");
   logData();
 }*/
 
 // Wait for log time.
  int32_t diff;
  do {
    diff = micros() - logTime;
  } while (diff < 0);
  
  // Check for data rate too high. 
  if (diff > 10) error("Missed data record");
  
  //logData();
  
  // Force data to SD and update the directory entry to avoid data loss.
  if (!file.sync() || file.getWriteError()) error("write error"); 
  
  if (Serial.available()) {
    // Close file and stop.
    file.close();
    Serial.println(F("Done"));
    while(1) {}
  } 
  
  //Serial.println(sensorReading);
  //delay(1000);
}
 
  
 

User avatar
Coldsoldier
 
Posts: 6
Joined: Wed Sep 17, 2014 5:44 pm

Re: DATALOGGING ON WAVESHIELD CODE HELP

Post by Coldsoldier »

I also redid the programming with the dataLogger as the base to see if I could solve it. I was able to log data into the SD card but I could not play any of the wav files.
This code is shorter and easier to understand. How should I go about pausing my data logging to play my wav files? I've been beating my head trying to figure this out. Thank you.

Code: Select all

/*
 * Simple data logger.
 */
#include <SdFat.h>
#include <WaveRP.h>
#include <SdFatUtil.h>
#include <ctype.h>
// SD chip select pin.  Be sure to disable any other SPI devices such as Enet.
const uint8_t chipSelect = SS;
// print file info - useful for debug
#define PRINT_FILE_INFO 0
//
// print bad wave file size and SD busy errors for debug
#define PRINT_DEBUG_INFO 1
// Interval between data records in milliseconds. 
// The interval must be greater than the maximum SD write latency plus the
// time to acquire and write data to the SD to avoid overrun errors.
// Run the bench example to check the quality of your SD card.
const uint32_t SAMPLE_INTERVAL_MS = 200;
int sensorInput = A0;
// Log file base name.  Must be six characters or less.
#define FILE_BASE_NAME "DATA"
//------------------------------------------------------------------------------
//Global variables
Sd2Card card;           // SD/SDHC card with support for version 2.00 features
SdVolume vol;           // FAT16 or FAT32 volume
SdFile root;            // volume's root directory            // current file
WaveRP wave;            // wave file recorder/player
int16_t lastTrack = -1; // Highest track number
uint8_t trackList[32];
int sensorReading = analogRead(sensorInput);
//------------------------------------------------------------------------------
// File system object.
SdFat sd;

// Log file.
SdFile file;

// Time in micros for next data record.
uint32_t logTime;

//==============================================================================
// User functions.  Edit writeHeader() and logData() for your requirements.

const uint8_t ANALOG_COUNT = 4;


// print error message and halt
void error(char* str) {
  PgmPrint("error: ");
  Serial.println(str);
  if (card.errorCode()) {
    PgmPrint("sdError: ");
    Serial.println(card.errorCode(), HEX);
    PgmPrint("sdData: ");
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}
//------------------------------------------------------------------------------
// Write data header.
void writeHeader() {
  file.print(F("micros"));
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.print(F(",adc"));
    file.print(i, DEC);
  }
  file.println();
}
//------------------------------------------------------------------------------
// start file playing
uint8_t playBegin(char* name) {
  if (!file.open(&root, name, O_READ)) {
    PgmPrint("Can't open: ");
    Serial.println(name);
    return false;
  }
  if (!wave.play(&file)) {
    PgmPrint("Can't play: ");
    Serial.println(name);
    file.close();
    return false;
  }
#if PRINT_FILE_INFO
  Serial.print(wave.bitsPerSample, DEC);
  PgmPrint("-bit, ");
  Serial.print(wave.sampleRate/1000);
  PgmPrintln(" kps");
#endif // PRINT_FILE_INFO
#if PRINT_DEBUG_INFO
  if (wave.sdEndPosition > file.fileSize()) {
    PgmPrint("play Size mismatch,");
    Serial.print(file.fileSize());
    Serial.print(',');
    Serial.println(wave.sdEndPosition);
  }
#endif // PRINT_DEBUG_INFO
  PgmPrint("Playing: ");
  Serial.print(name);
  return true;
}
//------------------------------------------------------------------------------
// check for pause resume
void pauseResume(void) {
  if (!Serial.available()) return;
  uint8_t c = Serial.read();
  while (Serial.read() >= 0) {}
  if (c == 's') {
    wave.stop();
  } else if (c == 'p') {
    wave.pause();
    while (wave.isPaused()) {
      PgmPrintln("\nPaused - type 's' to stop 'r' to resume");
      while (!Serial.available()) {}
      c = Serial.read();
      if (c == 's') wave.stop();
      if (c == 'r') wave.resume();
    }
  }
}
//------------------------------------------------------------------------------ 
//play a file
void playFile(char* name) {

  if (!playBegin(name)) return;
  PgmPrintln(", type 's' to stop 'p' to pause");
  while (wave.isPlaying()) {
    pauseResume();
  }
  file.close();
#if PRINT_DEBUG_INFO
  if (wave.errors()) {
    PgmPrint("busyErrors: ");
    Serial.println(wave.errors(), DEC);
  }
#endif // PRINT_DEBUG_INFO
}
//-------------------------------------------------------------------------------

// Log a data record.
void logData() {
  uint16_t data[ANALOG_COUNT];
  
  // Read all channels to avoid SD write latency between readings.
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    data[i] = analogRead(i);
  }
  // Write data to file.  Start with log time in micros.
  file.print(logTime);
  
  // Write ADC data to CSV record.
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.write(',');
    file.print(data[i]);
  }
  file.println();
}
//==============================================================================
// Error messages stored in flash.
#define error(msg) error_P(PSTR(msg))
//------------------------------------------------------------------------------
void error_P(const char* msg) {
  sd.errorHalt_P(msg);
}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  while (!Serial) {} // wait for Leonardo
  delay(1000);
  PgmPrint("\nFreeRam: ");
  Serial.println(FreeRam());
  if (!card.init()) error("card.init");
  if (!vol.init(&card)) error("vol.init");
  if (!root.openRoot(&vol)) error("openRoot");
  
  //Serial.println(F("Type any character to start"));
  //while (!Serial.available()) {}
  const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
  char fileName[13] = FILE_BASE_NAME "00.CSV";
  // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
  
  // Find an unused file name.
  if (BASE_NAME_SIZE > 6) {
    error("FILE_BASE_NAME too long");
  }
  while (sd.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } else {
      error("Can't create file name");
    }
  }
  if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) error("file.open");
  do {
    delay(10);
  } while (Serial.read() >= 0);
  
  Serial.print(F("Logging to: "));
  Serial.println(fileName);
 // Serial.println(F("Type any character to stop"));
  
  // Write data header.
  writeHeader();
  
  // Start on a multiple of the sample interval.
  logTime = micros()/(1000UL*SAMPLE_INTERVAL_MS) + 1;
  logTime *= 1000UL*SAMPLE_INTERVAL_MS;
}
//------------------------------------------------------------------------------
void loop() {
   
  //playFile("case1.wav"); // for testing wav player. Commented out due to the program not working 
   //delay(2000);              // uncomment to test. 
   
  // Time for next record.
  logTime += 1000UL*SAMPLE_INTERVAL_MS;
  
  // Wait for log time.
  int32_t diff;
  do {
    diff = micros() - logTime;
  } while (diff < 0);
  
  // Check for data rate too high. 
  if (diff > 10) error("Missed data record");
  
 
  
  logData();
  
  // Force data to SD and update the directory entry to avoid data loss.
  if (!file.sync() || file.getWriteError()) error("write error"); 
  
  if (Serial.available()) {
    // Close file and stop.
    file.close();
    Serial.println(F("Done"));
    while(1) {}
  }
 
   
}

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

Return to “Arduino Shields from Adafruit”