I picked up my 370Z CAN hacking project again after others expressed interest on a 370Z forum I frequent. I ported my old VB6 project over to VB.NET and created a few more tools to help. I've also added standard OBD PID polling to use that info to compare with Nissan's custom CAN data. I updated my CAN spreadsheet with new items and corrected a few others. I always keep the latest copy with the latest CAN information I've decoded on my Dropbox here.
Then I started looking into how to get to the undocumented Nissan PIDs. Various websites give bits and pieces of information, but a lot of times they're for different makes or models and nothing seemed to work with my car. Then I came across Swedish Implementation Standard SSF-14230. It relates to vehicle CAN systems and implements ISO-14230 that we use here in the US. You can find free copies using google. It outlines several of the protocols and commands used to access various parts of the CAN network. I was really interested in information on service 22, which is readDataByCommonIdentifier. Others had used this service successfully on Ford and GM cars to access their custom undocumented information.
This service works similarly to service 01, which is used to access the standard PIDs. However, this command takes 2 bytes for the address. This means there are 65,656 possible pieces of data ready to be accessed. The command structure is as follows:
7E0 03 22 XXXX
7E0 is the CAN address for the ECU, 03 is the number of bytes that follow, 22 is the readDataByCommonIdentifier command, and XXXX is the PID that you are requesting from the CAN node. However, sending this message returns the following error message:
7E8 03 7F 22 80
7E8 is the standard reply address from the ECU (7E0 + 8), 03 is the number of bytes that follow, 7F signifies a negative response, 22 is the command I sent that failed, and 80 is the error code for "Service Not Supported In Active Diagnostic Session". This means that the ECU recognizes the command, but the ECU needs to be placed in a different mode in order to act on it. I started researching diagnostic sessions and found there are 256 possible sessions. So I wrote a routine that automatically tried to place the ECU in every single diagnostic session. The command to place the ECU in a diagnostic session is as follows:
7E0 02 10 XX
10 is the startDiagnosticSession command and XX is the session you are requesting. Only 6 diagnostic sessions succeeded: 81, 85, C0, DA, FA, & FB.
I put the ECU in each diagnostic session one by one and tried to send the readDataByCommonIdentifier command from before. I received the same 80 error code for all sessions except for one: diagnostic session C0. Unfortunately, that response gave me a 12 error code. That means "Subfunction Not Supported or Invalid Format". Basically, it recognizes the command, but the parameters I sent with it (the 2 byte PID) are either unknown, not supported, or in an invalid format. That is the most vague error I've ever seen! It doesn't give you any kind of hint on how to fix the problem. I tried all sorts of different formats, added bytes, etc. but kept getting the same error. So I decided it must be in the right format, but there's just no information for that particular PID. I wrote another routine to try every single PID to see what I got.
After letting it run for an hour or so I looked through the logs and found lots of responses. I finally found Nissan's custom PIDs! 224 of them to be exact. I added the full list of supported PIDs to my spreadsheet and I will start trying to decipher them when I can. Please let me know if you are interested in helping. There's a ton of information to go through.
One other hiccup I ran into is that the ECU will drop out of the special diagnostic session and revert to the default session if there is no activity for about 3 seconds. The following command can be sent about every 2.5s to keep the current session active:
7E0 02 3E 01
Command 3E is the "Tester Present" command that lets the ECU know that a tester device is plugged in to the OBD port and to keep the active diagnostic session going. I added 01 to the message because it kept giving me a 12 error (just like I talked about above), which meant I needed some sort of parameter with it. I tried 01 and it responded with a positive response, which is good enough for me. The positive response looks like this:
7E8 01 7E
7E is the response to command 3E (3E + 40).
My LED Bar project uses an Arduino Duo to process button inputs, take analog readings, update the LCD display, and control the LED strips. That's a lot for a little microcontroller to handle and by the time I had all my features finalized I ran out of pins. All I needed was one more pin for a button input from the control panel. There are many ways to solve this problem depending on your project. However, one of the other buttons was already connected to an analog-to-digital converter (ADC) pin on the Arduino, but only using its digital input functionality. So I came up with a simple circuit to take both button inputs on this pin:
The microcontroller pictured above can be any microcontroller, not just an Arduino. When no buttons are pressed the bottom 10k resistor acts as a pull-down and the microcontroller sees 0V. When the left button is pressed 5V is fed directly into the microcontroller. When the right button is pressed it creates a voltage divider and splits the 5V in half, giving 2.5V. Unfortunately, if both buttons are pressed the top resistor is shorted out and it will look like only the left button is pressed. So it's a good idea to either pick two buttons that are not likely to be pressed at the same time or put the most important button on the left side.
In your Arduino project, just throw an analogRead() command in your main loop and use the result to determine which button is pressed. For the example above, the analog reading will be 0 when no buttons are pressed, 512 for the right button, and 1023 for the left button. These values are very spaced part, which makes for a very reliable circuit. I used the following ranges in my code to determine which button is pressed:
No buttons pressed: <256
Right button pressed: ≥256 and ≤768
Left button pressed: >768
Analog readings take much longer than a digital input reading, but my project is not time-sensitive and still responds instantly. In fact, I had to put in a timer scheme similar to debouncing a digital button input to prevent multiple hits on a single button press. This circuit isn't groundbreaking, but hopefully it helps someone out there if they run out of Arduino pins.
Adding More Buttons
The following circuit expands the first example to 4 buttons. You can expand even further, but eventually you'll hit a limit where temperature variations and resistor tolerances will cause unreliable readings.
The ADC readings for the above circuit are as follows:
None: 0 (0V)
Button #1: 255 (1.25V)
Button #2: 511 (2.5V)
Button #3: 769 (3.76V)
Button #4: 1023 (5V)
Simultaneous Button Presses
The following circuit expands the first example to add the ability to detect when both buttons are being pressed. The tradeoff is that the ADC values are closer together, but this shouldn't cause problems.
The ADC readings for the above circuit are as follows:
None: 0 (0V)
Left Button: 393 (1.92V)
Right Button: 511 (2.5V)
Both Buttons: 633 (3.1V)
As you can see, there are many ways to hook up multiple buttons to a single ADC pin. There are many other methods as well. For instance, you could use the internal pull-up resistor instead of the 10k pull-down resistor I used in my examples. The resistors could also be in series for each button so that different buttons engage different numbers of resistors, creating the effect of adding resistance. Experiment and search around online to find the best solution for your project.
Now that the LED Bar is installed and fully functional you can see it in action. These videos show off a few of the LED Bar effects. The first video shows the random shot routine. You just press the red random shot button and a crazy light show starts until a shelf and color are selected. This color matches colored wristbands on each of the bottles. Once it stops you take that shot.
This video shows the sliders in action. There is a red, green, and blue slider. Each one mixes in that color so that any color can be created on the bar LEDs. The demo just shows the panel, but the lights shine off the wall in the background.
This last video shows the flow effect. The colors change randomly and mix in to the next one. Sync is turned off for this video so the two shelves are different colors.
I performed a lot of testing and couldn't get individual RGB LEDs to light up different colored alcohol bottles the way I wanted. So I found some LED strips from Sparkfun and toyed around with them instead. This was much easier than installing individual LEDs into the actual shelves. The LEDs cannot be controlled individually on the strips, but it reduces complexity because I can use Arduino PWM outputs with external MOSFETs to drive them. The top and bottom shelves are independent so I can at least make those different colors.
After I built and tested the new LED bar design on my workbench, I moved everything down to my basement bar. It was a mess of wires just waiting for a spilled drink to destroy it, but it still worked exactly as I had envisioned. Then I threw a party and realized just how much fun an interactive bar can really be. By 'fun', I mean it's basically a hangover inducing robot. The random shot button was a huge hit and everyone tried it several times throughout the night.
After that I started on the actual installation to make everything more professional looking. I stuck the LED strips to the bar shelves using the built in adhesive strips. Then I installed the control panel on a wall above my sink. On the other side of this wall is a small, unfinished room with my furnace and water heater. This made it very easy to cut out a piece of drywall and mount the panel with relatively easy access behind it. I then mounted the PC power supply and electronics on a stud in the utility closet. There's an outlet in the room which makes it easy to power.
There are several display modes that can be selected using the control panel:
Flow: Randomly changes between different colors by color mixing to the next one. The two bar shelves can sync together and show the same color or change independently.
Pulse: Randomly changes between different colors by fading to black before the next one. The two bar shelves can sync together and show the same color or change independently.
Static: Displays a single color. There are several preset colors to choose from or the color sliders can be used to mix a custom color.
Strobe: Strobe light effect using a single color. There are several preset colors to choose from or the color sliders can be used to mix a custom color.
Random: Changes between different display modes. The strobe effect can be turned on or off in the rotation.
You can also press the random shot button at any time to interrupt the current light show and start the random shot selector routine. This will start a red, yellow, green countdown display for the entire bar (similar to a stop light). Then the lights will start rapidly switching between random colors. They switch very fast at first and then gradually slow down. After a set period of time one of the shelves will turn off completely. Then the lights on the remaining shelf will eventually stop on a color. That color will match one of several colored wristbands placed on the alcohol bottles. Each shelf has 7 different wristbands that can be placed on any of the bottles on that shelf. This adds to the fun because the person taking the shot has a little influence on their destiny by where they stick the wristbands. Certain alcohols can be heavily favored and others can be avoided completely.
I'll upload a few videos of the LED Bar in a future post.
I swapped out my head unit last summer. Since then I've been unimpressed with the stock speakers and their lackluster bass. So I thought it would be nice to drop in a little 8" sub to give it a little kick. The problem is that I didn't want a sub box sitting in the back of my car. I looked around and custom enclosures for the Z are pretty expensive. Plus, there are only a couple out there and none of them are that great in my opinion. I searched the 370Z forums and found an example of a sub enclosure that fits inside the spare tire. This makes it look stock at first glance and saves already limited trunk space.
The box is made out of various thicknesses of MDF. All pieces are circular and the sides are actually rings that build up the walls of the box. The speaker terminals are located on the bottom so that the speaker wires can feed up through the wheel spokes. The bottom of the box has a hole for the spare tire mounting stud to hold the tire and enclosure down tight. Unfortunately, this means I'll have to take out the speaker and then the box in order to use my spare tire, but hopefully I won't ever have to do that. Luckily, Nissan provides a screwdriver in the trunk that I can use to remove all of this. Each piece of MDF is glued to the next using Liquid Nails. There are screws coming in from the bottom and the top to keep everything tight. All of the internal seams are also sealed using silicon caulk.
I chose the Pioneer TS-SW841D subwoofer because it has a mounting depth of only 2.5". The box I created has a depth of only 3.5", so this was a key factor in choosing a speaker. The spare tire mounting stud will also be inside the box under the sub. So the actual available depth is just under 3". I chose the Kicker DX250.1 amplifier to power the sub. It's a relatively small amp that can fit behind the seats and in front of the rear strut bar. This will make it completely hidden from view once installed. I also put in some sound dampening mat anywhere I could fit it while I had the interior torn apart. The Nismo suspension makes for a rough and noisy ride so I wanted to knock that down as much as possible since I had the chance.
Another issue I wanted to address is that parallel parking or driving in reverse at all with 15% tint is next to impossible at night. Especially with the already poor visibility of the Z. My head unit supports a backup camera input so I installed one while I had my car torn apart. I purchased this camera from eBay. It was only about $13. It has a 170 degree viewing angle, shows distance markers on the picture, and has a very small form factor. I brought accessory power to it from the back of my head unit since I already had to run the video cable there. The reverse light signal can be found in an orange wire running horizontal across the very back of the car. There are several wires with the same color in that bundle, so a little trial and error was necessary. I mounted the camera next to the license plate light recessed as much as possible to make it less visible.