Go Down

Topic: iPod Serial play/pause (Read 3912 times) previous topic - next topic

teejaytiger

Hi there, I'm new, so forgive me if I'm not quite ~socialized~ to the forum.

I'm working on a project right now getting an iPod to play or restart music based on a distance variable calculated by a Ping))) ultrasonic distance sensor ( http://www.parallax.com/tabid/768/ProductID/92/Default.aspx ) using an iPod serial port breakout kit and an Arduino Uno. I had a bit of trouble getting the serial to work, and I'm new to C++, so I could very well be doing something silly. I borrowed a bit of code too, so that might not help.

The idea is that if you get close to the device, it plays music, and if you back up, it stops and restarts the track.

This is what my original code (with interaction with the ping sensor) looked like:

Code: [Select]



// initialize
int PingPin = 7;      // Serial for Ping)))
int PodPin = 0;       // IPod TX, board RX
int PodPout = 1;      // IPod RX, board TX
int PingBaud = 9600;  // Ping))) Baud rate
int PodBaud = 19200;  // IPod Baud rate
int threshOn = 20;    // supposedly 20cm
int threshOff = 60;   // supposedly 60cm


// Setup
void setup(){
}

int commands[]={0,0,0x01,0x08,0x10,0x02,0x04};
//nothing? nothing? play/pause forward back volup voldown
int buttonRelease[] = {0xFF, 0x55, 0x03, 0x02, 0x00, 0x00,0xFB};

void loop() {
  int val = Ping();
  if ( val < threshOn ) {
    sendCommand(commands[2]);//play/pause
    while (val < threshOff){
      val = Ping();
      delay (500);
    }
    sendCommand(commands[2]);//Play/pause
    sendCommand(commands[4]);//back
  }
  val = Ping();
}



int checkSum(int len, int mode, int command1, int command2, int parameter) {
  int checksum = 0x100 - ((len + mode + command1 + command2+ parameter) & 0xFF);
  return checksum;
}

void sendCommand(int cmd) {
  Serial.begin(PodBaud);
  int cs = checkSum(0x03, 0x02, 0x00, cmd, 0);
  Serial.println(cs,HEX);
  // no clue
  int bytes[] = {0xFF, 0x55, 0x03, 0x02, 0x00, cmd, cs};
  for (int i = 0; i < 8; i++) {
  Serial.write((byte)bytes[i]);
  }
  for (int i = 0; i < 8; i++) {
    Serial.write((byte)buttonRelease[i]);
  }
}

int Con_T_S(int pingLen){
  return pingLen / 29 / 2;
}

int Ping(){
  Serial.begin(PingBaud)      ;  // BaudRate set for Ping)))
  int x = 0;
  pinMode(PingPin, OUTPUT)    ;
  digitalWrite(PingPin, LOW)  ;  // init sensor to ensure clean HIGH pulse
  delayMicroseconds(2)        ; 
  digitalWrite(PingPin, HIGH) ;  // make the sensor send a pulse
  delayMicroseconds(5)        ; 
  digitalWrite(PingPin, LOW)  ;  // Set LOW again
  pinMode(PingPin, INPUT)     ;  // Get ready to capture the duration of the resulting pulse
  // Capture how long the pin stays in HIGH state.
  int Duration = pulseIn(PingPin, HIGH) ;
    x = Con_T_S(Duration);
    return x;
}


but that wasn't giving me the results I wanted (Ping sensor works great, for all I'm aware)

So I wrote this to test how I was interacting with the iPod:

Code: [Select]


#include <SoftwareSerial.h>
#define rxPin 0
#define txPin 1

SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

// initialize
int PodPin = 0;       // IPod TX, board RX
int PodPout = 1;      // IPod RX, board TX
int PodBaud = 19200;  // IPod Baud rate

// Setup
void setup(){
  mySerial.begin(19200);
}

int commands[]={0,0,0x01,0x08,0x10,0x02,0x04};
//0,0, play/pause, forward, back, volup, voldown
int buttonRelease[] = {0xFF, 0x55, 0x03, 0x02, 0x00, 0x00,0xFB};

void loop() {
  sendCommand(commands[2]);
  delay(5000);//5 seconds
}

