RP2040-based VPW adapter

endjuser

Member
Joined
Jul 7, 2020
Posts
12
Location
PA
I've seen a few folks on this forum experimenting with Arduino-based VPW adapters for interacting with Class 2 messages. I thought I would share one of my own projects, using a $5 Waveshare RP2040 Zero board to implement the VPW protocol using PIO for precise timing:

https://github.com/endjuser/rp2040-vpw

The main advantage of the RP2040 is that it's fast enough to handle 4X VPW (using PIO) and has plenty of available compute to implement your own logic. I'm using it primarily as an in-vehicle data logger to an SD card, but have another one on my workbench for testing/experimentation.

This code was designed for using a MC33390 VPW transceiver IC (level-shifted to 3.3V for the RP2040) to interface with the VPW bus, but for a DIY workbench scenario (e.g. not in-vehicle) you may be able to get away with just level-shifting 3.3V to 7V without using a transceiver chip.
 
  • Like
Reactions: AmpOverload
This comes from a *CHAT* with GPT4ALL (Off Line) in response the Question of Arduino Programming Software Options... using your First Post as the conversation starter:

4XRPWPIOA.jpg4XRPWPIOB.jpg4XRPWPIOC.jpg4XRPWPIOD.jpg

Prompt:

Is there any "Free Off The Shelf" Software available for the Arduino category for this OP’s Project?


"I've seen a few folks on this forum experimenting with Arduino-based VPW adapters for interacting with Class 2 messages. I thought I would share one of my own projects, using a $5 Waveshare RP2040 Zero board to implement the VPW protocol using PIO for precise timing:


The main advantage of the RP2040 is that it's fast enough to handle 4X VPW (using PIO) and has plenty of available compute to implement your own logic. I'm using it primarily as an in-vehicle data logger to an SD card, but have another one on my workbench for testing/experimentation.

This code was designed for using a MC33390 VPW transceiver IC (level-shifted to 3.3V for the RP2040) to interface with the VPW bus, but for a DIY workbench scenario (e.g. not in-vehicle) you may be able to get away with just level-shifting 3.3V to 7V without using a transceiver chip."


GPT4ALL Response:

Yes, there are several "Free Off The Shelf" (FOTS) software options available for the Arduino category that can be used with your project. Here are a few examples:

1. **Arduino IDE**: This is the official integrated development environment (IDE) provided by Arduino. It's free and open-source, allowing you to write code in C/C++ and upload it to various micro-controllers, including the RP2040.

2. **PlatformIO**: A popular alternative to the Arduino IDE, PlatformIO supports a wide range of micro-controllers, including the RP2040. It offers features like project management, library management, and debugging tools.

3. **Visual Studio Code (VSCode)**: While not specifically designed for Arduino, VSCode can be used with various extensions, such as the "Arduino" or "PlatformIO" extension, to create and upload code to micro-controllers.

For your specific use case of implementing VPW protocol using PIO on a RP2040 board:

1. **PIO (Programmable I/O)**: As you've already discovered, PIO is a powerful feature in the RP2040 that allows for precise timing control. You can write custom code to implement the VPW protocol.

2. **RP2040 libraries**: The official Raspberry Pi Foundation provides various libraries and examples for the RP2040 board, including ones related to serial communication (e.g., `rp2040-serial`).

Some other FOTS software options that might be useful in your project:

1. **SD card library**: For logging data to an SD card on the RP2040.
2. **GPIO libraries**: To interact with the GPIO pins of the board.

When choosing a software solution, consider factors like ease of use, community support, and compatibility with your specific hardware setup.

As for using just level-shifting 3.3V to 7V without a transceiver chip on your workbench scenario:

1. **Voltage shifting libraries**: You can find various FOTS libraries that provide voltage shifting functionality (e.g., `levelshifter` or `voltage_shifter`) which might be useful for this specific use case.

Keep in mind that using just level-shifting without a transceiver chip may not be the most reliable solution, especially if you're working with high-speed signals like VPW. However, it can work well for low-to-medium speed applications on your workbench setup.

Prompt:

Can YOU write a program in Python3 that would work with this Arduino System?

GPT4ALL Response:


Here's a basic example of how you could write a Python program to interact with the RP2040 board and implement VPW protocol using PIO. This code assumes you're running on a Raspberry Pi or other Linux-based system.

**Note:** This is just an example, and you'll need to modify it according to your specific requirements and hardware setup.

