Shop

My New Shop
MTS Creations

Subscribe to My YouTube Channel

Friday, May 11, 2012

Crystal Reports Error

If you try to insert a subreport and you get the following error:
"com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: Unexpected database connector error---- Error code:-2147467259 Error code name:failed"
It means that you need to rename your "Subreport Name".

To do this go to your main report and right click on the subreport, select "Format Subreport...", select the Subreport tab at the top, update the "Subreport Name:" to match your java PojoDataset tablename.

I sure wish that would have been somewhere that I could have read.

Thursday, May 10, 2012

My First Arduino Project: DoorTunes

My first Arduino project!
My "DoorTunes" (AKA: MP3 Doorbell)

Hardware:
Arduino Uno
Audio Shield (v1.1) "Wave Shield"


/*
 * This plays one .WAV file from the SD card by index when the doorbell is pressed
 */
#include 
#include 

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 represents the WAV file
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time
uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
dir_t dirBuf;     // buffer for directory reads

const int numberOfTunes = 14;

// See sketch (openByIndex) example
uint16_t tunesIndex[numberOfTunes]; // Number of Tune files.

/*
 * Define macro to put error messages in flash memory
 */
#define error(msg) error_P(PSTR(msg))

// Function definitions (we define them here, but the code is below)
void play(FatReader &dir);
void findFiles(FatReader &dir);
const int doorBellPin = 7; // Analog pin for doorbell
int doorBellState = 0;
long randNumber, lastNumber;

//////////////////////////////////// SETUP
void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps for debugging
  
  putstring_nl("\nRunning Setup!");  // say we woke up!
  
  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(FreeRam());

  // 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(doorBellPin, INPUT);

  //  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!)  
    error("Card init. failed!");  // Something went wrong, lets print out why
  }
  
  // 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  :(
    error("No valid FAT partition!");  // Something went wrong, lets print out why
  }
  
  // Lets tell the user about what we found
  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)) {
    error("Can't open root dir!");      // Something went wrong,
  }
  
  // Whew! We got past the tough parts.
  putstring_nl("Files found (* = fragmented):");

  // Print out all of the files in all the directories.
  root.ls(LS_R | LS_FLAG_FRAGMENTED);

  putstring("\nCalling findFiles()");
  root.rewind();
  findFiles(root);
  putstring("\nDONE WITH SETUP");
}

//////////////////////////////////// LOOP
void loop() {
  doorBellState = digitalRead(doorBellPin);
  if(doorBellState == HIGH) {
    putstring("\nDOORBELL is Pressed!\n");
    // print a random number from 0 to NumberOfTunes
    randNumber = random(numberOfTunes);
    while(randNumber == lastNumber) {
      Serial.println("Dude, we already heard that song! Pick something original");
      randNumber = random(numberOfTunes);
    }
    lastNumber = randNumber;
    
    putstring("\nRandom Number: ");
    Serial.println(randNumber);
    // Try to open the root directory
    if (!root.openRoot(vol)) {
      error("Can't open root dir!");      // Something went wrong,
    }
    Serial.println(tunesIndex[randNumber]);
    // open by index
    if (!file.open(root, tunesIndex[randNumber])) {
      error("open by index");
    }
    
    // create and play Wave
    if (!wave.create(file))
      error("wave.create");
    wave.play();
    uint8_t n = 0;
    while (wave.isplaying) {// playing occurs in interrupts, so we print dots in realtime
      // I also use this to keep it from trying to play more than one file while the doorbell is pressed.
      putstring(".");
      if (!(++n % 32))Serial.println();
      delay(300);
    }           
  }
}

/////////////////////////////////// HELPERS
/*
 * 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, great for debugging!
 */
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);
}

/*
 * Find all the tunes - possible stack overflow if subdirectories too nested
 */
void findFiles(FatReader &dir) {
  putstring("\nRunning findFiles()");
  FatReader file;
  int tunesCounter = 0;
  while (dir.readDir(dirBuf) > 0) {    // Read every file in the directory one at a time
  
    // Skip it if not a subdirectory and not a .WAV file
    if (!DIR_IS_SUBDIR(dirBuf)
         && strncmp_P((char *)&dirBuf.name[8], PSTR("WAV"), 3)) {
      putstring("\nfindFiles() Not a wav or subdir.");
      continue;
    }

    Serial.println();            // clear out a new line
    
    for (uint8_t i = 0; i < dirLevel; i++) {
       Serial.write(' ');       // this is for prettyprinting, put spaces in front
    }
    if (!file.open(vol, dirBuf)) {        // open the file in the directory
      error("file.open failed");          // something went wrong
    }
    
    if(file.isDir()) {
      putstring("Subdir: ");
      printEntryName(dirBuf);
      // recursive call to findFiles(file);
    }
    else {
      // Add the file to the tunes[]
      // Aha! we found a file that isnt a directory
      putstring("Adding file: ");
      printEntryName(dirBuf);              // print it out
      if (!wave.create(file)) {            // Figure out, is it a WAV proper?
        putstring(" Not a valid WAV");     // ok skip it
      } else {
        Serial.println();                  // Hooray it IS a WAV proper!
        putstring("tunesCounter: ");
        Serial.println(tunesCounter);

        // Save file's index (byte offset of directory entry divided by entry size)
        // Current position is just after entry so subtract one.
        tunesIndex[tunesCounter] = root.readPosition()/32 - 1;  
        tunesCounter++;

        sdErrorCheck();                    // everything OK?
      }
    }
  }
  putstring("\nDONE Running findFiles()");
}