07/11/2021 at 14:49 •
After a reeeeally long time I managed to get the firmware working with my custom PCB. PCB design has some flaws so there is still a potential for revision 2 of the PCB. I added an option to erase bonded devices and start pairing new one - use a button on PCB or hold mute button on the steering wheel for >3 seconds. Made a lot of tweaks to internal workings of the firmware and device behavior. Additional 10k resistor and 2.2u capacitor is needed as a power-on-reset on MCUs reset line to start properly, without it device is working but is not receiving CAN frames (maybe erratic initialization of MCP2515 on power-up?). Got it in my car conneted to OBD2 port and really happy with how it works. Spotify starts automatically on my phone after first button press to change song - nice not-intended feature :D
I'm happy with how it turned out, feel free to leave any comments either here or on my github. Maybe I will test other GM/Opel cars and update compatibility ;)
04/04/2021 at 12:22 •
Due to some free time during holidays I managed to get my hands dirty again in this project.
Pile of jumper wires and free hanging PCBs grew ever more since last time.
Because of a lot of stupid mistakes and copy-pasted code, writing MCP2515 driver was a real pain in the ass. Since functionality I need from the chip is not much extensive, I developed my own minimalistic solution heavily inspired by open-usb-can project and arduino library for MCP2515.
Overall I'm only initializing the chip, masks and filters, and one receive buffer(for now I guess). At last I started receiving some valid CAN frames in my logs.
First time a song switched was pretty magical. Also I figured I might have overengineered a simple task of changing a song on my PC :D
Code already got published to my GitHub, all I have to do now is design a proper PCB and give the software more polish. Maybe in not much time I could finally enjoy music while driving without distracting myself while driving.
See ya later and hope Episode 4 will be the last. Also I'm dedicating this episode to Gabe Newell, you know we want it! :P
02/04/2021 at 12:44 •
Since Raspberry Pi is capable of doing all the things like Bluetooth LE and CANBUS, i consider it too easy in execution and too overkill hardware-wise. This project is intended to be a simple, minimalistic device so highly embedded microcontroller with most needed functions and peripherals on-board is needed.
First promising candidate was ESP32 from Espressif, since it has embedded BLE and SJA1000 CAN controller. Problem is, due to hardware limitations involving clock distribution inside the chip, CAN controller can't run slower than 50kbaud. Second problem for me, is that ESP32 is intended to be used more like a module than a chip. This means easier development, but less flexibility when designing a final product.
Since I haven't found any more BLE+CANbus microcontrollers, my attention was drawn more towards BLE enabled ARM microcontrollers. After some research I established that the best way to get started was Nordic Semi NRF5 family. Chips are already for some time on the market, there are a lot of resources available, and Nordic distributes them with free and very extensive SDK (software development kit) and documentation. Price is maybe not the lowest but still attractive, especially for older NRF51xxx family. To simplify my development stage I bought a simple breakout board with NRF51822.
I already set up my firmware development toolchain with GCC (GNU C Cross-Compiler for ARM). Starting this way was a very steep learning curve, but payed off in a lot of gained knowledge, especially about the low-level working of microcontrollers (reset/interrupt vectors, linker scripts, startup). My final setup was Ecplise for C/C++ with Eclipse Embedded CDT plugin. My flash/debug probe was at first a J-Link device, but later I managed to get cheap ST-Link V2 working with help of OpenOCD software. To set up Eclipse IDE, this tutorial is a bit outdated but still helpful. After having a working toolchain I created a first warm-up project to get started with development for this microcontroller. After a lot of included headers from SDK, and learning from examples provided in it, I managed to get my first non-BLE application running - simple UART command line interface running on top of FreeRTOS.
Since NRF51 doesn't come with embedded CAN controller i need an external solution to communicate with vehicle. This time choice was simple - the most popular MCP2515 which I also used earlier with RPi to sniff SWCAN bus on my car. It's a pretty simple and robust chip, also comes with hardware CAN frame filtering, which in my case reduces CAN data processing by MCU to nearly zero since receiving data frame means a change of steering wheel button state - all other data from CANbus is discarded earlier by MCP2515 hardware filter.
After familiarizing with BLE inner workings, and Nordic's SoftDevice software, I already got a working BLE keyboard example running with modified report descriptor to be used as Consumer/Multimedia HID (Human Interface Device). Software wise only thing left is writing C library to support MCP2515 on NRF51 platform, which I'm in the middle of.
I'll keep you posted ;)
01/14/2021 at 18:40 •
Chevy Volt is a very complicated car, also when it comes to it's communication buses. It is equipped with 2 obd2 ports on driver and passenger side. Those ports expose various CAN and SWCAN buses, more about them here.
Mine primary focus is on a low-speed SWCAN bus on pin 1. It is not like a classic CAN bus, because signal is carried on one wire, with signal levels relative to chassis ground. But fortunately standard CAN hardware like transcievers can be interfaced with it. To make it work all grounds have to be connected together, and also CAN LOW termninal has to be connected to ground. CAN HIGH connects to SWCAN (pin 1 in OBD2 connector). More on GMLAN/SWCAN here
To make it all work I have to determine what data gets transmitted on the bus when I press a button on the steering wheel. To do it I made an analyzer from a cheap MCP2515 CAN-SPI module and Raspberry pi. CAN module needed a little modification to work with 3,3V from Pi. With a help of a driver, we can get CAN bus in linux, visible as a native network interface with a help of SocketCAN support in current linux kernel. To analyze captured data we can use Wireshark or command line tools from package can-utils. I choose the second way, but I warn everybody that it's harder to configure, since you have to compile can-utils from source. apt-get on raspberry pi downloads very old version of package, which does not have support for 29-bit CAN IDs. Clone git repository, and This link might help with compilation and installation process. Beware, also a libtool package is needed to execute scripts succesfully)
With working and newest version of can-utils I can start sniffing. I enabled interface can0 with command
sudo ip link set can0 up type can bitrate 33300
and then used cansniffer application from can-utils package
cansniffer can0 -c
I use my raspberry pi without a screen, so all was done via ssh. At first a huge list of CAN IDs transmitting data showed up. But to minimize amount of data transmitted on the CAN bus, I turned vehicle off, opened the drivers door and waited a while for all modules to go to sleep. Then I turned on the radio with a button on dashboard. Big amount of data showed up in cansniffer, but because it disappears after a moment of inactivity (data not changing for given ID), a list cleared itself to a few rows after a moment. After a few clicks on steering wheel I got CAN ID i was searching for.
ID 10438040(hex) is transmitting one byte of data on every steering wheel multimedia button event. Event type is determined by this byte's value:
01-vol up pressed
03-next track pressed
04-previous track pressed
05-audio source pressed
Criuse control buttons seem to be on another CAN bus, or need car to be turned on - i haven't seen any chages when pressing them in cansniffer.
My intent is to use 03, and 04 messages, since rest of them still triggers actions in stock radio/infotainment (on AUX prev/next track does nothing). Next step is to make an embedded sniffer with some microcontroller to sniff data only from 0x10438040 CAN ID.
See ya till next update on project! :)