Saturday, October 1, 2016

BlueSaab v5.0!

Sorry for not posting here lately; I've been busy on the forum and the FaceBook pages.

Here's v5.0!

This version changes all resistors and caps to 0805 to save space and make room for other things.
Got rid of DFU switch because using signal diodes removes the need for it.
Vertical USB connector for uploading code without the need for an external FTDI cable/adapter.
FTDI cable/adapter is still an option.
Changed to a high temp CAN transceiver, with the future ability for sleep (power savings).
Added 10-pin connector for "future use" ;)

Sunday, July 31, 2016

Version 4.1 is here!

This is a large change from v3.x.

- Switched from through hole atmega328 to surface mount atmega328.
- Added ISP header for programming new SMD 328 bootloader.
- Added on-board FTDI adapter so uploading code is as easy as plugging in a mini USB cable.
-- Still has 6 pin FTDI header so you can still use external FTDI adapter to program.
-- Added status LEDs for on-board FTDI uploading (rx/tx).
- Switched to a new voltage regulator that MUCH more common/easy to find.
-- Added heatsink area for vreg.
- Changed the way the board is powered; now all power inputs go through their own diode, and THEN to the vreg, so they're all isolated, and now the vreg output is a clean 3.3v.

OSHPark v4.1 PCB
Mouser BOM




Tuesday, January 12, 2016

Here's what v3.2 pcb looks like bare, and when finished :)

These pcbs were ordered from DFRobot, specifically asking for blue pcb color; OSHPark only makes pcbs in purple.




Friday, December 18, 2015

PCB v3.2 (BOM unchanged)

I've posted the latest PCB revision in the forum.

Mainly cosmetic changes and improved the layout.

Tuesday, December 15, 2015

BlueSaab v3.1 BOM & PCB

I'm getting a lot of requests for the BOM & PCB, so here they are. I'm also posting this in the forum.

Mouser parts list
http://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=0b60981423

OSHPark pcb (minimum order 3 copies)
https://oshpark.com/shared_projects/63HcVOFe

Thursday, November 5, 2015

BlueSaab Forum

At Karlis' suggestion, I've added a forum to the blog so people can ask questions and add comments easier (I hope) so that it will be more of an interactive discussion regarding the development of the module.

Feel free to start using it :)

The link should be on the right side, under "About Me".

Monday, November 2, 2015

RN52 hardware

Here's ver 2 of the hardware


I've already made a v3, to fix a problem with the USB plug on the bottom (for RN52 firmware upgrades). Firmware upgrades will be rare, and in fact, future upgrades will be done via UART pins, so the USB plug is for RN52 modules with old firmware (v1.10 & older). v1.16 and above will use UART for upgrades.

Karlis has done a smashing job on the software side! The module doesn't drop out at all now, steering wheel controls work with both iPhone and Android phones, and he's also integrated bluetooth sync connect & disconnect controls via the head unit (IHU).

There are still some bugs he wants to work out, and of course, getting artist/track info on the SID is on the to-do list :)

You'll also notice the 3.5mm jack at the top. That's for the Mic input to the RN52, which Karlis & I are planning on using the vehicle's On-Star mic. So once we figure out the best way to do that, he even has the code setup to bring Siri up for a long button press :) So eventually, you'll be able to wire in the car's mic to a 3.5mm plug, and plug that into the module, and be able to talk to Siri at the press of a button (or no button if your phone is charging or you have 6S)!

Feel free to ask questions in the comments; Karlis said he'd try to answer software questions for me :)

And no, I'm not planning on making/selling them. Do you know how much work that would be for me for all of you?! But I can help guide you along the way :)

Wednesday, September 16, 2015

New bluetooth module; RN52

So I've been working with a buddy (Karlis) about getting a better working module. He's determined that the BC05B module I was using isn't a very good module. It's a total PITA to work with, and has very limited documentation.

He suggested that we go with a RN52 module by Microchip.

He's done a lot of testing, and I've laid out a new pcb for that module.

Karlis has also done extensive testing and determined that the CANBUS code had a lot of bugs in it, which he's kindly fixed; Thanks Karlis!!

Prototypes are being built, then tested, then should be released for everyone else to use :)

Monday, June 22, 2015

New software

A fellow Saab enthusiast, Karlis, has kindly offered to work on my crappy code and make it better :)

He's posted his new code up on GitHub here

https://github.com/kveilands/SAAB-CDC/releases/tag/v1.0

Everyone should buy him a beer for his hard work, dealing with my bad code-writing abilities :)

