Resistance to Voltage Converter for Gen 3 ECU Logging

Posts: 155
Joined: Mon Feb 11, 2019 12:48 pm
Location: DFW, Texas

Resistance to Voltage Converter for Gen 3 ECU Logging

Postby jlvaldez » Sat Nov 19, 2022 4:29 am

Hey there all,
decided to use this as a place to put this tool development notes and what not.

What does the tool do:
This tool is designed to take 2 separate inputs for fluid thermistors (specifically GM/Delphi thermistors), and output an analog voltage to the ECU for datalogging over the unused secondary O2 sensor inputs.

Most C5s that get tracked seriously will not have catalytic converters, and the O2 sensors for the post-cat sensors are not connected or installed. The OEM ECU doesn't have many inputs that can be used to recording voltage via OBD logging tools (such as race chrono, for lap data acquisition). This is an idea I had to convert the 2 unused O2 post-cat O2 sensor inputs to temp sensor inputs that I could datalog the voltage for and then convert the voltage back to temperature.

For me, I'm wanting to use these inputs to record differential and transmission temperatures in race chrono by datalogging the post-cat O2 voltages and doing some math on them to derive the temperature.

The challenges:
The O2 sensor input range is 0 to 1 V, so the range is fairly narrow. There also is typically some sort of biasing network with an op amp to 450 mV. I don't believe this to be a problem if you have a strong enough output driver. The other challenge is that finding a purely analog way to convert the resistance to a predictable output voltage that linearized temperature readings was extremely difficult. Due to this, I opted to add a small MCU that would sample the resistance value, calculate the resistance and then could determine the temperature and generate a PWM output that could be filtered to be make an analog DC output voltage.

There are 2 parts to this project: The schematic/board, and the firmware for the MCU.

Circuit design:

I cranked this design out in about 1 hour. It has 4 main components
[*]Power stage: Take 4-28V DC input and regulate it down to 3.3V for MCU and component use
[*]Thermistor analog front end: A simple voltage divider network to sample the thermistor resistance, as well as provide some protection to the MCU I/Os
[*]MCU: The MSP430FR2111 is the brains of the board, sampling the resistance input and generating a PWM output
[*]DAC: Using a 10-bit PWM timer with a 2nd order low pass filter set below 150 Hz to generate a buffered DC analog voltage that the ECU can understand

The power stage uses a DC/DC buck regulator (TI LMR16006YQ3). This is capable of taking all input voltages from 4 V to 40 V and regulating it down to a 3.3V output efficiently. An LDO would generate too much heat due to the power draw of the op amps. It also features a schottky diode to provide reverse battery protection up to 20V (flipped power and ground wires).

The thermistor analog front end uses a 2.49K pull up resistor to 3.3V. This value is selected because this is the nominal value of a delphi temperature sensor at room temp (25C). It provides decent voltage range across temperature that the MCU should be able to sample. The 2.2K series resistor with 1nF capacitor is used to provide a current limiting functionality for over-voltage conditions where the ESD cell will trigger. While it technically provides a low pass filter functionality (-3 DB at ~78 kHz), that is not the primary function). There is a 3.9V zener diode designed to provide protection for the IOs in over-voltage conditions. This will require some testing, the datasheets show that it could have leakages as high as 10 uA at 1V, which would introduce a fairly large sampling error. I will play with this when I get the system in. It might end up being DNPed.

The MCU hardware is fairly simply. It has the standard decoupling capacitors needed, as well as a SPI By Wire (2 wire JTAG like programming interface TI uses) header for debug/programming. P1.3 and P1.4 are used as ADC inputs in the MCU (10-bit ADC right now, but it supports 12-bit. This will be something I have to test). The MCU utilizes P1.0 and P1.2 as ADC reference inputs (at least the option to). There are 2 pairs of outputs for the GPIO usage. P1.6/P2.0 and P1.7/P2.1. These pins are used by the timer module to generate a PWM output. Using the solder/bridge input for 2 GPIO to 1 output gives me the flexibility to choose different GPIOs if needed (due to functionality needs).

