Having gotten my bricked ECU to talk on the bench again (but not 100% functional) using SHBoot, time to get back up developing.
The Evap sensor routine that I hooked polls the sensor at 60-80ms intervals - too slow to use to read frequency properly in the 50-150Hz range that the GM FlexFuel sensor uses - will convert to 0-5V output to make this work easier on the Evap A35-20 input.
Having a PLX DM6 gauge for wideband display, I decided to use an Arduino Nano ($3 on eBay) to do the following:
1. Read Hz signal from FlexFuel sensor
2. Output 0-5V signal to ECU. The Evap pin is pulled up to 5V without anything attached, so I have initially coded E0 to send 5V and E100 to send 0V
3. Output serial PLX iMFD packet to PLX daisy chain (using Fuel Level sender ID code as I could not find any device ID for a Flex Fuel sensor for the DM6). This needs to be the terminal device in the PLX chain and will display E% as "Fuel Level" on the gauge.
4. Flex fuel sensor can be calibrated using pure gasoline and E85 inputting the frequency reads into the E0 and E85 values in the code before sending to Arduino. The Continental 13577429 sensor that I have reads 55 Hz with gasoline and 131 Hz with E85. I also have a couple of Chinese made 13577379 eBay sensors which have linear output but calibrations are off (80 Hz with gasoline, 150Hz with E85) if anyone wants a cheap working sensor with calibration data, PM me.
Frequency read is based on
FreqMeasure library at PJRC
Arduino code and Nano circuit diagram (it all works):
Code:
//Flex Fuel sensor code
//Input frequency on pin 8 - pulled up to 5V through 1.8K resistor
//V_out pin 3 - 0-5V output through 1.8K resistor with 10uf capacitor to ground
//PLX iMFD serial packet on Tx pin 0 through 3.3V TTL voltage divider (3.3K/6.8K)
#include <Arduino.h>
#include <FreqMeasure.h>
double sum = 0;
int count = 0;
int ethanol_int, V_out_int;
float freq, ethanol, V_out, E_scalar;
float E0 = 50; //calibration data for pure gasoline
float E85 = 135; //calibration data for E85
long P0, P1, Pdelta;
byte PLXpacket[7] {0x80, 0x00, 0x11, 0x00, 0x00, 0x00, 0x40};
//PLX iMFD packet, sent every 100ms:
//0x80 Start byte
//0x00 0x11 Sensor device fuel level
//0x00 Sensor instance
//0x00 0x00 Sensor value (integer, unscaled)
//0x40 Stop byte
void setup()
{
pinMode (3, OUTPUT);
FreqMeasure.begin();
Serial.begin(19200);
P0 = millis();
E_scalar = (E85 - E0) / 85;
}
void loop()
{
if (FreqMeasure.available())
{
// average several readings together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 30)
{
freq = FreqMeasure.countToFrequency(sum / count);
sum = 0;
count = 0;
}
}
ethanol = (freq - E0) / E_scalar; //scale frequency to E% interpolating E0 and E85 values
if (ethanol > 100)
{
ethanol = 100;
}
if (ethanol < 0)
{
ethanol = 0;
}
ethanol_int = (int)ethanol;
V_out = 5 - (0.05 * ethanol);
V_out = 51 * V_out; //scale to 255
V_out_int = (int)V_out; //convert to integer for analogWrite
analogWrite(3, V_out_int); //output V_out as PWM voltage on pin 3
P1 = millis(); //send PLX packet on Tx pin every 100ms
Pdelta = P1 - P0;
if (Pdelta >= 100)
{
P0 = P1;
PLXpacket[5] = ethanol_int; //set data byte in PLX packet to E%
Serial.write(PLXpacket, 7);
}
}