Saturday, January 10, 2015

Bluetooth BOM for those of you who are making one anyway...

http://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=9cf0c26186

The software is still not right, but it does work...

Monday, September 22, 2014

Bluetooth schematics and pcb

As requested, here are the schematics and pcb layout I have so far.

Eagle Schematic
Eagle PCB

This version works, BUT still has issues that I've talked about in the previous posts.



Saturday, May 17, 2014

Working bluetooth prototype!

Here's my working prototype bluetooth module. I'm using the BC05B bluetooth module, which works great.

It still has a lot of bugs, and I may have to redesign/add some things.

PROS:

  1. steering wheel controls for next track & beginning of song/previous track!
  2. 1 device for bluetooth audio/control; NO WIRES!
  3. sound quality is very good (IMHO)
  4. module connects to the last-known-connected device automatically, if it's within range (i.e., if my iPhone 5 was the last device that the module was connected to before I left the car, when I return to the car, it automatically connects when I'm back within range)
  5. when switching to aux mode, the currently connected device starts playing automatically
  6. when switching to radio mode, the currently playing, connected device stops playing (hits the pause button for you so you don't "lose your place" in the track)


CONS:
  1. The volume turns on at medium; i'm trying to get the device to turn the volume up full at power on but no luck yet
  2. still not 100% sure on the pairing sequence for to this module:

  • pairing a new-to-the-module device
  • pairing a new-to-the-module device when the module is currently connected to a different device
  • connecting a known device to the module
  • connecting a known device to the module when the module is currently connected to a diff device

No artist/track info available yet (that i'm aware of) for displaying on the SID; will look into this after I get all the other bugs worked out.

The bottom of my pcb is my attempt to get the volume to turn up at power on, but it's not working, I think because of software...could be the 4066 chip I piggy-backed on top of the other :)

Right now, I have the SRC button on the steering wheel set to put the module into discoverable mode (this only works if you're in Aux/CD changer mode, so you can still use SRC to change between FM1, FM2, and AM1). This has worked pretty good so far between switching connected devices; i.e., when my wife wants to play her music through the car, I hit the SRC button while playing my music, it disconnects from my phone, stops the music [the head unit kicks out of aux mode, back to the radio], the module goes into discoverable mode, she connects to it, and I hit CD twice to get back to aux mode, and it automatically starts playing the last thing she was listening to.

enough talk, pictures!



Sunday, March 2, 2014

How to build your own 3.5mm version of BlueSaab

I get a lot of emails from people on how to build one of these things so here are directions. This involves soldering through-hole components and uploading code to the microprocessor with Arduino.

Buy the parts here (~$40) or anywhere else you find similar stuff:
http://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=89c9334eae

If something is out of stock, you'll either have to wait for more to be ordered or delete it from your cart and buy a suitable substitute. i.e., sometimes the atmega328p is out of stock so I order the atmega328.

If you don't want to buy the blank atmega328 chip, you can pay extra for a 328 with a bootloader preinstalled ($5):
or

Buy one of these ($5):

Buy a CD changer connector ($7/ea, minimum 2, plus S/H: ~$20):

Order the PCB (minimum quantity 3, for $30 shipped):
It takes about 3 weeks for them to get fabbed and shipped.

You'll also need/want 4 screws to hold the PCB to the enclosure; I use 4, 5/16" panhead screws.
I also secure the CD changer connector to the PCB with 1/2" long 4/40 panhead screws and 4/40 locknuts.
  1. flash the bootloader if necessary (I'm not going to cover how to do that here; google it)
  2. Assemble the PCB
  3. Wire up the 3.5mm jack to the PCB with ~5" of wire for each pole
  4. Cut a hole in the enclosure for the CD changer connector and a 1/4" hole for the panel-mount 3.5mm jack.
  5. upload the code with an FTDI adapter/cable
  6. plug it into the cd changer harness (using the adapter cable, if necessary for 9-5 people)
  7. route the 3.5mm cable from the module to the front of the car under the carpet/door sills
You'll probably have to contact me regarding flashing the code...just FYI ;)

To get to the aux in on the head unit, hit the CD button twice. If you have a tape player and cd player (9-5 people), hit CD 3 times. You can also hit SRC button on the steering wheel to cycle.

With the minimum quantity orders for some of these items, it's probably a good idea to get together with another Saab buddy and just build 2 or 3 of them.

Newest version of code

// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// http://BlueSaab.blogspot.com/
// By Seth Evans
// 29 July 2013
// 19 Feb 2014 - added name, sid text, date to output
// ----------------------------------------------

#include <CAN.h>

int cdbutton = 0;
int toggleshuffle = 1;
int mute = 0;
int CDCcmd[] = {
  0xE0,0x00,0x3F,0x31,0xFF,0xFF,0xFF,0xD0};
// first byte needs to be 32 otherwise 2004 9-5 will throw airbag light; it was 0x62
int ninefivecmd[] = {
  0x32,0x00,0x00,0x16,0x01,0x02,0x00,0x00};
int beep[] = {
  0x80,0x04,0x00,0x00,0x00,0x00,0x00,0x00};
int playipod[] = {
  0xFF,0x55,0x04,0x02,0x00,0x00,0x01,0xF9};
int playpauseipod[] = {
  0xFF,0x55,0x03,0x02,0x00,0x01,0xFA};
int stopipod[] = {
  0xFF,0x55,0x04,0x02,0x00,0x00,0x02,0xF8};
int next[] = {
  0xFF,0x55,0x03,0x02,0x00,0x08,0xF3};
int prev[] = {
  0xFF,0x55,0x03,0x02,0x00,0x10,0xEB};
int shuffle[] = {
  0xFF,0x55,0x04,0x02,0x00,0x00,0x80,0x7A};
int repeat[] = {
  0xFF,0x55,0x05,0x02,0x00,0x00,0x00,0x01,0xF8};
int buttonRelease[] = {
  0xFF,0x55,0x03,0x02,0x00,0x00,0xFB};

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(9600);
  //cdbutton = 0;
  //toggleshuffle = 1;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
  // not sure if this is needed; pauses program before it loops
  Serial.println("9-5 Test Code 2");
  Serial.println("Seth Evans - 'Aux In'");
  Serial.println("19 Feb 2014");
  delay(2000);
}

void loop() {
  //cdbutton = 1;
  //PrintBus();
  // 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();
  for (int i = 0; i <= 860; i++) {
    if (CAN.CheckNew()) {
      CAN_TxMsg.data[0]++;
      CAN.ReadFromDevice(&CAN_RxMsg);
      //PrintBus();
      if (CAN_RxMsg.id==0x6A1) {
        CAN_TxMsg.id=0x6A2;     // CD Changer
        for (int c = 0; c < 8; c++) {
          CAN_TxMsg.data[c]=ninefivecmd[c];
        }
        CAN.send(&CAN_TxMsg);
      }

      if (CAN_RxMsg.id==0x3C0) {
        if (CAN_RxMsg.data[0]==0x80) {
          switch (CAN_RxMsg.data[1]) {
          case 0x24:
            cdbutton = 1;
            for (int j = 0; j < 8; j++) {
              CAN_TxMsg.id=0x430;
              CAN_TxMsg.data[j]=beep[j];
            }
            CAN.send(&CAN_TxMsg);
            for (int j = 0; j < 8; j++) {
              Serial.write(byte(playipod[j]));
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
            break;
          case 0x14:
            cdbutton = 0;
            for (int a = 0; a <=2; a++) {
              for (int j = 0; j < 8; j++) {
                CAN_TxMsg.id=0x430;
                CAN_TxMsg.data[j]=beep[j];
              }
              CAN.send(&CAN_TxMsg);
            }
            for (int j = 0; j < 8; j++) {
              Serial.write(byte(stopipod[j]));
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
            //Serial.println("Radio");
            break;
          }
          if (cdbutton == 1) {
            switch (CAN_RxMsg.data[1]) {
            case 0x59: // NXT button signal
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(playpauseipod[j]));
              }
              break;
            case 0x76: // Long press of CD/RDM button
              if (toggleshuffle > 3) {
                toggleshuffle = 1;
              }
              switch (toggleshuffle) {
              case 1:
                for (int j = 0; j < 9; j++) {
                  Serial.write(byte(repeat[j]));
                }
                break;
              case 2:
                for (int j = 0; j < 9; j++) {
                  Serial.write(byte(repeat[j]));
                }
                break;
              case 3:
                for (int j = 0; j < 9; j++) {
                  Serial.write(byte(repeat[j]));
                }
                for (int j = 0; j < 8; j++) {
                  Serial.write(byte(shuffle[j]));
                }
                break;
              }
              toggleshuffle++;
              //break;
            case 0xB1: // Audio mute on?
              for (int j = 0; j < 8; j++) {
                Serial.write(byte(stopipod[j]));
              }
              break;
            case 0xB0: // Audio mute off?
              for (int j = 0; j < 8; j++) {
                Serial.write(byte(playipod[j]));
              }
              break;
            case 0x35: // Seek next (Seek+)?
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(next[j]));
              }
              break;
            case 0x36: // Seek previous (Seek-)?
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(prev[j]));
              }
              break;
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
          }
        }
      }
      if (CAN_RxMsg.id==0x290) {
        if (CAN_RxMsg.data[0]==0x80) {
          if (cdbutton == 1) {
            switch (CAN_RxMsg.data[2]) {
              //case 0x04: // NXT button on wheel
              //for (int j = 0; j < 9; j++) {
              //Serial.write(byte(repeat[j]));
              //}
              //break;
            case 0x10: // Seek+ button on wheel
              //Serial.println("Next");
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(next[j]));
              }
              break;
            case 0x08: // Seek- button on wheel
              //Serial.println("Prev");
              for (int k = 0; k < 7; k++) {
                Serial.write(byte(prev[k]));
              }
              break;
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
          }
        }
      }
    }
    delay(1);
  }
  if (cdbutton==1) {
    //Serial.println("iPod ON");
    iPodOn();
  }
  else {
    //Serial.println("iPod OFF");
    //iPodOff();
    //delay(400);
  }
}

