Hi Matus
I've done a similar thing with help from Per Boddum.
We have the Vems protocol adapted to a Netduino so the netduino can be used to several things. I mainly uses it to drive my A/F display, but it have all the parameters from Vems so can do everything you can think of.
In short, You send an "A" on the TX port, and your Vems will return a string with all data, the trick is to decode the data string, code below.
Below code will request data from VEMS and store it in a set of parameters in your arduino, you then can use for what ever purpose. For my project did I only need the A/F ratio, to make a PWM outpput for my gauge.
static void ReadVEMS() //read parameters from VEMS
{
port.Write(System.Text.Encoding.UTF8.GetBytes("A"), 0, 1); //send "A" on Com1 TX
Thread.Sleep(80);
if (ReadBytes(ref bytes) > 35) //read RX if exceed 35 bytes
{
MsDatabase.Decode(ref bytes); //update MSdatabase
}
}
namespace TVR_PC
{
public class MsDatabase
{
const bool AfrDisplay = false;
const bool Celcius = true;
public struct VemsDataStruc
{
public Byte Seconds;
public Byte squirtBitflag;
public Byte engineBitflag;
public Byte Baro;
public UInt16 Map;
public Byte Mat;
public Byte Clt;
public Byte Tps;
public Byte Battery;
public Byte Ego1;
public Byte egoCorrection;
public Byte airCorrection;
public Byte warmupEnrich;
public UInt16 rpm;
public UInt16 pulseWidth1;
public Byte baroCorrection;
public Byte gammaEnrich;
public Byte veCurr1;
public Byte dwell;
public Byte advance;
public Byte idleDC;
// ikke protokol relateret flags
public bool ready;
public bool crank;
public bool startWarmup;
public bool warmup;
public bool accel;
public bool decel;
}
public static VemsDataStruc VemsData;
MsDatabase()
{
}
static public void Decode(ref byte[] aBuf)
{
VemsData.Seconds = aBuf[0];
VemsData.squirtBitflag = aBuf[1];
VemsData.engineBitflag = aBuf[2];
VemsData.Baro = aBuf[3];
VemsData.Map = aBuf[4];
VemsData.Map = (UInt16)(VemsData.Map <<
;
VemsData.Map |= aBuf[5] ;
VemsData.Mat = aBuf[6];
VemsData.Clt = aBuf[7];
VemsData.Tps = aBuf[8];
VemsData.Battery = aBuf[9];
VemsData.Ego1 = aBuf[10];
VemsData.egoCorrection = aBuf[11];
VemsData.airCorrection = aBuf[12];
VemsData.warmupEnrich = aBuf[13];
VemsData.rpm = aBuf[14];
VemsData.rpm = (UInt16)(VemsData.rpm <<
;
VemsData.rpm |= aBuf[15];
VemsData.pulseWidth1 = aBuf[16];
VemsData.baroCorrection = aBuf[18];
VemsData.gammaEnrich = aBuf[19];
VemsData.veCurr1 = aBuf[20];
VemsData.dwell = aBuf[21];
VemsData.advance = aBuf[22];
VemsData.idleDC = aBuf[23];
// mask flags
VemsData.ready = (VemsData.engineBitflag & 0x01) == 0x01;
VemsData.crank = (VemsData.engineBitflag & 0x02) == 0x02;
VemsData.startWarmup = (VemsData.engineBitflag & 0x04) == 0x04;
VemsData.warmup = (VemsData.engineBitflag & 0x08) == 0x08;
VemsData.accel = (VemsData.engineBitflag & 0x10) == 0x10;
VemsData.decel = (VemsData.engineBitflag & 0x20) == 0x20;
}
static public double Egoafr(double egoread)
{
double v1 = 14.7 * ((egoread > 211) ? ((egoread + 47.5) / 16 / 14.7) : (egoread + 306) / 470);
return v1;
}
static public double Temperature(double aValue)
{
double v1 = (aValue - 100);
return v1;
}
static public double FuelConsumption(int rpm, double pulseWidth, double roadSpeed)
{
/*
int nCylinders = 8;
int ccMin = 250;
double lagtime = 0.1;
Byte divider = 2; // alternating=1
*/
int nCylinders = 6;
int ccMin = 250;
double lagtime = 0.1;
int divider = 1;
double kml;
double l_100km;
double lphr;
double ccPhr;
double ccPerMin;
double pulseWidthInMinute;
pulseWidthInMinute = (pulseWidth - lagtime) / 60000.0;
ccPerMin = rpm * (nCylinders / (divider * 2.0)) * pulseWidthInMinute * ccMin;
ccPhr = ccPerMin * 60.0;
lphr = ccPhr / 1000.0;
l_100km = (lphr * 100.0) / roadSpeed;
kml = 100.0 / l_100km;
return l_100km;
}
}
}