```python

import time

# Define constants for VPW parameters (adjust as needed)

VPW_BAUD_RATE = 9600 # bits per second

VPW_BIT_PERIOD_US = int(1e6 / VPW_BAUD_RATE) # microseconds

VPW_DATA_BITS = [0, 1] # assume binary data

# Define a function to generate the VPW signal using PIO (simplified example)

def generate_vpw_signal(pio):

for bit in VPW_DATA_BITS:

pio.set_high()

time.sleep(VPW_BIT_PERIOD_US / 2) # high pulse

if bit == 1: # only send a low pulse if the data is '1'

pio.set_low()

time.sleep(VPW_BIT_PERIOD_US / 2)

return

# Define a function to read VPW signal using PIO (simplified example)

def read_vpw_signal(pio):

received_data = []

for _ in range(len(VPW_DATA_BITS)):

while not pio.get():

pass

time.sleep(VPW_BIT_PERIOD_US / 2) # wait for high pulse

if pio.get(): # check if the data is '1'

received_data.append(1)

else:

received_data.append(0)

return received_data

# Initialize PIO (simplified example, adjust according to your setup)

import rp2040pio as pio

pio.init()

pio.set_mode(pio.MODE_OUTPUT)

try:

while True:

# Generate VPW signal for transmission

generate_vpw_signal(pio)

# Read VPW signal from the bus (assuming a simple receiver is connected)

received_data = read_vpw_signal(pio)

print("Received data:", ''.join(map(str, received_data)))

except KeyboardInterrupt:

pio.deinit()

```
This code uses the `rp2040pio` library to interact with the RP2040 board's PIO. It defines two functions: one for generating a VPW signal and another for reading it.

Please note that this is a simplified example and might not work as-is in your specific setup. You'll need to adjust the constants, modify the code according to your hardware configuration (e.g., adding transceiver logic), and ensure proper error handling.

Also, keep in mind that using just level-shifting without a transceiver chip may introduce errors or noise into the signal, which can affect the reliability of data transmission.
 
Last edited:
I've seen a few folks on this forum experimenting with Arduino-based VPW adapters for interacting with Class 2 messages. I thought I would share one of my own projects, using a $5 Waveshare RP2040 Zero board to implement the VPW protocol using PIO for precise timing:

https://github.com/endjuser/rp2040-vpw
A cool project, indeed!

The main advantage of the RP2040 is that it's fast enough to handle 4X VPW (using PIO) and has plenty of available compute to implement your own logic.
I've given almost no thought to VPW 4X mode since I only hear talk about it being used for dumping/programming an ECU. I may experiment more with it at some point in the distant future though.

This code was designed for using a MC33390 VPW transceiver IC (level-shifted to 3.3V for the RP2040) to interface with the VPW bus, but for a DIY workbench scenario (e.g. not in-vehicle) you may be able to get away with just level-shifting 3.3V to 7V without using a transceiver chip.
I wish the MC33390 had been available when I started thinking about implementing a VPW circuit, but I think it's been obsolete/unobtainable now for a long time. I managed to hack Bruce Lightner's circuit (from a cool MPG-gauge project that does VPW comm without a dedicated transceiver) to great effect in my own little project.

I'm using it primarily as an in-vehicle data logger to an SD card, but have another one on my workbench for testing/experimentation.
I've been using my circuit mostly for a VPW-protocol vehicle simulator (frequently coupled with Tech2Win and a VXDIAG VCX Nano), but I'd also started using a 2nd circuit (same exact hardware but with different ATMega328 firmware) as a scantool, with the idea of doing exactly what you've done -- a data-recording scantool. That project was going well, working fine as a scantool but without having yet implemented the actual SD-card recording. But I had to shelve it several months ago for more pressing activities, hopefully to be resumed within a few months.

I've considered abandoning the Atmel/Microchip MCUs for something better, but I've got a lot of "investigative homework" to do first and no time to do it! But RP2040/RP2350 will probably be one of the contenders, so I appreciate you sharing your project and wish you luck with it!
 
  • Like
Reactions: TJBaker57
I wish the MC33390 had been available when I started thinking about implementing a VPW circuit, but I think it's been obsolete/unobtainable now for a long time. I managed to hack Bruce Lightner's circuit (from a cool MPG-gauge project that does VPW comm without a dedicated transceiver) to great effect in my own little project.

That's a great idea to have a hardware simulator!

I imagine you could use similar circuitry to interface the RP2040 with the VPW bus. Essentially the only thing the MC33390 is doing is overvoltage/short protection and wave shaping (rounding the edges) of the output from the microcontroller to reduce ringing on the bus. The PIO input/output is standard J1850 VPW (but at 3.3V)