void CDC() {
  CAN_TxMsg.id=0x3C8;     // CD Changer
  for (int c = 0; c < 8; c++) {
    CAN_TxMsg.data[c]=CDCcmd[c];
  }
  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]=0x20; // _
  CAN_TxMsg.data[4]=0x20; // _
  CAN_TxMsg.data[5]=0x20; // _
  CAN_TxMsg.data[6]=0x41; // A
  CAN_TxMsg.data[7]=0x75; // u
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x01; // message 1
  CAN_TxMsg.data[3]=0x78; // x
  CAN_TxMsg.data[4]=0x20; // _
  CAN_TxMsg.data[5]=0x49; // I
  CAN_TxMsg.data[6]=0x6E; // n
  CAN_TxMsg.data[7]=0x20; // _
  CAN.send(&CAN_TxMsg);
  delay(10);

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

  CAN_TxMsg.id=0x348;     // audio text control
  CAN_TxMsg.data[0]=0x11; // 11
  CAN_TxMsg.data[1]=0x02; // Row 2?
  CAN_TxMsg.data[2]=0x05; // 05
  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 PrintBus() {
  if (CAN_RxMsg.id==0x6A2) {
  //if (CAN_RxMsg.data[0]==0x80) {
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    for (int i = 0; i < 8; i++) {
      Serial.print(CAN_RxMsg.data[i],HEX);
      Serial.print(";");
    }
    Serial.println("");
  }
}

