RPico CAN Interface for Tesla Model 3

    When I built a stereo for my Tesla Model 3 back in 2019, I originally designed it to just bypass the OEM system. I have no control over all the processing and filtering and compressing that Tesla does inside the car's computers, so there's no way I can use the OEM stereo as a source for clean, guaranteed-high-quality sound. So I've always used my iPhone as the source, with a lighting port USB DAC sending uncompressed CD or HD quality audio directly into my aftermarket DSP, which gives me complete control over the signal, end to end. Wonderful.

    However, bypassing the OEM stereo creates a new problem. How do I control the aftermarket system? For an initial quick solution, I glued an aftermarket control knob onto my center display. That gave me volume and bass level controls, all I really cared about. But after a while I got tired of looking at that clunky fix and I started looking for a way to use the car's steering wheel controls to control my aftermarket system, the same way they would control the OEM system. I threw together a solution that tapped into the car's BodyCAN bus, read the steering wheel controls and sleep/wake status, and used those to control my aftermarket stereo's wakeup and volume level. For bass level control I mounted a quadrature encoder inside the center console. To control everything, I used a Texas Instruments TM4C board. When I first learned how to develop embedded systems back in college, the program there used TM4Cs. They're nice. They're pretty full-featured, they cost $20, and over the years I built a lot of projects using those boards. But they never had broad community support, or any support at all beyond the example code from my college courses, there are much more powerful solutions available today for $5 or less, and they're no longer in production. I've shifted all the rest of my hobby projects over to Raspberry Pi Picos, and my car stereo interface was the only TM4C project I had remaining in use.

    For some reason a few weeks ago I decided to rewire parts of my car stereo. I honestly don't remember why. I think I thought of a simpler, easier, more efficient way to do it. Originally I had wires running all over the car, and over time I consolidated most things into the trunk. After I disconnected everything, after I rearranged everything, when I was plugging everything back in, I touched the wrong wire to the wrong pin and burned out the TM4C board that had been in my car for the past four years. That was a common annoyance with the TM4Cs. If you touched a 12V wire to anything anywhere on the board, it would immediately burn out the microscopic LDO that they used to drop USB 5V down to MCU 3.3V and the board was ruined. I didn't have any more TM4Cs in my possession and like I said, they're out of production, so I decided this was a good time to switch over to RPico.

    The only downside of the RPico that I've found is that it doesn't have a CAN controller built in, like the TM4C did. When I first started using RPicos when they first came out, the chip shortage was really bad and general purpose CAN controller and transceiver chips were out of stock everywhere, which is why I didn't switch this project over sooner. But now those chips are available again. I hooked up an MCP2515 board to the RPico, found an existing CAN library, and was able to read the car's BodyCAN with no problems. Then I programmed the RPico to do exactly what the TM4C had done: wake the stereo up when the car wakes up and use the steering wheel left dial to control aftermarket stereo volume. I started to port the code to read the quadrature encoder that I had been using to control bass level when it occurred to me ... the right steering wheel dial isn't being used for anything. If I turn it while I'm driving, nothing happens because there is no function associated with it. It controls following distance when Autopilot is engaged, but I don't and won't use Autopilot. Autopilot is utterly useless and downright dangerous on the windy mountain roads where I live. So I should just use the right dial to control bass level. It has a click, so I can do the exact same control scheme that I was doing with my aftermarket encoder: scroll up and down to move level up and down and click to reset to default level. And then I can get rid of the aftermarket encoder. One less wire running through the car.

    So that's what I have now. It works beautifully. Simpler than ever before. I need to make some decent packaging and mounting for the board. Right now it's just wrapped in masking tape. I also want to look for a better CAN cable to tap into. I've always tapped into the OBD connector in the center console, but almost everything else has been moved into the trunk and I'd like to find a connection in the trunk if there is one. The OEM rear amp doesn't have a CAN connection, only A2B, but I think the charge port cover uses CAN. I'll take a look at that. I can't do anything about 12V supply; that has to go to the penthouse DCDC. And of course the line-out cable from my iPhone has to run all the way up to the front seats. But that's it. Those would be the only connections I'd have outside the trunk. Nice. As always, code is on gitlab.

Update: I looked at the connections coming out of the charging controller in the trunk and it looks like none of them go to the BodyCAN bus that I need for my stereo. I just tested the pins in the connectors. I didn't cut into any wires to check those.