Friday, October 12, 2012

New bluetooth module

I might buy this bluetooth module and throw it in my setup & see how it sounds...it's cheap, less than $20 shipped...

http://www.elecfreaks.com/store/audio-bluetooth-speaker-modulebc05b-p-435.html

I'll post if I buy it & let everyone know how it sounds.

My buddy has been trying to convince me to disassemble an old Airport Express (the wall-wart type, not the AppleTV type) and use the guts as the audio source; sounds good, but it's big as hell.

Thursday, October 11, 2012

Possible New Name

So, the Belkin F8Z492TTP device SUCKS. The sound quality is so shitty, it's amazing. I wired a 3.5mm plug inside my box so I can plug a line directly into the sound system, or through the bluetooth dongle. The sound quality is night & day. The direct connect almost sounds too bass-y, but with the shitty Belkin module, there are no mids. It sounds metallic and hollow like you're listening to your music from a boombox in a hallway.

Hence the name change...I could maybe buy a different bluetooth module (I was looking at the Logitech 980-000540; it has great reviews for sound quality, but it's big as shit), but another problem I've noticed is the lack of "auto reconnect" that these bluetooth devices (don't) have. It's kind of a PITA to have to reselect and connect to the damn thing each & everytime you want to use it.

So for the meantime, I've changed the SID to display "iSaab Aux". It's more generic but still gets the point across.

Code for the SID change is below.


// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// http://BlueSaab.blogspot.com/
// By Seth Evans
// 5 Oct 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200);
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  // CDC code needs sent every second or less so all loops
  // running added together need to take less than 1000ms
  // but no more or the car won't "see" the CDC
  CDC();
  if (cdbutton==1) {
    Serial.println("iPod ON");
    iPodOn();
  }
  else {
    Serial.println("iPod OFF");
    //iPodOff();
    //delay(400);
  }
  for (int i = 0; i <= 900; i++) {
    delay(1);
    // this loop takes 850ms
    if (CAN.CheckNew()) {
      CAN_TxMsg.data[0]++;
      CAN.ReadFromDevice(&CAN_RxMsg);
      //PrintBus();
      if (CAN_RxMsg.id==0x3C0) {
        if (CAN_RxMsg.data[0]==0x80) {
          switch (CAN_RxMsg.data[1]) {
          case 0x24:
            cdbutton = 1;
            Serial.println("CDC");
            break;
          case 0x14:
            cdbutton = 0;  
            Serial.println("Radio");
            break;
          }
        }
      }
    }
  }
}

void CDC() {
  CAN_TxMsg.id=0x3C8;     // CD Changer
  CAN_TxMsg.data[0]=0xE0;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x3F; // all 6 discs inserted
  CAN_TxMsg.data[3]=0x31; // playing , disc 1
  CAN_TxMsg.data[4]=0xFF;
  CAN_TxMsg.data[5]=0xFF;
  CAN_TxMsg.data[6]=0xFF;
  CAN_TxMsg.data[7]=0xD0; // married "OK" code
  CAN.send(&CAN_TxMsg);
}

void iPodOn() {
  // This loop takes 0ms
  CAN_TxMsg.id=0x328;     // SID audio text
  CAN_TxMsg.data[0]=0x42; // message 2
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02; // Row 2
  CAN_TxMsg.data[3]=0x69; // i
  CAN_TxMsg.data[4]=0x53; // S
  CAN_TxMsg.data[5]=0x61; // a
  CAN_TxMsg.data[6]=0x61; // a
  CAN_TxMsg.data[7]=0x62; // b
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x01; // message 1
  CAN_TxMsg.data[3]=0x20; // _
  CAN_TxMsg.data[4]=0x41; // A
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x78; // x
  CAN_TxMsg.data[7]=0x20; // _
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x00; // message 0
  CAN_TxMsg.data[3]=0x00; // _
  CAN_TxMsg.data[4]=0x00; // _
  CAN_TxMsg.data[5]=0x00; //
  CAN_TxMsg.data[6]=0x00; //
  CAN_TxMsg.data[7]=0x00; //
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.id=0x348;     // audio text control
  CAN_TxMsg.data[0]=0x11;
  CAN_TxMsg.data[1]=0x02; // Row 2
  CAN_TxMsg.data[2]=0x05;
  CAN_TxMsg.data[3]=0x18; // priority 18?
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.id=0x368;     // SID text priority
  CAN_TxMsg.data[0]=0x02; // Row 2
  CAN_TxMsg.data[1]=0x18; // priority 18?
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void iPodOff() {
  // I don't think this code is needed at all...
  CAN_TxMsg.id=0x368;     // turn off the SID (SPA) text
  CAN_TxMsg.data[0]=0x02;
  CAN_TxMsg.data[1]=0x19;
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void PrintBus() {
  if (CAN_RxMsg.id==0x3C0) {
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}

Friday, October 5, 2012

Photos!

Here are a few I took

The connector to the car is on the left here, under all that white (clear) silicone. At the top of this picture (the orange crystal resonator) is the RBBB Arduino board. The large green board is the Saablin balanced audio converter (the TC962EPC is on the other side of this board), and the bluetooth receiver is on the right at an angle. The connector on the right is simply the 6 pin FTDI programming port off of the RBBB board so I don't have to open it up every time I want to change the software.
This view is the opposite angle, trying to view the Secuduino board on the very bottom.
Here is the entire module installed in the car, using a velcro strap to attach the box to that black tube along the driver's side trunk. This is normally where the CD changer would be anyway, so there's plenty of room here. All hidden away behind the trunk carpet!

All finished??

So I rearranged some code to more efficiently check for the radio/cdc selection, as well as not flood the bus with CDC messages. So now the code runs the CDC command every 900 or 950ms depending if the SID is displaying text.

The SID also displays the text cleaner, either because I'm using 348 and 368 messages, or because I'm sending them with priority 18 (I think). I think the CDC is normally priority 19, so anything lower than that is a higher priority. I don't want to completely take over the SID in case an alert from the car pops up, so anything lower than 19 should work. Currently, the SID will alternate flashing "BlueSaab" and "CD1 PLAY" a few times back and forth, then eventually "BlueSaab" will "win" and stay steady. Seems to be pretty steady, and my turn signals seem to be working, so I don't think the bus is overloaded :)



// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// http://BlueSaab.blogspot.com/
// By Seth Evans
// 5 Oct 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200);
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  // CDC code needs sent every second or less so all loops
  // running added together need to take less than 1000ms
  // but no more or the car won't "see" the CDC
  CDC();
  if (cdbutton==1) {
    Serial.println("iPod ON");
    iPodOn();
  }
  else {
    Serial.println("iPod OFF");
    //iPodOff();
    //delay(400);
  }
  for (int i = 0; i <= 900; i++) {
    delay(1);
    // this loop takes 900ms
    if (CAN.CheckNew()) {
      CAN_TxMsg.data[0]++;
      CAN.ReadFromDevice(&CAN_RxMsg);
      //PrintBus();
      if (CAN_RxMsg.id==0x3C0) {
        if (CAN_RxMsg.data[0]==0x80) {
          switch (CAN_RxMsg.data[1]) {
          case 0x24:
            cdbutton = 1;
            Serial.println("CDC");
            break;
          case 0x14:
            cdbutton = 0;  
            Serial.println("Radio");
            break;
          }
        }
      }
    }
  }
}

void CDC() {
  CAN_TxMsg.id=0x3C8;     // CD Changer
  CAN_TxMsg.data[0]=0xE0;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x3F; // all 6 discs inserted
  CAN_TxMsg.data[3]=0x31; // playing , disc 1
  CAN_TxMsg.data[4]=0xFF;
  CAN_TxMsg.data[5]=0xFF;
  CAN_TxMsg.data[6]=0xFF;
  CAN_TxMsg.data[7]=0xD0; // married "OK" code
  CAN.send(&CAN_TxMsg);
}

void iPodOn() {
  // This loop takes 50ms
  CAN_TxMsg.id=0x328;     // SID audio text
  CAN_TxMsg.data[0]=0x42; // message 2
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02; // Row 2
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x01; // message 1
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x00; // _
  CAN_TxMsg.data[7]=0x00; // _
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x00; // message 0
  CAN_TxMsg.data[3]=0x00; // _
  CAN_TxMsg.data[4]=0x00; // _
  CAN_TxMsg.data[5]=0x00; //
  CAN_TxMsg.data[6]=0x00; //
  CAN_TxMsg.data[7]=0x00; //
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.id=0x348;     // audio text control
  CAN_TxMsg.data[0]=0x11;
  CAN_TxMsg.data[1]=0x02; // Row 2
  CAN_TxMsg.data[2]=0x05;
  CAN_TxMsg.data[3]=0x18; // priority 18?
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.id=0x368;     // SID text priority
  CAN_TxMsg.data[0]=0x02; // Row 2
  CAN_TxMsg.data[1]=0x18; // priority 18?
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void iPodOff() {
  // I don't think this code is needed at all...
  CAN_TxMsg.id=0x368;     // turn off the SID (SPA) text
  CAN_TxMsg.data[0]=0x02;
  CAN_TxMsg.data[1]=0x19;
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void PrintBus() {
  if (CAN_RxMsg.id==0x3C0) {
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}

Thursday, October 4, 2012

New Diagram

Here's the updated diagram for the entire setup. I was actually able to cram ALL 4 boards into one small box, about 4" x 2" x 1" !!! I have 2 connectors, one that connects to the CDC connector, and the other is simply the Arduino programming port so I don't have to open the box up to edit the firmware/program.


Hardware = finished; Software = eh...

So I got the inverter chip (TC962EPA) which inverts any input from +3 to +18V and wired it up so it's giving the Saablin board the -12V for the OpAmps....it works great! The ground loop isolator made the sound quiet, and a little hollow, and seemed to miss some lows (although it shouldn't have according to the specs). Rass' Saablin board with the opamps sounds a little hollow, but the lows came back, and overall, it sounds wonderful :)

Rass' website here: http://saablin.net/
Rass' Saablin Balanced Audio circuit board: http://saablin.net/node/10
BatchPCB board for order: https://www.batchpcb.com/product_info.php?products_id=31438&check=04c8d356c127174ce72449dcbc8523ce

I still need to update my entire diagram to replace the dual ground loop isolator & replace it with Rass' Saablin board.

As for the software....it still has the display glitch that flickers "BlueSaab" with "CD1 Play".

// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
// 
// Saab CDC Changer Emulator
// http://BlueSaab.blogspot.com/
// By Seth Evans
// 4 Oct 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200); 
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  CDC();
  delay(5);
  if (CAN.CheckNew()) {
    CAN_TxMsg.data[0]++;
    CAN.ReadFromDevice(&CAN_RxMsg);
    //PrintBus();
    if (CAN_RxMsg.id==0x3C0) {
      //CDC();
      //delay(5);
      if (CAN_RxMsg.data[0]==0x80) {
        switch (CAN_RxMsg.data[1]) {
        case 0x24:
          cdbutton = 1;
          Serial.println("CDC");
          break;
        case 0x14:
          cdbutton = 0;    
          Serial.println("Radio");
          break;
          //case default:
        } // end of switch case
        //else if (CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x14)
      }
    }
  } 
  if (cdbutton==1) {
    //CDC();
    //delay(5);
    iPodOn();
  }
  else {
    iPodOff();
  }
}

void CDC() {
  CAN_TxMsg.id=0x6A2;     // 
  CAN_TxMsg.data[0]=0x32;
  CAN_TxMsg.data[1]=0x00;  
  CAN_TxMsg.data[2]=0x00; 
  CAN_TxMsg.data[3]=0x16; // 
  CAN_TxMsg.data[4]=0x01;
  CAN_TxMsg.data[5]=0x02;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00; // 
  CAN.send(&CAN_TxMsg);
  delay(5);
  
  CAN_TxMsg.id=0x3C8;     // CD Changer
  CAN_TxMsg.data[0]=0xE0;
  CAN_TxMsg.data[1]=0x00;  
  CAN_TxMsg.data[2]=0x3F; 
  CAN_TxMsg.data[3]=0x31; // playing disc 1
  CAN_TxMsg.data[4]=0xFF;
  CAN_TxMsg.data[5]=0xFF;
  CAN_TxMsg.data[6]=0xFF;
  CAN_TxMsg.data[7]=0xD0; // married "OK" code
  CAN.send(&CAN_TxMsg);
}

void iPodOn() {
  CAN_TxMsg.id=0x328;     // SID audio text
  CAN_TxMsg.data[0]=0x42;
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02;
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.data[0]=0x01;
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x00; // _
  CAN_TxMsg.data[7]=0x00; // _
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.data[0]=0x00;
  CAN_TxMsg.data[3]=0x00; // _
  CAN_TxMsg.data[4]=0x00; // _
  CAN_TxMsg.data[5]=0x00; // 
  CAN_TxMsg.data[6]=0x00; // 
  CAN_TxMsg.data[7]=0x00; // 
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.id=0x368;     // enable the SID (audio) text?
  CAN_TxMsg.data[0]=0x02;
  CAN_TxMsg.data[1]=0x19;
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(5);
}

void iPodOff() {
  CAN_TxMsg.id=0x368;     // turn off the SID (SPA) text
  CAN_TxMsg.data[0]=0x02;
  CAN_TxMsg.data[1]=0x19;
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void PrintBus() {
  if (CAN_RxMsg.id==0x290) {
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}



Tuesday, October 2, 2012

Maybe it STILL needs tweaking....

So after work today, the display went blank, except for small blips of "BlueSaab", so it's working somewhat...more tweaking tomm!

Smooth display

I think I finally got the SID to display "BlueSaab" without flickering now. I don't know why, but I'm using the 348 ID to say "1102FF1900000000" after I send the "BlueSaab" text...I thought that 348 command would turn the text off, but I guess it turned off the "CD1 PLAY" text!

I still have 2 issues...
1, the Arduino has problems where it will miss my button press to go to the CDC or Radio, thereby still displaying "BlueSaab" (or not, depending on your intended source). Several cycles through the sources (easiest with the SRC button on the steering wheel) will usually catch whatever source you need, and match the SID to it.
2, If playing BlueSaab and you turn the radio off, the SID still displays "BlueSaab". This is remedied by turning the head unit back on, switching to Radio, and turning the radio off. The sound turns off, but the SID does not. It's still something with the Arduino not catching button clicks. I may have to add an "If/Then" or "switch" to catch the power down mode & turn off the SID.

New code!



// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// Seth Evans
// 2 Oct 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200);
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  CDC();
  delay(5);
  if (CAN.CheckNew()) {
    CAN_TxMsg.data[0]++;
    CAN.ReadFromDevice(&CAN_RxMsg);
    //PrintBus();
    if (CAN_RxMsg.id==0x3C0) {
      //CDC();
      //delay(5);
      if (CAN_RxMsg.data[0]==0x80) {
        switch (CAN_RxMsg.data[1]) {
        case 0x24:
          cdbutton = 1;
          Serial.println("CDC");
          break;
        case 0x14:
          cdbutton = 0;  
          Serial.println("Radio");
          break;
          //case default:
        } // end of switch case
        //else if (CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x14)
      }
    }
  }
  if (cdbutton==1) {
    //CDC();
    //delay(5);
    iPodOn();
  }
  else {
    iPodOff();
  }
}

void CDC() {
  CAN_TxMsg.id=0x6A2;     //
  CAN_TxMsg.data[0]=0x32;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x16; //
  CAN_TxMsg.data[4]=0x01;
  CAN_TxMsg.data[5]=0x02;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00; //
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.id=0x3C8;     // CD Changer
  CAN_TxMsg.data[0]=0xE0;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x3F;
  CAN_TxMsg.data[3]=0x31; // playing disc 1
  CAN_TxMsg.data[4]=0xFF;
  CAN_TxMsg.data[5]=0xFF;
  CAN_TxMsg.data[6]=0xFF;
  CAN_TxMsg.data[7]=0xD0; // married "OK" code
  CAN.send(&CAN_TxMsg);
}

void iPodOn() {
  CAN_TxMsg.id=0x328;     // SID audio text
  CAN_TxMsg.data[0]=0x42;
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02;
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.data[0]=0x01;
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x00; // _
  CAN_TxMsg.data[7]=0x00; // _
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.data[0]=0x00;
  CAN_TxMsg.data[3]=0x00; // _
  CAN_TxMsg.data[4]=0x00; // _
  CAN_TxMsg.data[5]=0x00; //
  CAN_TxMsg.data[6]=0x00; //
  CAN_TxMsg.data[7]=0x00; //
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.id=0x348;     // enable the SID (audio) text?
  CAN_TxMsg.data[0]=0x11;
  CAN_TxMsg.data[1]=0x02;
  CAN_TxMsg.data[2]=0xFF;
  CAN_TxMsg.data[3]=0x19;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(5);
}

void iPodOff() {
  CAN_TxMsg.id=0x368;     // turn off the SID (SPA) text
  CAN_TxMsg.data[0]=0x02;
  CAN_TxMsg.data[1]=0x19;
  CAN_TxMsg.data[2]=0x00;
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void PrintBus() {
  if (CAN_RxMsg.id==0x290) {
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}

Thursday, September 27, 2012

2nd update for today

New code; this time I used the Saab Park Assist (SPA) message to display "BlueSaab" on the SID. It seems to work pretty well; it takes a few seconds for the display to register, but the music lines are on immediately so you'll see "CD1 PLAY" for about 5 seconds, and then "BlueSaab" appears. All other SID functions seem to work properly, and the turn signals seem to work w/out interruption ;)

Going back to Radio mode, however, seems to be intermittent. This has always kind of been an issue; if the Arduino doesn't see the Radio selection, it doesn't know to switch back to Radio mode (aka, turn off the CD Changer code/SID display). The SID will go back to Radio mode, and you'll hear the station you're on, but if the Arduino didn't see the switch, "BlueSaab" will pop up again (that 5 second) delay. I just cycle back to the CDC input and back to the radio (3 presses of the SRC button on the wheel) and it seems to clear it up (maybe after a few cycles).

Stupid bugs...


// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// Seth Evans
// 27 Sep 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200);
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  if (CAN.CheckNew()){
    CAN_TxMsg.data[0]++;
    CAN.ReadFromDevice(&CAN_RxMsg);
    //PrintBus();
    if (CAN_RxMsg.id==0x3C0){
      CDC();
      if (CAN_RxMsg.data[1]==0x24){
        cdbutton = 1;
        Serial.println("CDC");
      }
      else if (CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x14){
        cdbutton = 0;  
        Serial.println("Radio");
      }
    }

    if (cdbutton==1){
      CDC();
      delay(5);
      iPodOn();
    }
    else {
      //iPodOff();
    }
  }
}

void CDC(){
  CAN_TxMsg.id=0x3C8;     // CD Changer
  CAN_TxMsg.data[0]=0xE0;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x3F;
  CAN_TxMsg.data[3]=0x31; // playing disc 1
  CAN_TxMsg.data[4]=0xFF;
  CAN_TxMsg.data[5]=0xFF;
  CAN_TxMsg.data[6]=0xFF;
  CAN_TxMsg.data[7]=0xD0; // married "OK" code
  CAN.send(&CAN_TxMsg);
}

void iPodOn(){
  CAN_TxMsg.id=0x357;     // enable the SID (SPA) text
  CAN_TxMsg.data[0]=0x1F;
  CAN_TxMsg.data[1]=0x02;
  CAN_TxMsg.data[2]=0x05;
  CAN_TxMsg.data[3]=0x12;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.id=0x337;  
  CAN_TxMsg.data[0]=0x42;
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02;
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x01;
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x20; // _
  CAN_TxMsg.data[7]=0x20; // _
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x00;
  CAN_TxMsg.data[3]=0x20; // _
  CAN_TxMsg.data[4]=0x20; // _
  CAN_TxMsg.data[5]=0x00; //
  CAN_TxMsg.data[6]=0x00; //
  CAN_TxMsg.data[7]=0x00; //
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void iPodOff(){
  CAN_TxMsg.id=0x357;     // turn off the SID (SPA) text
  CAN_TxMsg.data[0]=0x1F;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x05;
  CAN_TxMsg.data[3]=0x08;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void PrintBus(){
  if (CAN_RxMsg.id==0x3C0){
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}

Latest software

So I commented out the line calling the routine displaying text on the SID because it was causing issues with the I-Bus communications. For example, turning on either blinker, occasionally the indicators on the dash would not blink, or blink twice fast, as they time themselves with the outside blinker. The timing with the SID text display was interrupting this, and god knows what else. Of course, this is only an indication issue, the outside blinkers still work perfectly.


// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator, BlueSaab
// Seth Evans
// 27 Sep 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200);
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;  // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  if (CAN.CheckNew()){
    CAN_TxMsg.data[0]++;
    CAN.ReadFromDevice(&CAN_RxMsg);
    //PrintBus();
    if (CAN_RxMsg.id==0x3C0){
      CDC();
      if (CAN_RxMsg.data[1]==0x24){
        cdbutton = 1;
        Serial.println("CDC");
      }
      else if (CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x14){
        cdbutton = 0;  
        Serial.println("Radio");
      }
    }

    if (cdbutton==1){
      CDC();
      delay(5);
      //iPodOn();
    }
    else {
      iPodOff();
    }
  }
}

void CDC(){
  CAN_TxMsg.id=0x3C8;  
  CAN_TxMsg.data[0]=0x80;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x3F;
  CAN_TxMsg.data[3]=0x41;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0xD0;
  CAN.send(&CAN_TxMsg);
}

void iPodOn(){
  CAN_TxMsg.id=0x348;
  CAN_TxMsg.data[0]=0x11;
  CAN_TxMsg.data[1]=0x02;
  CAN_TxMsg.data[2]=0x04;
  CAN_TxMsg.data[3]=0x19;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.id=0x328;  
  CAN_TxMsg.data[0]=0x42;
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02;
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(5);

  CAN_TxMsg.data[0]=0x01;
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x20; // _
  CAN_TxMsg.data[7]=0x20; // _
  CAN.send(&CAN_TxMsg);
  delay(5);
}

void iPodOff(){
}

void PrintBus(){
  if (CAN_RxMsg.id==0x3C0){
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}

Tuesday, September 25, 2012

Software update


I'm still playing with the SID display timing...this version seems to work pretty well, except the radio has a tendency to just shut off randomly...(?).

I tried using 0x337 SPA (Saab Park Assist) Messages to display the audio status, but that had it's own issues as well. As you can see below, I'm currently using 0x328 SID Audio Text Messages.

// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// Seth Evans
// 25 Sep 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200);
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;  // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  CDC();
  delay(5);
  if (CAN.CheckNew()){
    CAN_TxMsg.data[0]++;
    CAN.ReadFromDevice(&CAN_RxMsg);
    //PrintBus();
    if (CAN_RxMsg.id==0x3C0){
      if (CAN_RxMsg.data[1]==0x24){
        cdbutton = 1;
        Serial.println("CDC");
      }
      else if (CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x14){
        cdbutton = 0;  
        Serial.println("Radio");
      }
    }
  }
  if (cdbutton==1){
    iPodOn();
  }
  else {
    iPodOff();
  }
}

void CDC(){
  CAN_TxMsg.id=0x3C8;  
  CAN_TxMsg.data[0]=0x80;
  CAN_TxMsg.data[1]=0x00;
  CAN_TxMsg.data[2]=0x3F;
  CAN_TxMsg.data[3]=0x41;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0xD0;
  CAN.send(&CAN_TxMsg);
}

void iPodOn(){
  CAN_TxMsg.id=0x328;  
  CAN_TxMsg.data[0]=0x42;
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02;
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x01;
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x20; // _
  CAN_TxMsg.data[7]=0x20; // _
  CAN.send(&CAN_TxMsg);
  delay(10);
}

void iPodOff(){
}

void PrintBus(){
  if (CAN_RxMsg.id==0x3C0){
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[0],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[1],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[2],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[3],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[4],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[5],HEX);
    Serial.print(";");
    Serial.print(CAN_RxMsg.data[6],HEX);
    Serial.print(";");
    Serial.println(CAN_RxMsg.data[7],HEX);
  }
}

Monday, September 24, 2012

Saab I-BUS info...

So it took me a day or so to figure out that the Saab I-Bus talks on a non-standard speed: 47.619Kbps. Most other CANBUS interfaces talk at 50, 100, 125, 250, 500, or 1000Kbps (1MBit). It's easy to change the speed, but there are many factors that affect the speed in the CANBUS chip/module.

Inside the CAN folder, there is a file called CAN.cpp. You need to edit the CAN.cpp file with Notepad or similar.

Scroll to where it says “switch(speed)”, and you should see several chunks of code that reference “case 1” and “case 500” and a few more. Anytime after the “{“ and before the next “}”, between the other cases, add the following code and save the file:

case 47:
mcp2515_write_register(CNF1,0xC7);
mcp2515_write_register(CNF2,0xBE);
mcp2515_write_register(CNF3,0x04);
#if (DEBUGMODE==1)
Serial.println("Speed=47.619Kps");
#endif
break;

You can see how each case designates a case (I called mine 47 because the Saab I-Bus communicates at 47.619kbps), and by default, this software is not setup to allow us to communicate at the same speed as our Saab I-Bus. So all we're doing here is changing the speed parameters and assigning that speed to “47”. You'll notice that in the Arduino code, I called “CAN.begin(47)”. This is where the Arduino tells the Secuduino to talk to the I-Bus at 47.619kbps.

The "CNF1", "CNF2", and "CNF3" values (registers) we set tell the MCP2515 to talk at 47.619Kbps. These values are different for each speed setting. You can look at the datasheet for this chip and try to decipher it all; it's hard for me to grasp most of it :P

The site http://www.kvaser.com/en/support/bit-timing-calculator.html has a calculator to help you choose the proper register values for what speed and clock values you give it.

Probably more information than you needed/wanted to know, but I think it's good to share none the less.

BlueSaab Software

Here's the code that you can copy & paste into Arduino & write to your chip.

// **START COPY HERE**
// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
// 
// Saab CDC Changer Emulator
// Seth Evans
// 23 Sep 2012
// ----------------------------------------------

#include <CAN.h>

int cdbutton;

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(115200); 
  cdbutton = 0;
  CAN_TxMsg.header.rtr=0;  // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
}

void loop() {
  CDC();
  delay(50);
  if (CAN.CheckNew()){
    CAN_TxMsg.data[0]++;
    CAN.ReadFromDevice(&CAN_RxMsg);
    /*if (CAN_RxMsg.id==0x3C0){
     Serial.print(CAN_RxMsg.id,HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[0],HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[1],HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[2],HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[3],HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[4],HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[5],HEX);
     Serial.print(";");
     Serial.print(CAN_RxMsg.data[6],HEX);
     Serial.print(";");
     Serial.println(CAN_RxMsg.data[7],HEX);
     }*/

    //if (CAN_RxMsg.id==0x3C0 && CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x24){
    if (CAN_RxMsg.id==0x3C0 && CAN_RxMsg.data[1]==0x24){
      cdbutton = 1;
      //Serial.print("cdbutton = ");
      //Serial.println(cdbutton);
      Serial.println("CDC");
    }

    //if (CAN_RxMsg.id==0x3C0 && CAN_RxMsg.data[0]==0x80 && CAN_RxMsg.data[1]==0x14){
    else if (CAN_RxMsg.id==0x3C0 && CAN_RxMsg.data[1]==0x14){
      cdbutton = 0;    
      //Serial.print("cdbutton = ");
      //Serial.println(cdbutton);
      Serial.println("Radio");
    }
  }
  if (cdbutton==1){
    ipod();
  }
}

void CDC(){
  CAN_TxMsg.id=0x3C8;     
  CAN_TxMsg.data[0]=0x20;
  CAN_TxMsg.data[1]=0x00;  
  CAN_TxMsg.data[2]=0x17; 
  CAN_TxMsg.data[3]=0x45;
  CAN_TxMsg.data[4]=0x33;
  CAN_TxMsg.data[5]=0x01;
  CAN_TxMsg.data[6]=0x53;
  CAN_TxMsg.data[7]=0xD0;
  CAN.send(&CAN_TxMsg);
}

void ipod(){
  CAN_TxMsg.id=0x328;     
  CAN_TxMsg.data[0]=0x42;
  CAN_TxMsg.data[1]=0x96;  
  CAN_TxMsg.data[2]=0x02; 
  CAN_TxMsg.data[3]=0x42; // B
  CAN_TxMsg.data[4]=0x6C; // l
  CAN_TxMsg.data[5]=0x75; // u
  CAN_TxMsg.data[6]=0x65; // e
  CAN_TxMsg.data[7]=0x53; // S
  CAN.send(&CAN_TxMsg);
  delay(9);

  CAN_TxMsg.id=0x328;     
  CAN_TxMsg.data[0]=0x01;
  CAN_TxMsg.data[1]=0x96;  
  CAN_TxMsg.data[2]=0x02; 
  CAN_TxMsg.data[3]=0x61; // a
  CAN_TxMsg.data[4]=0x61; // a
  CAN_TxMsg.data[5]=0x62; // b
  CAN_TxMsg.data[6]=0x20; // _
  CAN_TxMsg.data[7]=0x20; // _
  CAN.send(&CAN_TxMsg);
  //delay(10);
  /*
  CAN_TxMsg.id=0x328;     
   CAN_TxMsg.data[0]=0x00;
   CAN_TxMsg.data[1]=0x96;  
   CAN_TxMsg.data[2]=0x02; 
   CAN_TxMsg.data[3]=0x20; // _
   CAN_TxMsg.data[4]=0x00;
   CAN_TxMsg.data[5]=0x00;
   CAN_TxMsg.data[6]=0x00;
   CAN_TxMsg.data[7]=0x00;
   CAN.send(&CAN_TxMsg);
   //delay(10);
   */
}
// **STOP COPY HERE**

Diagrams & Schematics


Here's an overall idea of what we're going to build.


















Here's the CD Changer connector that we're hacking into:













Here's how we're going to connect the Ground Loop Isolator to connect our unbalanced audio out (from the bluetooth module) to the vehicle (balanced audio).






Friday, September 21, 2012

A new upgrade to an old friend

I'll be posting information on how to add an auxiliary input to your 1998 – 2002 Saab 9-3 and 2003 9-3 Convertible, 1994 – 1998 Saab 900 (?) (and similar vehicles), by using the CD Changer (CDC) lines in the trunk. These lines need to be turned on by the car. The car turns these lines on when a special code is sent along the I-Bus. This isn't terribly hard, and not even terribly expensive.

I got most of my information from the following site:
http://pikkupossu.1g.fi/tomi/projects/i-bus/i-bus.html#530

And the few pieces of hardware I'm using:
SecuDuino CANBUS adapter (~$50)

RBBB Kit ($17)(any Arduino board will work)

FTDI cable ($15)(like this one, but there are several available)

Bluetooth stereo audio receiver ($25)

Stereo ground loop isolator ($40)

Other than that, it's just a matter of connecting everything and programming the Arduino. Once that's done, you just power everything up, connect your device to the bluetooth device, and play your music!