iPod Serial play/pause

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:

// 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:

#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.

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

teejaytiger:
… forgive me if I’m not quite ~socialized~ to the forum.

We’ll fix that!

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:

  sendCommand(1);

Isn’t it? What does the array achieve?

Plus what James C4S said.

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.

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. :~

You might want to consider this project: http://davidfindlay.org/weblog/files/2009_09_07_ipod_remote.php

teejaytiger:
These are things that help me.

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

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.

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. :blush:

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.

teejaytiger: 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).

Downloaded bounce. I’m getting this:

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)

#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?

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

This is where the code stands:

#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?

  iPodSerial(); // Setup iPodSerial

I'm not sure I understand what this is calling.

In setup() you need to have:

 simpleRemote.setup()

Somewhere in loop() you also need to call:

 simpleRemote.loop()

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!

#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);
}

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?

You have too much going on for untested software and hardware. Yank half those wires - the one going to the ping sensor, specifically. If you can't get the iPad to do anything, it doesn't matter what is in front of the ping sensor, does it?

Write a simple script that does some stuff in setup(), with NOTHING in loop(). Does the iPan react? If not, it isn't wired correctly or you are sending the wrong stuff to it.

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

The soldering doesn't look very good.

Are those arrows data direction flow? In which case you have data on the receive line pointing the wrong way.

I have one of those level shifting boards. You have to power them. The HV and LV pins appear unconnected. The board has transistors on it. Transistors need power to work.