I've got a software-based simulator that's part of a web-based VPW analysis tool I've been working on for bench testing. I wrote it before I made the RP2040 adapter, so at the moment it uses two cheap ELM-compatible adapters and an OBD2 Y-splitter (one for read and one for write) for comms. Essentially it starts by reading all the blocks/PIDs/DPIDs/memory from a module and saves that to a JSON file for later use. Then I can monitor the VPW bus and simulate the saved device(s). I have a (very ugly) screen full of text boxes that highlights which PIDs/blocks are being requested (e.g. when I have a Tech2 plugged in on a data screen) and I can change the values in real time.

Once I finish my research into functional messages, I'm planning to re-write the useful parts of that tool, along with its VPW decoder, into a public webpage so anyone can use it.
 

Attachments

  • simulator.png
    simulator.png
    88.4 KB · Views: 9
I've got a software-based simulator that's part of a web-based VPW analysis tool I've been working on for bench testing. [...]
Very nice! :thumbsup:

I too have a software simulator, but it's considerably different than yours. (I don't typically mention it here because it's far less relevant on this site than my hardware sim.) To any communicating app, it basically looks like a serial port that it can open and talk to a (fake) scantool. I can simulate any of several vehicles and any of several scantools, all in the software. I've used that software sim far longer than my hardware sim and it's been invaluable over the years in learning OBD2 stuff. But there's no GUI -- it runs in a console window, with user-typed commands to control it, so it's not very user-friendly. I've thought about "GUI-fying" it, but that day will probably never come.

When I started using a VXDIAG VCX Nano and the Tech2Win & GDS2 software that came with it, my hardware sim opened up a whole new world to me, for the GM vehicles.

But lately I've been spending more of my free time on Ford/Lincoln/Mercury, so I may have to work on a J1850-PWM sim next! And I just bought a 3D printer, so I'm learning all I can, with a plan to print some custom cases for my various circuits. So many projects & ideas, so little time! :)

I will definitely have to take a closer look at the RP2040 (etc). Thanks for your input -- very interesting stuff!
 
I've been working on something like this but on SMT32 instead of RP2040, and I used a discrete transmitter instead of the obsolete of the shelf ones. https://github.com/garnerm91/J1850VPW_USB_HW-SW
It's always interesting to see the various hardware implementations of SAE J1850, so thanks for providing another option with your project/schematic!

Page 2 of your PDF schematic shows "L2" with a value of "0 ohm 0805", which I assume is an oversight. Can you please clarify what that was supposed to be?

Also, I'm curious if you've ever seen the SAE J1850 VPW schematic used by (contest winner) Bruce Lightner in the October 2005 issue (#183) of the old "Circuit Cellar" magazine? If you're curious, Bruce has the magazine article on his website:

https://www.lightner.net/lightner/bruce/Lightner-183.pdf

The VPW part of that circuit uses nothing but common, readily available components.

Back in 2023 when I was designing my "HVS-VPW" (Hardware Vehicle Simulator) PCB, I took a look at various VPW circuit designs, including the one in the ELM327 datasheet. I prioritized designs by those that didn't depend on obsolete and/or unobtainable components (like a VPW transceiver), and decided to use the VPW portion of that circuit that Bruce designed, further modified to reduce the component count by 2 resistors (R14 & R17) and 1 capacitor (C5), taking advantage of the fact that the more modern AVR MCUs (compared to the AT90S8515 he used back in 2005) have a built-in reference voltage.

My modified circuit has worked out well for me so far, although it may not conform 100% to the SAE J1850 VPW specification, but probably no less (or more!) than Bruce's original circuit/firmware did. :wink:

I probably won't re-design my HVS-VPW PCB, but if I ever do, I've also considered using a PIC16F145{4,5,9} MCU. I've used that MCU in a previous project. It has built-in USB, which was the attraction for me. I'm no electrical engineer, just a hobbyist, but I think it could reduce the part count in your VPW circuit, since (like the ATMega328 that I used) the PIC16F145{4,5,9} MCU series also has a built-in comparator. So, IIUC, you could drop U1 (CH340C) and U5 (TL331), along with some of their supporting hardware. Just some food for thought, in case it's even mildly helpful or enlightening. (I recall you mentioning a plan to do a series of common PCBs in your video, so I realize that my musings may not be that useful in the end.)

Thanks again for posting your design, including the supporting software and firmware! If I ever find some free time, I'd like to wire up your circuit and compare it to mine/Bruce's on the 'scope, gaining some much-needed STM32 knowledge in the process.

P.S. Many thanks also for your video on repairing GM instrument clusters with weakly lit PRNDL displays! I successfully used that to confidently repair a 2004 Buick Century's cluster a few years ago. I still laugh about that "MELF" = "Most End up Lying on the Floor" comment every time I think about that repair job! :biggrin:

EDIT: Typo fix!
 
Last edited:
Page 2 of your PDF schematic shows "L2" with a value of "0 ohm 0805", which I assume is an oversight. Can you please clarify what that was supposed to be?
L2 was an inductor, but in testing, my rise time was too fast, causing it to ring. It worked correctly within the confines of what is defined as a J1850VPW network (min resistive load and min capacitive load). However, GM's implementation of J1850 does not follow the standard, so it was ringing. It wasn't ringing badly enough to really affect anything, but I was cool with the idea of selling something I knew was broadcasting EMI, so I removed the inductor. The idea behind L1 was to make a low-pass filter to help prevent triggering on noise.

I have not seen that article. I am going to read it now, thanks!

I designed the board for the BOM price point, which is why I used the CH340. It was cheaper to use an STM32C0 with a CH340 than it was to use an STM32 that supports Crystalless USB. The 33-ohm resistors aren't required for that chip; they are used to reduce EMI. D1 is for ESD/TVS protection.

A lot of STM32s do have built-in comparators. I used an actual comparator instead of a microcontroller with it built in for 2 reasons. 1 want someone to be able to just copy and paste page 2 of the SCH and use it with any 3.3V micro. 2nd, the comparator can handle much higher input voltage, making it less susceptible to TVS events. D5 clamps at 19.9V, meaning I would need to divide the input down to a small enough signal to protect the micro if I were going to expose it directly to the bus. That comes out to divide by 6, so 4/6=~0.6 where 4 is roughly the high-level trigger for incoming data. 0.6 is probably too low for a microcontroller-based comparator.

You could overcome this, but not by dividing by 6. Maybe just divide by 2 and put a zener clamp, but a zener doesn't cost much less than a comparator, so we are back to just using an external comparator.

I am not saying all this to say you are wrong for wanting to do it that way; I am just sharing my thought process on why I ended up the way that I did.

Another way I have seen people make a J1850 VPW transceiver is by using optocouplers.
 
  • Like
Reactions: AmpOverload
Page 2 of your PDF schematic shows "L2" with a value of "0 ohm 0805", which I assume is an oversight. Can you please clarify what that was supposed to be?
L2 was an inductor, [...]
Many thanks for your clarifications and additional explanations! I learned a lot from your post! Your expertise far surpasses mine, so I consider myself a humble student here. :)

