Can Soundboard be triggered by remote XBee?

XBee projects like the adapter, xBee tutorials, tweetawatt/wattcher, etc. from Adafruit

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Can Soundboard be triggered by remote XBee?

Post by GrampaF »

The Soundboard with "menu commands" up and working fine. Two XBees communicating fine (from 6" away from each other). How get a soundboard action from sending something from the TX XBee?

I'd like to trigger a sound file playing not by entering something in the monitor or pushing a button, but by having a Transmitting XBee send something to a Receiving XBee. The Receiving XBee is on an XBee shield, on an Arduino, which is connected to the Soundboard.

I have the "Remote Control" file working on the Receiving XBee and can trigger led pins to light up on the Receiving XBee board by sending a "packet" from the Transmitting XBee. So I know the RX XBee is getting stuff fine from the TX XBee.

I have meshed the two files together and things still work. But if I send "L\n" from the TX XBee to the RX XBee, nothing happens on the serial monitor of the RX Arduino or the Soundboard.

Help greatly appreciated.

-Peter

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Can Soundboard be triggered by remote XBee?

Post by adafruit_support_rick »

Can you post your sketch?

User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

Thanks for the interest!

Oh, and the (Sparkfun) XBee shields (both XBees are mounted on shields on Arduinos) have a physical switch on them to either set it to UART or DLine. As per the "Remote Control" sketch, both are set to "DLine".

Here's the code:

Code: Select all


// PLEASE NOTE I HAVE TRIED TO "MARK" CERTAIN PARTS FROM ANOTHER SKETCH THAT DOES WORK TO CONTROL A SERVO BY MEANS OF A TX-XBEE SENDING COMMANDS 
// TO AN RX-XBEE, TRIGGERING A SERVO ON THE RECEIVING END

/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/
/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/




/* 
  Menu driven control of a sound board over UART.
  Commands for playing by # or by name (full 11-char name)
  Hard reset and List files (when not playing audio)
  Vol + and - (only when not playing audio)
  Pause, unpause, quit playing (when playing audio)
  Current play time, and bytes remaining & total bytes (when playing audio)

  Connect UG to ground to have the sound board boot into UART mode
*/

#include <SoftwareSerial.h>

/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/
                      SoftwareSerial XBee(2, 3); // Arduino RX, TX (XBee Dout, Din)
                      #include<Servo.h>
                      Servo release;

/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/

#include "Adafruit_Soundboard.h"


// Choose any two pins that can be used with SoftwareSerial to RX & TX
#define SFX_TX 5
#define SFX_RX 6

// Connect to the RST pin on the Sound Board
#define SFX_RST 4

// You can also monitor the ACT pin for when audio is playing!

// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);

// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third 
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

void setup() {
  Serial.begin(9600);
  Serial.println("Adafruit Sound Board!");
  
  // softwareserial at 9600 baud
  ss.begin(9600);
  // can also do Serial1.begin(9600)

  if (!sfx.reset()) {
    Serial.println("Not found");
    while (1);
  }
  Serial.println("SFX board found");

/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/


printMenu(); // Print a helpful menu:

int led = 13;
int val;

/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/

}


void loop() {
  flushInput();
  
  Serial.println(F("What would you like to do?"));
  Serial.println(F("[r] - reset"));
  Serial.println(F("[+] - Vol +"));
  Serial.println(F("[-] - Vol -"));
  Serial.println(F("[L] - List files"));
  Serial.println(F("[P] - play by file name"));
  Serial.println(F("[#] - play by file number"));
  Serial.println(F("[=] - pause playing"));
  Serial.println(F("[>] - unpause playing"));
  Serial.println(F("[q] - stop playing"));
  Serial.println(F("[t] - playtime status"));
  Serial.println(F("> "));
  
  while (!Serial.available());
  char cmd = Serial.read();
  
  flushInput();
  
  switch (cmd) {
    case 'r': {
      if (!sfx.reset()) {
        Serial.println("Reset failed");
      }
      break; 
    }
    
    case 'L': {
      uint8_t files = sfx.listFiles();
    
      Serial.println("File Listing");
      Serial.println("========================");
      Serial.println();
      Serial.print("Found "); Serial.print(files); Serial.println(" Files");
      for (uint8_t f=0; f<files; f++) {
        Serial.print(f); 
        Serial.print("\tname: "); Serial.print(sfx.fileName(f));
        Serial.print("\tsize: "); Serial.println(sfx.fileSize(f));
      }
      Serial.println("========================");
      break; 
    }
    
    case '#': {
      Serial.print("Enter track #");
      uint8_t n = readnumber();

      Serial.print("\nPlaying track #"); Serial.println(n);
      if (! sfx.playTrack(n) ) {
        Serial.println("Failed to play track?");
      }
      break;
    }
    
    case 'P': {
      Serial.print("Enter track name (full 12 character name!) >");
      char name[20];
      readline(name, 20);

      Serial.print("\nPlaying track \""); Serial.print(name); Serial.print("\"");
      if (! sfx.playTrack(name) ) {
        Serial.println("Failed to play track?");
      }
      break;
   }

   case '+': {
      Serial.println("Vol up...");
      uint16_t v;
      if (! (v = sfx.volUp()) ) {
        Serial.println("Failed to adjust");
      } else {
        Serial.print("Volume: "); Serial.println(v);
      }
      break;
   }

   case '-': {
      Serial.println("Vol down...");
      uint16_t v;
      if (! (v=sfx.volDown()) ) {
        Serial.println("Failed to adjust");
      } else { 
        Serial.print("Volume: "); 
        Serial.println(v);
      }
      break;
   }
   
   case '=': {
      Serial.println("Pausing...");
      if (! sfx.pause() ) Serial.println("Failed to pause");
      break;
   }
   
   case '>': {
      Serial.println("Unpausing...");
      if (! sfx.unpause() ) Serial.println("Failed to unpause");
      break;
   }
   
   case 'q': {
      Serial.println("Stopping...");
      if (! sfx.stop() ) Serial.println("Failed to stop");
      break;
   }  

   case 't': {
      Serial.print("Track time: ");
      uint32_t current, total;
      if (! sfx.trackTime(&current, &total) ) Serial.println("Failed to query");
      Serial.print(current); Serial.println(" seconds");
      break;
   }  

   case 's': {
      Serial.print("Track size (bytes remaining/total): ");
      uint32_t remain, total;
      if (! sfx.trackSize(&remain, &total) ) 
        Serial.println("Failed to query");
      Serial.print(remain); Serial.print("/"); Serial.println(total); 
      break;
   }  

  }








/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/

// In loop() we continously check to see if a command has been
  //  received.
  if (XBee.available())
  {
    char c = XBee.read();
    switch (c)
    {
    case 'w':      // If received 'w'
    case 'W':      // or 'W'
      writeAPin(); // Write analog pin
      break;
    case 'd':      // If received 'd'
    case 'D':      // or 'D'
      writeDPin(); // Write digital pin
      break;
    case 'r':      // If received 'r'
    case 'R':      // or 'R'
      readDPin();  // Read digital pin
      break;
    case 'a':      // If received 'a'
    case 'A':      // or 'A'
      readAPin();  // Read analog pin
      break;
    }
  }

/******  END OF PART FROM THE "REMOTE CONTROL" SKETCH **********/






//   end of "loop" follows below......   

}









/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/




// Write Digital Pin
// Send a 'd' or 'D' to enter.
// Then send a pin #
//   Use numbers for 0-9, and hex (a, b, c, or d) for 10-13
// Then send a value for high or low
//   Use h, H, or 1 for HIGH. Use l, L, or 0 for LOW
void writeDPin()
{
  while (XBee.available() < 2)
    ; // Wait for pin and value to become available
  char pin = XBee.read();
  char hl = ASCIItoHL(XBee.read());

  // Print a message to let the control know of our intentions:
  XBee.print("Setting pin ");
  XBee.print(pin);
  XBee.print(" to ");
  XBee.println(hl ? "HIGH" : "LOW");

  pin = ASCIItoInt(pin); // Convert ASCCI to a 0-13 value
  pinMode(pin, OUTPUT); // Set pin as an OUTPUT
  digitalWrite(pin, hl); // Write pin accordingly


int led = 13;
int val;      

val = digitalRead(8);
//      val2 = digitalRead(8);

  
if(val==LOW)  //if we send a LOW command to pin 8
  {
  release.attach(9); 
  release.write(12);
  delay(1000);
  //release.write(12);
 // delay(1000);
  release.detach();
//  digitalWrite(led, HIGH);
  }
if(val==HIGH)  //if we send a HIGH command to pin 8
  {
  release.attach(9); 
  release.write(12);
  delay(2000);
 release.write(170);
 delay(1000);
  release.detach();

  }

  digitalWrite(8, LOW);







  
}

// Write Analog Pin
// Send 'w' or 'W' to enter
// Then send a pin #
//   Use numbers for 0-9, and hex (a, b, c, or d) for 10-13
//   (it's not smart enough (but it could be) to error on
//    a non-analog output pin)
// Then send a 3-digit analog value.
//   Must send all 3 digits, so use leading zeros if necessary.
void writeAPin()
{
  while (XBee.available() < 4)
    ; // Wait for pin and three value numbers to be received
  char pin = XBee.read(); // Read in the pin number
  int value = ASCIItoInt(XBee.read()) * 100; // Convert next three
  value += ASCIItoInt(XBee.read()) * 10;     // chars to a 3-digit
  value += ASCIItoInt(XBee.read());          // number.
  value = constrain(value, 0, 255); // Constrain that number.

  // Print a message to let the control know of our intentions:
  XBee.print("Setting pin ");
  XBee.print(pin);
  XBee.print(" to ");
  XBee.println(value);

  pin = ASCIItoInt(pin); // Convert ASCCI to a 0-13 value
  pinMode(pin, OUTPUT); // Set pin as an OUTPUT
  analogWrite(pin, value); // Write pin accordingly
}

// Read Digital Pin
// Send 'r' or 'R' to enter
// Then send a digital pin # to be read
// The Arduino will print the digital reading of the pin to XBee.
void readDPin()
{
  while (XBee.available() < 1)
    ; // Wait for pin # to be available.
  char pin = XBee.read(); // Read in the pin value

  // Print beggining of message
  XBee.print("Pin ");
  XBee.print(pin);

  pin = ASCIItoInt(pin); // Convert pin to 0-13 value
  pinMode(pin, INPUT); // Set as input
  // Print the rest of the message:
  XBee.print(" = "); 
  XBee.println(digitalRead(pin));
}

// Read Analog Pin
// Send 'a' or 'A' to enter
// Then send an analog pin # to be read.
// The Arduino will print the analog reading of the pin to XBee.
void readAPin()
{
  while (XBee.available() < 1)
    ; // Wait for pin # to be available
  char pin = XBee.read(); // read in the pin value

  // Print beginning of message
  XBee.print("Pin A");
  XBee.print(pin);

  pin = ASCIItoInt(pin); // Convert pin to 0-6 value
  // Printthe rest of the message:
  XBee.print(" = ");
  XBee.println(analogRead(pin));
}

// ASCIItoHL
// Helper function to turn an ASCII value into either HIGH or LOW
int ASCIItoHL(char c)
{
  // If received 0, byte value 0, L, or l: return LOW
  // If received 1, byte value 1, H, or h: return HIGH
  if ((c == '0') || (c == 0) || (c == 'L') || (c == 'l'))
    return LOW;
  else if ((c == '1') || (c == 1) || (c == 'H') || (c == 'h'))
    return HIGH;
  else
    return -1;
}

// ASCIItoInt
// Helper function to turn an ASCII hex value into a 0-15 byte val
int ASCIItoInt(char c)
{
  if ((c >= '0') && (c <= '9'))
    return c - 0x30; // Minus 0x30
  else if ((c >= 'A') && (c <= 'F'))
    return c - 0x37; // Minus 0x41 plus 0x0A
  else if ((c >= 'a') && (c <= 'f'))
    return c - 0x57; // Minus 0x61 plus 0x0A
  else
    return -1;
}


/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/







/************************ MENU HELPERS ***************************/

void flushInput() {
  // Read all available serial input to flush pending data.
  uint16_t timeoutloop = 0;
  while (timeoutloop++ < 40) {
    while(ss.available()) {
      ss.read();
      timeoutloop = 0;  // If char was received reset the timer
    }
    delay(1);
  }
}

char readBlocking() {
  while (!Serial.available());
  return Serial.read();
}

uint16_t readnumber() {
  uint16_t x = 0;
  char c;
  while (! isdigit(c = readBlocking())) {
    //Serial.print(c);
  }
  Serial.print(c);
  x = c - '0';
  while (isdigit(c = readBlocking())) {
    Serial.print(c);
    x *= 10;
    x += c - '0';
  }
  return x;
}

uint8_t readline(char *buff, uint8_t maxbuff) {
  uint16_t buffidx = 0;
  
  while (true) {
    if (buffidx > maxbuff) {
      break;
    }

    if (Serial.available()) {
      char c =  Serial.read();
      //Serial.print(c, HEX); Serial.print("#"); Serial.println(c);

      if (c == '\r') continue;
      if (c == 0xA) {
        if (buffidx == 0) {  // the first 0x0A is ignored
          continue;
        }
        buff[buffidx] = 0;  // null term
        return buffidx;
      }
      buff[buffidx] = c;
      buffidx++;
    }
  }
  buff[buffidx] = 0;  // null term
  return buffidx;
}
/************************ MENU HELPERS ***************************/




















// printMenu
// A big ol' string of Serial prints that print a usage menu over
// to the other XBee.
void printMenu()
{
  // Everything is "F()"'d -- which stores the strings in flash.
  // That'll free up SRAM for more importanat stuff.
  XBee.println();
  XBee.println(F("Arduino XBee Remote Control!"));
  XBee.println(F("============================"));
  XBee.println(F("Usage: "));
  XBee.println(F("w#nnn - analog WRITE pin # to nnn"));
  XBee.println(F("  e.g. w6088 - write pin 6 to 88"));
  XBee.println(F("d#v   - digital WRITE pin # to v"));
  XBee.println(F("  e.g. ddh - Write pin 13 High"));
  XBee.println(F("r#    - digital READ digital pin #"));
  XBee.println(F("  e.g. r3 - Digital read pin 3"));
  XBee.println(F("a#    - analog READ analog pin #"));
  XBee.println(F("  e.g. a0 - Read analog pin 0"));
  XBee.println();
  XBee.println(F("- Use hex values for pins 10-13"));
  XBee.println(F("- Upper or lowercase works"));
  XBee.println(F("- Use 0, l, or L to write LOW"));
  XBee.println(F("- Use 1, h, or H to write HIGH"));
  XBee.println(F("============================"));  
  XBee.println();

}





User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Can Soundboard be triggered by remote XBee?

Post by adafruit_support_rick »

Two things:
Thing 1: You're not calling XBee.begin in setup()
Thing 2: Software Serial can only listen to one connection at a time. You have to manually switch between which software serial port you're listening to. Ise the listen function to make sure you're listening to the XBee port.
https://www.arduino.cc/en/Reference/Sof ... rialListen

User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

Thanks for the reading of the code and the advice.

I've (sort of) diagrammed the situation now that I have read-up on Software.Serial, creating two software 'ports' and 'listen'.

The diagram and question are below:
Attachments
Here is the set-up and question..  All advice appreciated..
Here is the set-up and question.. All advice appreciated..
Image for communication question.png (251.45 KiB) Viewed 814 times

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Can Soundboard be triggered by remote XBee?

Post by adafruit_support_rick »

So, the thing to remember is that serial data is asynchronous. That means it can appear at any time, not just when you're listening for it.
In your case, the commands from the XBee can appear at any time. However, the data from the sound board will only appear right after you ask for it. In that sense, the soundboard data is synchronous. And that's what will allow this to work.

It's not entirely clear to me, but I think what you want to do is to rewrite the code you posted (i.e., the receive side) so that the soundboard commands come from the XBee and not from Serial. Is that right?

You are also getting commands to read and write pins from the XBee. So, you will get pin commands and sound commands from the XBee?

User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

Yes, trying to get from the TX-XBee commands that trigger a servo position change (e.g. "when pin 8 is "HIGH", move servo from position 0 to position 180, delay 5 seconds, then move the servo position back to 0") and use perhaps 6 other pins for commands to play one or another of 6 sound files (code that says " when pin 7 is HIGH, play sound file 07.ogg" then make pin 7 "LOW")

(I didn't think I could use all 10 pins because they are needed for the servo(pin 8), and for listening for commands from the RX-XBee(pins 2 and 3?) leaving one spare).

So, if it's all coming from the same TX-XBee, I guess I don't need to go the 2-ports route. But I enjoyed learning about it!

Well, yes that is what I am trying to do, but am a bit lost about how to do it...

Trying.

Advice or suggestions continue to be welcomed. It is too nice a day here in CT to spend it all inside on trial and error...:)


Thanks.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Can Soundboard be triggered by remote XBee?

Post by adafruit_support_rick »

So, what you want to do is to always listen to XBee, except when you do a soundboard command. You also want to combine your soundboard and Xbee switch statements into a single switch. I modified your code to do that. One problem is that both the soundboard and pin I/O switches used the case 'r'. To fix that, I eliminated all of the lower-case commands for the pin I/O.

I also modified the readBlocking, readNumber, and readLine functions so that they don't read from Serial anymore. I added an argument so that they will read from whatever serial stream you pass in.

This ought to be enough to get you started.

Code: Select all

// PLEASE NOTE I HAVE TRIED TO "MARK" CERTAIN PARTS FROM ANOTHER SKETCH THAT DOES WORK TO CONTROL A SERVO BY MEANS OF A TX-XBEE SENDING COMMANDS
// TO AN RX-XBEE, TRIGGERING A SERVO ON THE RECEIVING END

/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/
/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/




/*
  Menu driven control of a sound board over UART.
  Commands for playing by # or by name (full 11-char name)
  Hard reset and List files (when not playing audio)
  Vol + and - (only when not playing audio)
  Pause, unpause, quit playing (when playing audio)
  Current play time, and bytes remaining & total bytes (when playing audio)

  Connect UG to ground to have the sound board boot into UART mode
*/

#include <SoftwareSerial.h>

/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/
SoftwareSerial XBee(2, 3); // Arduino RX, TX (XBee Dout, Din)
#include<Servo.h>
Servo release;

/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/

#include "Adafruit_Soundboard.h"


// Choose any two pins that can be used with SoftwareSerial to RX & TX
#define SFX_TX 5
#define SFX_RX 6

// Connect to the RST pin on the Sound Board
#define SFX_RST 4

// You can also monitor the ACT pin for when audio is playing!

// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);

// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

void setup() {
  Serial.begin(9600);
  Serial.println("Adafruit Sound Board!");

  // softwareserial at 9600 baud
  ss.begin(9600);
  // can also do Serial1.begin(9600)

  if (!sfx.reset()) {
    Serial.println("Not found");
    while (1);
  }
  Serial.println("SFX board found");

  XBee.begin(9600);
  XBee.listen();

  printMenu(); // Print a helpful menu:


}


void loop() {
  if (XBee.available())
  {
    char cmd = XBee.read();

    switch (cmd) {
      //servo commands
//      case 'w':      // If received 'w'
      case 'W':      // or 'W'
        writeAPin(); // Write analog pin
        break;

//      case 'd':      // If received 'd'
      case 'D':      // or 'D'
        writeDPin(); // Write digital pin
        break;

//      case 'r':      // If received 'r'
      case 'R':      // or 'R'
        readDPin();  // Read digital pin
        break;

//      case 'a':      // If received 'a'
      case 'A':      // or 'A'
        readAPin();  // Read analog pin
        break;

      case 'r': {
          ss.listen();  //switch to soundboard
          if (!sfx.reset()) {
            Serial.println("Reset failed");
          }
          break;
        }

      case 'L': {
          ss.listen();  //switch to soundboard
          uint8_t files = sfx.listFiles();

          Serial.println("File Listing");
          Serial.println("========================");
          Serial.println();
          Serial.print("Found "); Serial.print(files); Serial.println(" Files");
          for (uint8_t f = 0; f < files; f++) {
            Serial.print(f);
            Serial.print("\tname: "); Serial.print(sfx.fileName(f));
            Serial.print("\tsize: "); Serial.println(sfx.fileSize(f));
          }
          Serial.println("========================");
          break;
        }

      case '#': {
          Serial.print("Enter track #");
          uint8_t n = readnumber(&ss);

          Serial.print("\nPlaying track #"); Serial.println(n);
          ss.listen();  //switch to soundboard
          if (! sfx.playTrack(n) ) {
            Serial.println("Failed to play track?");
          }
          break;
        }

      case 'P': {
          Serial.print("Enter track name (full 12 character name!) >");
          char name[20];
          readline(&ss,name, 20);

          Serial.print("\nPlaying track \""); Serial.print(name); Serial.print("\"");
          ss.listen();  //switch to soundboard
          if (! sfx.playTrack(name) ) {
            Serial.println("Failed to play track?");
          }
          break;
        }

      case '+': {
          Serial.println("Vol up...");
          uint16_t v;
          ss.listen();  //switch to soundboard
          if (! (v = sfx.volUp()) ) {
            Serial.println("Failed to adjust");
          } else {
            Serial.print("Volume: "); Serial.println(v);
          }
          break;
        }

      case '-': {
          Serial.println("Vol down...");
          uint16_t v;
          ss.listen();  //switch to soundboard
          if (! (v = sfx.volDown()) ) {
            Serial.println("Failed to adjust");
          } else {
            Serial.print("Volume: ");
            Serial.println(v);
          }
          break;
        }

      case '=': {
          Serial.println("Pausing...");
          ss.listen();  //switch to soundboard
          if (! sfx.pause() ) Serial.println("Failed to pause");
          break;
        }

      case '>': {
          Serial.println("Unpausing...");
          ss.listen();  //switch to soundboard
          if (! sfx.unpause() ) Serial.println("Failed to unpause");
          break;
        }

      case 'q': {
          Serial.println("Stopping...");
          ss.listen();  //switch to soundboard
          if (! sfx.stop() ) Serial.println("Failed to stop");
          break;
        }

      case 't': {
          Serial.print("Track time: ");
          uint32_t current, total;
          ss.listen();  //switch to soundboard
          if (! sfx.trackTime(&current, &total) ) Serial.println("Failed to query");
          Serial.print(current); Serial.println(" seconds");
          break;
        }

      case 's': {
          Serial.print("Track size (bytes remaining/total): ");
          uint32_t remain, total;
          ss.listen();  //switch to soundboard
          if (! sfx.trackSize(&remain, &total) )
            Serial.println("Failed to query");
          Serial.print(remain); Serial.print("/"); Serial.println(total);
          break;
        default:
          break;
        }
    }
    XBee.listen();
  } //end if (XBee.available();

}    //   end of "loop"









/******  THIS PART IS FROM THE "REMOTE CONTROL" SKETCH **********/




// Write Digital Pin
// Send a 'd' or 'D' to enter.
// Then send a pin #
//   Use numbers for 0-9, and hex (a, b, c, or d) for 10-13
// Then send a value for high or low
//   Use h, H, or 1 for HIGH. Use l, L, or 0 for LOW
void writeDPin()
{
  while (XBee.available() < 2)
    ; // Wait for pin and value to become available
  char pin = XBee.read();
  char hl = ASCIItoHL(XBee.read());

  // Print a message to let the control know of our intentions:
  XBee.print("Setting pin ");
  XBee.print(pin);
  XBee.print(" to ");
  XBee.println(hl ? "HIGH" : "LOW");

  pin = ASCIItoInt(pin); // Convert ASCCI to a 0-13 value
  pinMode(pin, OUTPUT); // Set pin as an OUTPUT
  digitalWrite(pin, hl); // Write pin accordingly


  int led = 13;
  int val;

  val = digitalRead(8);
  //      val2 = digitalRead(8);


  if (val == LOW) //if we send a LOW command to pin 8
  {
    release.attach(9);
    release.write(12);
    delay(1000);
    //release.write(12);
    // delay(1000);
    release.detach();
    //  digitalWrite(led, HIGH);
  }
  if (val == HIGH) //if we send a HIGH command to pin 8
  {
    release.attach(9);
    release.write(12);
    delay(2000);
    release.write(170);
    delay(1000);
    release.detach();

  }

  digitalWrite(8, LOW);








}

// Write Analog Pin
// Send 'w' or 'W' to enter
// Then send a pin #
//   Use numbers for 0-9, and hex (a, b, c, or d) for 10-13
//   (it's not smart enough (but it could be) to error on
//    a non-analog output pin)
// Then send a 3-digit analog value.
//   Must send all 3 digits, so use leading zeros if necessary.
void writeAPin()
{
  while (XBee.available() < 4)
    ; // Wait for pin and three value numbers to be received
  char pin = XBee.read(); // Read in the pin number
  int value = ASCIItoInt(XBee.read()) * 100; // Convert next three
  value += ASCIItoInt(XBee.read()) * 10;     // chars to a 3-digit
  value += ASCIItoInt(XBee.read());          // number.
  value = constrain(value, 0, 255); // Constrain that number.

  // Print a message to let the control know of our intentions:
  XBee.print("Setting pin ");
  XBee.print(pin);
  XBee.print(" to ");
  XBee.println(value);

  pin = ASCIItoInt(pin); // Convert ASCCI to a 0-13 value
  pinMode(pin, OUTPUT); // Set pin as an OUTPUT
  analogWrite(pin, value); // Write pin accordingly
}

// Read Digital Pin
// Send 'r' or 'R' to enter
// Then send a digital pin # to be read
// The Arduino will print the digital reading of the pin to XBee.
void readDPin()
{
  while (XBee.available() < 1)
    ; // Wait for pin # to be available.
  char pin = XBee.read(); // Read in the pin value

  // Print beggining of message
  XBee.print("Pin ");
  XBee.print(pin);

  pin = ASCIItoInt(pin); // Convert pin to 0-13 value
  pinMode(pin, INPUT); // Set as input
  // Print the rest of the message:
  XBee.print(" = ");
  XBee.println(digitalRead(pin));
}

// Read Analog Pin
// Send 'a' or 'A' to enter
// Then send an analog pin # to be read.
// The Arduino will print the analog reading of the pin to XBee.
void readAPin()
{
  while (XBee.available() < 1)
    ; // Wait for pin # to be available
  char pin = XBee.read(); // read in the pin value

  // Print beginning of message
  XBee.print("Pin A");
  XBee.print(pin);

  pin = ASCIItoInt(pin); // Convert pin to 0-6 value
  // Printthe rest of the message:
  XBee.print(" = ");
  XBee.println(analogRead(pin));
}

// ASCIItoHL
// Helper function to turn an ASCII value into either HIGH or LOW
int ASCIItoHL(char c)
{
  // If received 0, byte value 0, L, or l: return LOW
  // If received 1, byte value 1, H, or h: return HIGH
  if ((c == '0') || (c == 0) || (c == 'L') || (c == 'l'))
    return LOW;
  else if ((c == '1') || (c == 1) || (c == 'H') || (c == 'h'))
    return HIGH;
  else
    return -1;
}

// ASCIItoInt
// Helper function to turn an ASCII hex value into a 0-15 byte val
int ASCIItoInt(char c)
{
  if ((c >= '0') && (c <= '9'))
    return c - 0x30; // Minus 0x30
  else if ((c >= 'A') && (c <= 'F'))
    return c - 0x37; // Minus 0x41 plus 0x0A
  else if ((c >= 'a') && (c <= 'f'))
    return c - 0x57; // Minus 0x61 plus 0x0A
  else
    return -1;
}


/****  END OF PART FROM THE "REMOTE CONTROL" SKETCH *********************/







/************************ MENU HELPERS ***************************/

void flushInput() {
  // Read all available serial input to flush pending data.
  uint16_t timeoutloop = 0;
  while (timeoutloop++ < 40) {
    while (ss.available()) {
      ss.read();
      timeoutloop = 0;  // If char was received reset the timer
    }
    delay(1);
  }
}

char readBlocking(Stream* s) {
  while (!s->available());
  return s->read();
}

uint16_t readnumber(Stream* s) {
  uint16_t x = 0;
  char c;
  while (! isdigit(c = readBlocking(s))) {
    //Serial.print(c);
  }
  Serial.print(c);
  x = c - '0';
  while (isdigit(c = readBlocking(s))) {
    Serial.print(c);
    x *= 10;
    x += c - '0';
  }
  return x;
}

uint8_t readline(Stream* s, char *buff, uint8_t maxbuff) {
  uint16_t buffidx = 0;

  while (true) {
    if (buffidx > maxbuff) {
      break;
    }

    if (s->available()) {
      char c =  s->read();
      //Serial.print(c, HEX); Serial.print("#"); Serial.println(c);

      if (c == '\r') continue;
      if (c == 0xA) {
        if (buffidx == 0) {  // the first 0x0A is ignored
          continue;
        }
        buff[buffidx] = 0;  // null term
        return buffidx;
      }
      buff[buffidx] = c;
      buffidx++;
    }
  }
  buff[buffidx] = 0;  // null term
  return buffidx;
}
/************************ MENU HELPERS ***************************/




















// printMenu
// A big ol' string of Serial prints that print a usage menu over
// to the other XBee.
void printMenu()
{
  // Everything is "F()"'d -- which stores the strings in flash.
  // That'll free up SRAM for more importanat stuff.
  XBee.println();
  XBee.println(F("Arduino XBee Remote Control!"));
  XBee.println(F("============================"));
  XBee.println(F("Usage: "));
  XBee.println(F("w#nnn - analog WRITE pin # to nnn"));
  XBee.println(F("  e.g. w6088 - write pin 6 to 88"));
  XBee.println(F("d#v   - digital WRITE pin # to v"));
  XBee.println(F("  e.g. ddh - Write pin 13 High"));
  XBee.println(F("r#    - digital READ digital pin #"));
  XBee.println(F("  e.g. r3 - Digital read pin 3"));
  XBee.println(F("a#    - analog READ analog pin #"));
  XBee.println(F("  e.g. a0 - Read analog pin 0"));
  XBee.println();
  XBee.println(F("- Use hex values for pins 10-13"));
  XBee.println(F("- Upper or lowercase works"));
  XBee.println(F("- Use 0, l, or L to write LOW"));
  XBee.println(F("- Use 1, h, or H to write HIGH"));
  XBee.println(F("============================"));
  XBee.println();

}




User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

Rick, You're the best! I will give it a try in a few minutes. No matter if it works or not: "It is the thought that counts!"

User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

Well.. almost..

I uploaded and find that if I send from the TX-XBee "#5n\"

The receiving Arduino prints "Enter track number" and then breaks the connection.

To get the two to be able to communicate either way, I have to unplug and plug-in-again both using XCTU.

On the pother hand, if I type in "D8H" it turns on an led I have connected to Pin 8, and the connection is still there. I can turn pin 8 Low and the led goes off, etc.

But then send a packet with in "#5n\" , the receiving Arduino prints prints "Enter track number" and the connection is broken again.

Interestingly, if I send the list files command "Ln\" it dutifully lists the files and the connection IS NOT broken. I send "D8H" and the led goes on, etc.



I added some "println"s to try to see where the code stopped, and the one BEFORE "Enter your track =# prints, but nothing after that prints.

Does that provide a clue? I don't see why the connection would break.

case '#': {
Serial.println("before");
Serial.print("Enter track #");
uint8_t n = readnumber(&ss);

Serial.print("\nPlaying track #"); Serial.println(n);
ss.listen(); //switch to soundboard
if (! sfx.playTrack(n) ) {
Serial.println("Failed to play track?");
}
Serial.println("before break");
break
Serial.println("after break");
}

So I thought that it might be something about the "#" that conflicts with some code in the "Remote Control" sketch that it is meshed with?
But when I changed it to trigger on "M" instead of "#", the same pattern happened... connection broken right after "Enter track #"

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Can Soundboard be triggered by remote XBee?

Post by adafruit_support_rick »

Sorry - my fault. I had a brain cramp. I should have called readNumber and readLine with XBee, not with ss:

Code: Select all

      case '#': {
          Serial.print("Enter track #");
          uint8_t n = readnumber(&XBee);

          Serial.print("\nPlaying track #"); Serial.println(n);
          ss.listen();  //switch to soundboard
          if (! sfx.playTrack(n) ) {
            Serial.println("Failed to play track?");
          }
          break;
        }

      case 'P': {
          Serial.print("Enter track name (full 12 character name!) >");
          char name[20];
          readline(&XBee,name, 20);

          Serial.print("\nPlaying track \""); Serial.print(name); Serial.print("\"");
          ss.listen();  //switch to soundboard
          if (! sfx.playTrack(name) ) {
            Serial.println("Failed to play track?");
          }
          break;
        }


User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

You have done it again! Great!

And you have my promise that I will go back over all this (later) and make myself understand why one worked and the other did not.

The red light on the soundboard comes on, it says "playing track 7", all great, but no sound comes out. Sound is set for "184", and I have adjusted it up to 204 and still no sound. I can pause, unease, etc. just like it s'pos to do.

I will now re-check and then reverse the red&black leads from the 4 Ohm speaker and see if I can get this going. Almost there! Thanks again.

-Peter

User avatar
GrampaF
 
Posts: 35
Joined: Sat Nov 07, 2015 2:45 pm

Re: Can Soundboard be triggered by remote XBee?

Post by GrampaF »

Works great! -might have ben a loose wire (very technical stuff).

The servo fires when it is supposed to and the sound triggers when IT is supposed to.

Thanks again!

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Can Soundboard be triggered by remote XBee?

Post by adafruit_support_rick »

Glad to hear it!

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

Return to “XBee products (discontinued)”