DAC stage is the more interesting part of the circuit. The target PWM frequency at 10-bit resolution will be somewhere in the 2 to 8 kHz range. We obviously do not want to see the on/off switching of the GPIO at the ECU. Utilizing a 2nd order low pass filter with a cut off frequency of about 30 Hz. Selecting the resistance and capacitance values is fairly straight forward, but the goal is to keep resistance low enough such that the series resistance does not affect the voltage seen by the buffer too much (since all op amps have an input bias current, which is the amount of current they "consume" on the + or - pins). The other balancing act is keeping capacitors small enough to fit on the board with ease. The output of the 2nd stage low pass filter is fed into a non-inverting op amp (the LMV358, a dual channel op amp package supporting 3.3V single ended supply with rail-to-rail capabilities). The Op amp is another choice because I need an op amp that can be supplied with a 0V and 3.3V input (instead of the usual +/- supply requirements) and can drive rail to rail. The output of the op amp has 2 100-ohm series resistors and a clamping zener diode to provide some protection to the op amp's driver, since this pin will be directly connected to a long wire that runs to the ECU.

Cranking out a quick and dirty layout in 1-2 hours resulted in this:
pcb.jpeg (30.64 KiB) Viewed 2392 times

It's far from ideal, with the long narrow power wire trace that breaks up the ground plane, but it is a 2 layer board that's small and meets the requirements for JLCPCB's $2/5 board manufacturing. We'll see how it performs.

Firmware wise, it's pretty simple. I cranked out the code last night, and it's less 400 lines of actual code. My github repository for this project is a code composer studio project (for TI MCUs) that is pretty straight forward. There's the main.c file, and it does everything. The easiest way to break it down is as follows

Timers: This MCU has only 1 timer, but has 3 capture and compare registers. This means I have to use this timer to not only start the sample of the ADC, but also the PWM generation. It was not possible to meet both requirements nicely, so I instead have a lazy software counter each time the timer overflows, and once 100 of them occur, we'll have about 100 ms of time elapsed, and then I start an ADC sample. The ADC sampling for each channel happens once every ~200 ms, alternating which channel is sampled every 100 ms.

ADC: Once the ADC samples the input, it copies the ADC value to a global variable and sets a flag for the software to do some math.

The measurement to voltage process: The ADC value samples an analog voltage, knowing the pull up resistance, we can easily calculate the resistance of the thermistor at the input.
The ADC to resistance calculation happens in the calculateResistance() function. It returns a uint32_t resistance value.
Then the resistance value is ran through a look up table with interpolation in the calculateTemperature() function. This returns a temperature (in F, for more resolution, since I do not have floats/doubles). The LUT is set up with various points across the GM delphi sensor calibration range.
Once the temperature is known, the calculateTargetOutputVoltageFromTemp() function will scale the temperature to a target output voltage (in mv) to represent a temperature based on the defines at the top of the file. In my initial version, I use 0C/32F at 0V output and 150C/304F at 1V scale. This function will provide a target mV that's linear across this range for the given temperature value.
The last function, calculatePWMDutyCycleFromTargetOutputVoltage(), takes the target output voltage and converts it into a PWM count based on the PWM resolution and the GPIO voltage defines at the top of the file. It will return the final count value needed to achieve the target mV output.
Once this process takes place, it clears the new sample flag and the ADC is free to update again in the future.

There are a few downsides to this MCU:
1) 1 timer, so i'm fairly limited in being able to efficiently/hardware trigger the ADC and meet my output PWM requirements
2) No hardware multiply or divide functionality, so we'll see how slow these functions are
3) No hardware floating point math. I tried to add floats or doubles, and the resulting supporting library that had to be linked blew the binary size up by >1.8 kB. It no longer fit in memory, so I had to do everything as integer math and be careful about multiplying before i divide and making sure I can't overflow.