int checkSum(int len, int mode, int command1, int command2, int parameter) {
  int checksum = 0x100 - ((len + mode + command1 + command2+ parameter) & 0xFF);
  return checksum;
}

void sendCommand(int cmd) {
  int cs = checkSum(0x03, 0x02, 0x00, cmd, 0);
  mySerial.println(cs,HEX);
  int bytes[] = {0xFF, 0x55, 0x03, 0x02, 0x00, cmd, cs};
  for (int i = 0; i < 8; i++) {
  mySerial.write((byte)bytes[i]);
  }
  for (int i = 0; i < 8; i++) {
    mySerial.write((byte)buttonRelease[i]);
  }
}


and despite my best efforts, I came up with nothing. No response from the iPod except when I plugged it into the board to let me know it's charging.

Any of you brilliant minds have some sort of magical remedy for my plight?
Thanks a ton.

cmiyc

Why are you using Software Serial on pins 0 and 1?  Those are the Hardware Serial pins.
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

nickgammon


... forgive me if I'm not quite ~socialized~ to the forum.


We'll fix that! <grin>

Code: [Select]
int commands[]={0,0,0x01,0x08,0x10,0x02,0x04};
//0,0, play/pause, forward, back, volup, voldown
int buttonRelease[] = {0xFF, 0x55, 0x03, 0x02, 0x00, 0x00,0xFB};

void loop() {
 sendCommand(commands[2]);
 delay(5000);//5 seconds
}


This is a long-winded way of saying:

Code: [Select]
 sendCommand(1);

Isn't it? What does the array achieve?

Plus what James C4S said.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

teejaytiger

Quote
Why are you using Software Serial on pins 0 and 1?  Those are the Hardware Serial pins.


These are things that help me.
If I use Software Serial on other pins (e.g. 8 and 9), will I get the results I'm looking for? Or is there some way to communicate on 1 and 0 that would work here?

I'm really lost/new on this, anything helps,
-Thanks.

teejaytiger

Quote
Isn't it? What does the array achieve?


the array just holds certain parts of the big long what I'm sending over serial. Looking back now I suppose that would also work, but I think iPod is supposed to receive Strings? Or something? I'm just so inexperienced with serial communications.  :~


cmiyc

You might want to consider this project:
http://davidfindlay.org/weblog/files/2009_09_07_ipod_remote.php
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

nickgammon


These are things that help me.



If you are using pins 0 and 1 you can use hardware serial (Serial) rather than software serial.

Quote
the array just holds certain parts of the big long what I'm sending over serial.


But you aren't doing that. This may be part of the problem.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

teejaytiger

Yaknow, the thing is, I've seen that, and I kept getting errors originating from his library? And it was just too much to deal with just to send play and pause. But I guess trying to make things simpler resulted in the opposite.  :smiley-red:

teejaytiger

I'll be away from the computer for a minute, but I will get back and try a couple of these things out and let you know what happened.

cmiyc


Yaknow, the thing is, I've seen that, and I kept getting errors originating from his library?

I just downloaded the library and have had no issues.... after I also downloaded the Bounce library (mentioned in the comments for the examples).
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

teejaytiger

Downloaded bounce. I'm getting this:

Quote
Documents\Arduino\libraries\IPodSerialLib/iPodSerial.h:167: error: ISO C++ forbids declaration of 'byte' with no type