Sunday, January 12, 2014

CD Changer Connectors

I recently found out that "The Connector People" sells these connectors online via their website for under $7! I think they have a minimum order of 2...



http://connectorpeople.com/Connector/TYCO-AMP-TE_CONNECTIVITY/8/827229-1

Awesome!

Thursday, January 9, 2014

9-5 adapter harness

I've been told by a few people who have 9-5's, that certain years (not sure which) didn't come with the "regular" cd changer plug; Saab made an adapter though, that converts those cars from a 2-plug harness into the single plug connector.

eEuroParts sells them for less than $12.

I wish I could tell you which years need this cable, but it shouldn't be too hard to figure out if your 9-5 has 2 connectors or 1 under the rear carpet.

Wednesday, January 8, 2014

ATMega328 with bootloader

A reader, Jeff, made a good find that I didn't even think about; Mouser sells ATMega328's with the Arduino bootloader preinstalled! I'm not for sure which bootloader is installed, but it should work.

http://www.mouser.com/ProductDetail/Arduino/A000048/?qs=sGAEpiMZZMs0PWRNvpRp0N8bFGqoofv%2f

Sparkfun sells one with the Optiboot bootloader

https://www.sparkfun.com/products/10524

Thanks for the good find, man! :)

Bluetooth parts list

It's been requested I post the parts list for the bluetooth board, so here it is, minus the CD changer connector of course.

http://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=9cf0c26186

And the bluetooth module is still needed as well.

The code is still in work; I should have my bluetooth modules in a week or so; the first shipment I ordered (50 days ago!) got lost, so I had to ask for a replacement.

Saturday, November 30, 2013

Prototype Bluetooth Module

Here's my prototype; still need to do some more testing, write some software, and I'm waiting on some parts to arrive from China but things are looking promising! :) 


This module is missing the Bluetooth chip