Right now everything in the mail to me, so I have yet to try any of this, but I'm hoping it'll work once I get it in.

Git hub links:
Last edited by jlvaldez on Sun Nov 27, 2022 6:00 pm, edited 1 time in total.

Site Admin
User avatar
Posts: 8117
Joined: Sat Feb 28, 2009 8:34 pm

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby antus » Sun Nov 20, 2022 8:57 am

Very interesting. Thanks for sharing and the write up!
Have you read the FAQ? For lots of information and links to significant threads see here: viewtopic.php?f=7&t=1396

Posts: 155
Joined: Mon Feb 11, 2019 12:48 pm
Location: DFW, Texas

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby jlvaldez » Sun Nov 27, 2022 4:43 pm

Got the prototype boards in and assembled them. Realized that 0603 components might have been a mistake with your standard home soldering equipment lol. I do it all the time at work but don't have a great setup at home.
Board soldered
. It's ugly but it's together.

Here's a quick and dirty setup using the C5 transmission thermistor I had laying around.
testing thermistor

Flashed the board and to my surprise everything seems to be working. Checked resistance of thermistor with multimeter, then checked it with the MCU at a breakpoint. You can see the measured resistance. Then it calls a function to look up the temp. From that point it goes through another function which takes some defines that defines the lower and upper limits for voltage and temp output to determine the output target voltage to send to the ECU.

Scope plot
tek00004.png (27.43 KiB) Viewed 2214 times

Here we see 2 waveforms. The raw GPIO PWM output from the MCU (at 1 khz) and the 2nd order low pass filter output in blue.

The MCU binary size is pretty close to the limit of this MCU though... However, it works.

Wonder if it makes sense to rev the board for bigger footprint SMD components for easier soldering and possibly to accept other inputs (such as a voltage input or something).

Next step: To make sure an MCU can actually see this input as expected so that we can datalog it.

Posts: 892
Joined: Sun Apr 10, 2016 9:20 pm

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby kur4o » Sun Nov 27, 2022 6:03 pm

You may already know, that gm temp sensors are not linear and all gm pcm have 2 rc networks, that are switched around 30-40*C and now you got out of 0-5v better resolution.

Posts: 155
Joined: Mon Feb 11, 2019 12:48 pm
Location: DFW, Texas

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby jlvaldez » Sun Nov 27, 2022 6:38 pm

I'm aware they're not linear. Their temp curves are pretty easy to find online, so in the firmware I just have a LUT with 10C step resolution and it'll interpolate between that. I did not know that they switch RC networks to gain accuracy across temperatures, but it makes sense. When I was looking at this, I didn't understand how they kept accuracy across the resistance range.
In my case, I am really only interested in high temps, so it's skewed to be more accurate at mid and higher temperatures. I did some sims when I was trying to select the pull up resistance for the ADC and decided to skew it towards the high side for accuracy. Lower temperatures will be off more, but I'll never be beating on the car when temps are cold, and I live in Texas, where the car will realistically never even see freezing temperatures. In my firmware, I use 0V as freezing temperatures, and will likely even skew that up more to gain more resolution in the area of interest for me (on-track temperatures). No reason the values couldn't be tweaked for someone that might have other interest. The resistance calculation uses a define in my firmware with a defined pull up resistance value, so it's easy to change.