for this: (which is his, so I could make sure that I wasn't crazy)

Code: [Select]
#include <SimpleRemote.h>
#include <Bounce.h>

const byte BUTTON_PIN = 5;
const unsigned long DEBOUNCE_MS = 20;

Bounce button(BUTTON_PIN, DEBOUNCE_MS);
SimpleRemote simpleRemote;

void setup()
{
  pinMode(BUTTON_PIN, INPUT);

  // enable pull-up
  digitalWrite(BUTTON_PIN, HIGH);

  simpleRemote.setup();
}

void loop()
{
  simpleRemote.loop();

  if (button.update())
  {
    if (button.read() == LOW)
    {
      // prod the iPod in case it went to sleep since we last talked to it
      // (after which older iPods will stop responding to us otherwise)
      simpleRemote.sendiPodOn();
      delay(50);
      simpleRemote.sendButtonReleased();
     
      simpleRemote.sendPlay();
    }
    else
    {
      simpleRemote.sendButtonReleased();
    }
  }
}



I am at a loss. What do I have to do to his library, or my original code (without his library) to just make this durn thing work?

teejaytiger

So, I've run out of compiling errors, but I still get no response from the iPod.

This is where the code stands:

Code: [Select]

#include <iPodSerial.h>
#include <SimpleRemote.h>

SimpleRemote simpleRemote;

// initialize
int pingPin = 7          ; // Serial for Ping)))
int podPin = 0           ; // IPod TX, board RX
int podPout = 1          ; // IPod RX, board TX
int pingBaud = 9600      ; // Ping))) Baud rate
int podBaud = 19200      ; // IPod Baud rate
int threshOn = 20;
int threshOff = 40;

// set up
void setup() {
  iPodSerial(); // Setup iPodSerial
}

unsigned long pp = 0;

void loop() {
  simpleRemote.sendiPodOn();
    delay(50);
    simpleRemote.sendButtonReleased();
    simpleRemote.sendPlay();
    delay(5000);
}
/*
  pp = Ping();
  while (pp > threshOn){
    delay(500);
    break;
  }
  if (pp < threshOn) {
    simpleRemote.sendiPodOn();
    delay(50);
    simpleRemote.sendButtonReleased();
    simpleRemote.sendPlay();
    while (pp < threshOff){
      pp = Ping();
      delay (500);
    }
  }
  simpleRemote.sendiPodOn();
  simpleRemote.sendButtonReleased();
  simpleRemote.sendPlay();
  simpleRemote.sendSkipBackward();
}
*/

unsigned long Ping(){
  Serial.begin(pingBaud);
  int x = 0;
  pinMode(pingPin, OUTPUT)    ;
  digitalWrite(pingPin, LOW)  ;  // init sensor to ensure clean HIGH pulse
  delayMicroseconds(2)        ; 
  digitalWrite(pingPin, HIGH) ;  // make the sensor send a pulse
  delayMicroseconds(5)        ; 
  digitalWrite(pingPin, LOW)  ;  // Set LOW again
  pinMode(pingPin, INPUT)     ;  // Get ready to capture the duration of the resulting pulse
  // Capture how long the pin stays in HIGH state.
  unsigned long Duration = pulseIn(pingPin, HIGH) ; 
  x = Convert_Time_Space(Duration) ;
  delay(500);
  return x;
}

unsigned long Convert_Time_Space(const unsigned long fnDuration )
{
  // I used 29 microseconds per cm.
  // 40kHz supersonic burst
  // 1130 fps -> 29.0339814 microseconds per cm
  return fnDuration / 29 / 2 ;
}


and as for hardware, it's right outta this:

http://www.flickr.com/photos/finsprings/4403179910/lightbox/

With the exception that my power runs straight from 5v to the iPod, since it actually charges that way. But since that has nothing to do with TX/RX, forget it.

Anyone see what I'm doing wrong here?


cmiyc

Code: [Select]
  iPodSerial(); // Setup iPodSerial
I'm not sure I understand what this is calling. 

In setup() you need to have:
Code: [Select]
simpleRemote.setup()

Somewhere in loop() you also need to call:
Code: [Select]
simpleRemote.loop()
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

teejaytiger

I can't believe I missed that.

Thanks, but still no response from the iPod. This is baffling me. I am not worthy.

current code!
Code: [Select]


#include <iPodSerial.h>
#include <SimpleRemote.h>

SimpleRemote simpleRemote;

// initialize
int pingPin = 7          ; // Serial for Ping)))
int podPin = 0           ; // IPod TX, board RX
int podPout = 1          ; // IPod RX, board TX
int pingBaud = 9600      ; // Ping))) Baud rate
int podBaud = 19200      ; // IPod Baud rate
int threshOn = 20;
int threshOff = 40;

// set up
void setup() {
 //iPodSerial();
 //TODO: Why did I put this here?
 simpleRemote.setup();
}

void loop() {
 simpleRemote.loop();
 simpleRemote.sendiPodOn();
 delay(50);
 simpleRemote.sendPlay();
 simpleRemote.sendButtonReleased();
 delay(5000);
}

teejaytiger

Here's a really awful picture of the hardware, if it helps. I am not much of a hardware guy, so excuse the awfulness.



Anything visibly wrong here? Did it become a hardware problem?

Go Up