Another way I have seen people make a J1850 VPW transceiver is by using optocouplers.
I too have seen a VPW design that uses optocouplers -- specifically, this one:

http://www.nerdkits.com/videos/obdii/

I am not saying all this to say you are wrong for wanting to do it that way; I am just sharing my thought process on why I ended up the way that I did.
I have to hand-solder everything, so I probably (unintentionally? irrationally?) lean toward reducing the part count. Maybe one day I'll experiment with solder paste and a reflow oven or a hotplate! :)

I've also got a lot to learn about TVS and making my PCB design less susceptible to "load dump" (etc). My aforementioned 'HVS-VPW' PCB, by design, gets used solely "on the bench", but I also designed a "DIY scantool" that uses the exact same hardware, just with different MCU firmware and with the gender swapped on the 16-pin OBD2 DLC (Diagnostic Link Connector). But to date, I've only used this crude "scantool" on the bench, not yet connected to the harsh electrical environment of an actual vehicle, which will require some additional hardware. My long-term plan is to add an RTC and an SD card, for time-stamped data-logging right off the bus.

Thanks again for sharing your knowledge and experience!
 
I am probably going to rev the design and use MOSFETs instead. I can remove D4 doing that and keep the same BOM cost. I am not sure, though, if I keep D4; I can put some preload on it, which would help with rise time. Maybe someone will come up with a better idea.
LTspice.JPG
That's with MOSFETs; my rise time is still too fast, making an LC tank out of an inductor and a cap that rings. Green trace is the J1850vpw bus, and blue is the microcontroller output.

Removing the inductor eliminates the ring. The easy thing is to just remove the inductor. Motorola used this exact filter in their example designs for J1850vpw, so I am kinda stuck getting my transmitter to work properly with it. Maybe I should just be happy it works. GM didn't actually add capacitive loading, and their networks only have a resistive load of about 4K by the way. "
The total load capacitance (CLOAD) on the J1850 VPW network, as specified in SAE
J1850, must be between 2470 pF and 16544 pF. Likewise, the load resistance (RLOAD) on the network must be between 315 ohm and 1575 ohm. In addition, the network time constant (the product of RLOAD and CLOAD) must not exceed 5.2 ms"

It would be much easier to design something to work within that window than to work from 6 kohm to 315 Ω with an unknown Cload. GMs sloppy implementation of J1850 makes it PIA
 
  • Like
Reactions: AmpOverload

Forum Statistics

Threads
24,250
Posts
648,410
Members
20,689
Latest member
dstairs

Members Online