Code: Select all
   const int32_t tempCurve[20][2] = {
                                    { -40, 96044 },
                                    { -30, 53674 },
                                    { -20, 26386 },
                                    { -10, 14822 },
                                    {   0, 91247 },
                                    {  10, 5244  },
                                    {  20, 3277  },
                                    {  30, 2108  },
                                    {  40, 1392  },
                                    {  50, 941   },
                                    {  60, 650   },
                                    {  70, 458   },
                                    {  80, 329   },
                                    {  90, 240   },
                                    { 100, 178   },
                                    { 110, 134   },
                                    { 120, 102   },
                                    { 130, 78    },
                                    { 140, 61    },
                                    { 150, 48    }


The goal of this device is also to linearize the temperature output to the ECU since most dataloggers/transfer functions you can place on voltage inputs will only accept linear functions. I use 0V = 0C and 1V = 150C for my purposes, which is to datalog transmission and differential temperatures pre and post cooler while on track.

Do you happen to have any links to the RC networks used? Quick google doesn't show much, but I found a reference to a 380 ohm used for high temp and 3.5k used for low temp with 30-40C used as the crossover as you mentioned. Very interesting. Makes me think I might want to skew my 2.49k resistors even more and use the 500 ohm resistors I have to firmly plant myself into the high-temperature-use zone. Thanks for that note.

Not sure what you mean by the 0-5V resolution, but unfortunately I'm stuck using 0-1V since this project is aimed at utilizing the (often disconnected) downstream O2 sensor inputs. Those seem to only accept 0-1V in the ECU. It's definitely a trade off, and this is designed with a fairly niche use case in mind. However, again, in firmware everything is set with defines. No reason we couldn't change a few defines and utilize the full VCC output range if desired. I have a track event with the car in less than 1 week, so this is really a mad dash for me to get everything together for my use case ASAP.

Posts: 892
Joined: Sun Apr 10, 2016 9:20 pm

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby kur4o » Sun Nov 27, 2022 8:47 pm

We got that fully hacked for older LT1 pcm, not sure it will be of any use, some tracing on the p59 pcm will be needed. O2s input also goes through some sort of filtering, you`d better do dome simulations to see how the pcm interpret the signals.
A/D conversion can be easily ripped from code. Are you using the 7603 OS.

I am sure there will be extra 0-5v inputs left over on the pcm. There is for sure trans temp channel already, but you need 2 so another unused should be found on hardware and than mapped in software.

Posts: 155
Joined: Mon Feb 11, 2019 12:48 pm
Location: DFW, Texas

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby jlvaldez » Mon Nov 28, 2022 1:18 am

I am using 7603 but I'm more curious about the front end hardware. I can implement my own filtering if needed.

I looked for other inputs that could be used to datalog a 0-5V signal and there is not much.
1) MAP
2) AC sensor

I'm using these both which left my only open inputs as the down stream o2 sensors which only sample 0-1V. So for my purpose of being able to log a PID with my phone datalogger while on track, O2 sensor is my only choice

Posts: 497
Joined: Wed Apr 11, 2018 8:50 am

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby bubba2533 » Mon Nov 28, 2022 10:06 am

The EGR input is another 0-5 volt ADC that could be used.

I haven’t had time, but I was always interested to know if there was a resistor or something that could be swapped out to make the inputs go up to 5 volts as it would be really useful to have extra inputs.

Edit: Also the oil pressure input if not already used.
LS1 Boost OS V3 Here. For feature suggestions post in here Development Thread. Support future development ->Patreon.

Posts: 155
Joined: Mon Feb 11, 2019 12:48 pm
Location: DFW, Texas

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby jlvaldez » Mon Nov 28, 2022 11:02 am

Oil Pressure is used.

Thought EGR on the gen 3 was just an output to the solenoid.

That's a good thought though. My ECU is powered off 3.3V but no reason i couldn't create some gain on the op amp to feed it. Up to 5.

I want to say there's an op amp that biases the O2 sensor input to 450 mV. Not sure how strong the bias is, but it can't be much since the O2 voltage generated is a fairly high impedance driver.

Posts: 497
Joined: Wed Apr 11, 2018 8:50 am

Re: Resistance to Voltage Converter for Gen 3 ECU Logging

Postby bubba2533 » Mon Nov 28, 2022 1:14 pm

EGR also has an input to monitor position as it has closed loop control.

C1 Blue Pin 55 is the 0-5 Volt input pin.
LS1 Boost OS V3 Here. For feature suggestions post in here Development Thread. Support future development ->Patreon.


Return to Tool Development

Who is online

Users browsing this forum: No registered users and 2 guests