oje
Göteborg
Här sen Apr 2005
Inlägg: 836
Trådstartare
19 Okt 2013 20:57
Senast ändrad av oje, 07 Aug 2018 09:12, ändrad totalt 5 gånger
Äntligen fungerande mätare.
Det har tagit oäntligt med timmar, men skam den som ger sig.
Torrkörning hemma...
...och i garaget
Varvtal, hastighet och vattentemperatur kommer på CAN. Oljetryck och varningslampa fullt analogt och tankmätaren går från analog till digital till analog. Insugstemperatur visas på laddtrycksmätaren (20degC = 0.2bar). Oljenivågivaren är lite jobbigt då den kräver höga ström och en lite klurigare mätmetod, så den får vänta. Batterivarningslampan visar förutom låg batterispänning även låg kylvatten, låg bromsvätska och hög kylvattentemperatur. Senare skall den även varna för "check engine" och ABS problem. Inte illa för en gammal folka.
Allt körs via ett Arduino Mega board med CAN interface och enkla slutsteg till de flesta in- och utgångarna.
Jag lägger upp arduino programmet här. Mest för mig själv, men även för andra nerds. Programmet utvecklas hela tiden, men som det är nu fungerar det mesta.
|
// PC: Mega 2560 on COM3 (Bluetooth COM4 code:1234)
#include "mcp_can.h"
#include <SPI.h>
#include <stdio.h>
//noToneLib//#include <Tone.h>
//#define INT8U unsigned char
// Only necessairy if both revcounter and speedo are run by arduino
// OBS: both Tone.cpp and pins_arduino.h have been modified to get timer 3 and 4 exclusively for speedo and revcounter
// Output pin definitions
#define PIN_OILTEMP 11//11 usually 9, but changed due to timer problems //oiltempmeter is used to show water temp
#define PIN_FUELLVL 12
#define PIN_VEHSPEED 10
//RevCntRemove//#define PIN_ENGSPEED 7
#define PIN_BOOST 8 //8=dummy, usually 11
#define PIN_OILLVL 13
#define PIN_FUELLVLLIGHT 44
#define PIN_BATTLIGHT 5
// Input pin definitions
#define PIN_SENS_BRKFLUIDLVL 30
#define PIN_SENS_FUELLVL 0 //analog
#define PIN_SENS_FUELLVLACT 43
#define PIN_SENS_OILLVL 7 //analog
#define PIN_SENS_OILLVLACT 41
#define PIN_SENS_AMBITEMPACT 42
// input for ambient temperature to be added
#define PIN_SENS_CLNTLVL 4 //analog; old binary pin 34
#define PIN_SENS_BATTVOLT 6 //analog
// Other definitions
#define FRQ_AT300 332 // calculate as pulses/km on speedo devided by 12. Example 4109/12 = 342.
#define odebug 0
#define startuptest 0
#define garagetest 0
#define kaliboillvl 0
#define fueloffset 0 //200-230 or 0
#define clntoilrpmthrs 4000
#define showbreakfluidlvl 1 // activate brake fluid level warning
#define invertclntlvlinput 0 // 0 for Porsche sender; 1 for VW sender
#define sendserialoutput 1 // suppress messages to serial port
#define STARTPAUSE 100 // only used during initialisation
#define STARTNUMSTEPS 20 // only used during initialisation
//NoInterrupt unsigned char Flag_Recv = 0;
unsigned char len = 0;
unsigned char buf[8];
char str[20];
unsigned int msgID=0;
unsigned int VehSpeed=0;
int value=0;
int oldfuellvl=290;
//unsigned long fuellvlsum=0;
//int fuellvlcnt=0;
int oillvl_1 = 0;
int oillvl_memory[10] = {255,255,255,255,255,255,255,255,255,255};
int oillvl_index = 0;
int oillvl_sum = 2550;
int valueByte = 0;
int index = 0;
int index2 = 0;
int index_TimeFunc=0;
int time_30sTimeFunc = 0;
boolean alert_batt = false;
boolean alert_clnt = false;
boolean oillvl_active = false;
boolean inhibit_clnt = false;
boolean init_oillvl = true;
boolean show_clnttemp = true;
boolean canDebug = false;
boolean diagDebug = true;
boolean fuelDebug = false;
boolean oilDebug = false;
boolean pauseDebug = false;
unsigned long time_LastTimeFunc = 0;
unsigned long time_StartOfOilLvl = 0;
unsigned long time_LastVehSpd = 0;
unsigned long time_DiffLastVehSpd = 0;
unsigned long time_BattAlertStart = 0;
//unsigned long time_BattAlertEnd = 0;
int incomingByte = 0;
//noToneLib//Tone tone_VehSpeed;
//RevCntRemove//Tone tone_EngSpeed;
// ------------ initialisation ------------
void setup()
{
//if (sendserialoutput==1){
Serial.begin(9600);
//}
pinMode(PIN_FUELLVLLIGHT,OUTPUT);
pinMode(PIN_BATTLIGHT,OUTPUT);
pinMode(PIN_SENS_FUELLVLACT,OUTPUT);
pinMode(PIN_SENS_OILLVLACT,OUTPUT);
// PIN_SENS_FUELLVL //analog
// pinMode(PIN_SENS_CLNTLVL,INPUT); analog on pin 4, digital on 34
pinMode(PIN_SENS_BRKFLUIDLVL,INPUT);
//noToneLib// tone_VehSpeed.begin(PIN_VEHSPEED);
//RevCntRemove// tone_EngSpeed.begin(PIN_ENGSPEED);
if (startuptest)
{
digitalWrite(PIN_BATTLIGHT, HIGH);
digitalWrite(PIN_FUELLVLLIGHT,HIGH);
for (index=1;index<STARTNUMSTEPS;index++){
//noToneLib// tone_VehSpeed.play(5+ index*312/STARTNUMSTEPS);
//RevCntRemove// tone_EngSpeed.play(5+ index*270/STARTNUMSTEPS);
analogWrite(PIN_OILTEMP, index*255/STARTNUMSTEPS);
analogWrite(PIN_FUELLVL,120+ index*135/STARTNUMSTEPS);
analogWrite(PIN_BOOST, 255-index*200/STARTNUMSTEPS);
analogWrite(PIN_OILLVL, 255-index*200/STARTNUMSTEPS);
delay (STARTPAUSE);
}
digitalWrite(PIN_BATTLIGHT, LOW);
//analogWrite(PIN_BATTLIGHT, 1);
digitalWrite(PIN_FUELLVLLIGHT,LOW);
for (index=STARTNUMSTEPS;index>=1;index--){
//noToneLib// tone_VehSpeed.play(5+ index*312/STARTNUMSTEPS);
//RevCntRemove// tone_EngSpeed.play(5+ index*270/STARTNUMSTEPS);
analogWrite(PIN_OILTEMP, index*255/STARTNUMSTEPS);
analogWrite(PIN_FUELLVL,120+ index*135/STARTNUMSTEPS);
analogWrite(PIN_BOOST, 255-index*200/STARTNUMSTEPS);
analogWrite(PIN_OILLVL, 255-index*200/STARTNUMSTEPS);
delay (STARTPAUSE);
}
}
// Initialise all outputs
//analogWrite(8, 100);
analogWrite(PIN_OILTEMP, 1);
analogWrite(PIN_FUELLVL, 1);
analogWrite(PIN_BOOST, 254);
analogWrite(PIN_OILLVL, 254);
digitalWrite(PIN_BATTLIGHT, LOW);
//analogWrite(PIN_BATTLIGHT, 1);
digitalWrite(PIN_FUELLVLLIGHT,LOW);
digitalWrite(PIN_SENS_OILLVLACT,LOW);
//noToneLib// tone_VehSpeed.stop();
noTone(PIN_VEHSPEED);
//RevCntRemove// tone_EngSpeed.stop();
// initial reading of fuel level for quick start
digitalWrite(PIN_SENS_FUELLVLACT,HIGH);
delay(1);
oldfuellvl=analogRead(PIN_SENS_FUELLVL)+fueloffset; //0bit or 0V = full; 289bit or 1.41V =tom
digitalWrite(PIN_SENS_FUELLVLACT,LOW);
//if (sendserialoutput==1){
Serial.print("Initial fuel level: ");
Serial.println(oldfuellvl);
//}
// delay for CAN
delay(500);
// pre conditioning of oil level sensor
time_StartOfOilLvl=millis();
digitalWrite(PIN_SENS_OILLVLACT,HIGH);
delay(1000+time_StartOfOilLvl-millis());
digitalWrite(PIN_SENS_OILLVLACT,LOW);
CAN.begin(CAN_500KBPS);
//if(CAN.begin(CAN_500KBPS) ==CAN_OK) Serial.print("can init ok!!\r\n");
//else Serial.print("Can init fail!!\r\n");
//NoInterrupt attachInterrupt(0, MCP2515_ISR, FALLING); // interrupt indicates when message is available
//CAN.init_Filt
}
//NoInterrupt void MCP2515_ISR()
//NoInterrupt {
//NoInterrupt Flag_Recv = 1;
//NoInterrupt }
// ------------ main program ------------
void loop()
{
// Check for input from Serial port
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
switch(incomingByte){
case 99: //c
if (canDebug){
Serial.println("Raw CAN dedug is off");
canDebug = false;
}else{
Serial.println("Raw CAN dedug is on");
canDebug = true;
diagDebug = false;
fuelDebug = false;
oilDebug = false;
Serial.println();
Serial.println("MsgID : DataBytes");
}
pauseDebug=false;
break;
case 100: //d
if (diagDebug){
Serial.println("Diagnostic output is off");
diagDebug = false;
}else{
Serial.println("Diagnostic output is on");
diagDebug = true;
}
pauseDebug=false;
break;
case 102: //f
if (fuelDebug){
Serial.println("Raw fuel level debug is off");
fuelDebug = false;
}else{
Serial.println("Raw fuel level debug is on");
fuelDebug = true;
}
pauseDebug=false;
break;
case 111: //o
if (oilDebug){
Serial.println("Oil level calibration debug is off");
oilDebug = false;
}else{
Serial.println("Oil level calibration debug is on");
oilDebug = true;
}
pauseDebug=false;
break;
default:
{
if (pauseDebug){
pauseDebug=false;
}else{
Serial.println("Debug commands:");
Serial.println();
Serial.println("c: Toggle raw CAN debug");
Serial.println("d: Toggle diagnostic output (default on)");
Serial.println("f: Toggle raw fuel level debug");
Serial.println("o: Toggle oil level calibration debug");
Serial.println();
Serial.println("Debug paused. Press any key to continue");
pauseDebug = true;
}
}
}
// read CR and LF if sent. Empty buffer.
if (Serial.available() > 0) {
incomingByte = Serial.read();}
if (Serial.available() > 0) {
incomingByte = Serial.read();}
}
//NoInterrupt if(Flag_Recv) {
// if (CAN.checkReceive())
//NoInterrupt Flag_Recv = 0;
CAN.readMsgBuf(&len, buf);
msgID=CAN.getCanId();
if (canDebug && !pauseDebug) // Print raw CAN messages if in debug mode
{
Serial.print(msgID);
Serial.print(" : ");
for (int i = 0; i < 8; i = i + 1)
{
Serial.print(buf[i], DEC);
Serial.print(" ");
}
Serial.println();
}
// CAN functions are always executed
switch(msgID){
case 416: // ABS ID:1A0 vehSpd
//Serial.println(buf[3]);
VehSpeed= (buf[3]*256+buf[2]);
VehSpeed=VehSpeed/200;
//Serial.println(VehSpeed);
valueByte = map(VehSpeed, 0, 300, 0, FRQ_AT300); // Valuebyte in this case is frequency
time_DiffLastVehSpd=millis()-time_LastVehSpd;
if (valueByte > 30){
if (time_DiffLastVehSpd > 120){
tone(PIN_VEHSPEED,valueByte);
//noToneLib// tone_VehSpeed.play(valueByte); // normal operation
time_LastVehSpd=millis();
}
}
else
{
if (valueByte > 10){
if (time_DiffLastVehSpd > 80){
//time100Hz = (valueByte*time_DiffLastVehSpd)/40;
tone(PIN_VEHSPEED,40,(valueByte*time_DiffLastVehSpd)/40);
time_LastVehSpd=millis();
}
}
else
{
noTone(PIN_VEHSPEED);
time_LastVehSpd=millis();
}
}
// Serial.print("Vehicle speed [km/h]: ");
// Serial.println(value);
break;
case 640: // Motor ID280 engspeed
value=(buf[3]*256+buf[2])/4;
valueByte=value/20; // devided by 60 for rps and times 3 for 6cyl engines
if (valueByte > 32){
//RevCntRemove// tone_EngSpeed.play(valueByte); // normal operation
}
// else
// {
// Serial.print("Engine speed [rpm]: ");
// Serial.println(value);
// }
if (value > clntoilrpmthrs+50 && alert_clnt==false){ //&& show_clnttemp == true ){
show_clnttemp = false;
}
else
{
if (value < clntoilrpmthrs-50){ // && show_clnttemp == false ){
show_clnttemp = true;
}
}
break;
case 649: // Motor ID289 coolant
//value= (buf[1]*2)/3-40;
value= (buf[1]*3)/4-47;
// Serial.print("Coolant Temperature [degC]: ");
// Serial.println(value);
if (inhibit_clnt == false && show_clnttemp == true){
valueByte = map(value, 40, 135, 0, 255); //
valueByte = max(valueByte,0);
analogWrite(PIN_OILTEMP, valueByte);
}
if (time_30sTimeFunc ==30)
{
if (diagDebug && !pauseDebug){
Serial.print("Coolant Temperature [degC]: ");
Serial.println(value);
}
time_30sTimeFunc++;
}
if (value >105)
{alert_clnt=true;
digitalWrite(PIN_BATTLIGHT, HIGH);
//analogWrite(PIN_BATTLIGHT, 254);
if (diagDebug && !pauseDebug){
Serial.println("High coolant temperature !");
Serial.print("Coolant Temperature [degC]: ");
Serial.println(value);
}
}
else
{alert_clnt=false;}
break;
case 664: // Motor IAT
value= (buf[1]*2)/3-40;
//same factor as coolant and oil temperatures?
if (value > 20)
{if (value > 40)
{if (value > 60)
{if (value >80)
{valueByte = map(value, 80, 100, 91, 82);}
else
{valueByte = map(value, 60, 80, 104, 91);}
}
else
{valueByte = map(value, 40, 60, 123, 104);}
}
else
{valueByte = map(value, 20, 40, 156, 123);}
}
else
{valueByte = map(value, 0, 20, 220, 156);}
analogWrite(PIN_BOOST, valueByte);
if (time_30sTimeFunc == 10)
{
if (diagDebug && !pauseDebug){
Serial.print("Intake air temperature [degC]: ");
Serial.println(value);
}
time_30sTimeFunc++;
}
break;
case 1248: // Motor ID oil temperature
//value= (buf[5]*2)/3-40;
value= (buf[5]*3)/4-47;
if (inhibit_clnt == false && show_clnttemp == false){
valueByte = map(value, 60, 155, 0, 255); // oil temperature scale 20deg offset against coolant
valueByte = max(valueByte,0);
analogWrite(PIN_OILTEMP, valueByte);
}
if (time_30sTimeFunc == 20)
{
if (diagDebug && !pauseDebug){
Serial.print("Oil Temperature [degC]: ");
Serial.println(value);
}
time_30sTimeFunc++;
}
break;
case 680: // ABS ID2A8 ABS sensors
break;
case 1952: // Motor unknown
break;
// default:
// {
// }
}
if (oillvl_active == true && millis()-time_StartOfOilLvl>=1000)
{
value=analogRead(PIN_SENS_OILLVL)-oillvl_1; //
valueByte=map(value, 0, 80, 77, 255);
// Serial.print("Oil Level Act: ");
// Serial.println(valueByte);
if (init_oillvl==true){
for (index=0;index<=9;index++){
oillvl_memory[index]=valueByte;
}
oillvl_sum=valueByte*10;
init_oillvl=false;
}
oillvl_sum = oillvl_sum - oillvl_memory[oillvl_index] + valueByte;
oillvl_memory[oillvl_index]=valueByte;
if (oillvl_index < 9)
{oillvl_index++;}
else
{oillvl_index = 0;}
//oillvl_sum = oillvl_sum + valueByte; // oillvl_memory[oillvl_index];
valueByte = oillvl_sum/10;
// Serial.print("Oil Level Average: ");
// Serial.println(valueByte);
analogWrite(PIN_OILLVL, valueByte); // full 77-87bit; empty 194-255bit
digitalWrite(PIN_SENS_OILLVLACT,LOW);
oillvl_active = false;
}
// time based functions are executed every 100ms
// every time based function is executed about once per second
if (millis()-time_LastTimeFunc > 100)
{
index_TimeFunc++;
switch(index_TimeFunc){
case 1: // fuel level
digitalWrite(PIN_SENS_FUELLVLACT,HIGH);
delay(1);
value=analogRead(PIN_SENS_FUELLVL)+fueloffset; //0bit or 0V = full; 289bit or 1.41V =tom
digitalWrite(PIN_SENS_FUELLVLACT,LOW);
if (value > oldfuellvl && oldfuellvl<255){
oldfuellvl=oldfuellvl+1;
}else{
if(value < oldfuellvl && oldfuellvl>0){
oldfuellvl=oldfuellvl-1;
}
}
//valueByte = map(oldfuellvl, 250, 15, 115, 255);
if (oldfuellvl > 71)
{if (oldfuellvl > 117)
{if (oldfuellvl > 153)
{if (oldfuellvl >227)
{valueByte = map(oldfuellvl, 227, 250, 128, 110);}
else
{valueByte = map(oldfuellvl, 153, 227, 148, 128);}
}
else
{valueByte = map(oldfuellvl, 117, 153, 166, 148);}
}
else
{valueByte = map(oldfuellvl, 71, 117, 200, 166);}
}
else
{valueByte = map(oldfuellvl, 15, 71, 255, 200);}
valueByte = min(valueByte,255);
analogWrite(PIN_FUELLVL, valueByte); //revised 4/4 255bit; 3/4 200bit; 2/4 158bit; 1/4 140bit; empty 128bit //old 4/4 255bit; 3/4 200bit; 2/4 160bit; empty 131bit
if (oldfuellvl > 212) { // Warning below 10liters //(valueByte < 135) {
digitalWrite(PIN_FUELLVLLIGHT,HIGH);
}else{
digitalWrite(PIN_FUELLVLLIGHT,LOW);
}
if (fuelDebug && !pauseDebug){
Serial.print("Fuel level (raw): ");
Serial.println(value);
}
break;
case 2: // coolant level
// value=analogRead(PIN_SENS_CLNTLVL);
// Serial.println(value);
value=analogRead(PIN_SENS_CLNTLVL);
if (((value>900)&&(invertclntlvlinput==1)) || ((value<100)&&(invertclntlvlinput==0))) //high = not GND = open circuit
{ analogWrite(PIN_OILTEMP, 254); // shows water temperature
digitalWrite(PIN_BATTLIGHT, HIGH); // active during 200ms
//analogWrite(PIN_BATTLIGHT, 254);
if (diagDebug && !pauseDebug)
{Serial.println("Low coolant level!");}
inhibit_clnt = true;
}
break;
case 3: // battery voltage
value=analogRead(PIN_SENS_BATTVOLT); //
if (time_30sTimeFunc == 1 && diagDebug && !pauseDebug)
{
valueByte=73.5*value/4.8128;
Serial.print("Battery voltage [mv]: ");
Serial.println(valueByte);
}
if (value < 753) // 720 = 11V 740 = 11.3V 753 =11.5V
// if 11V limit is not good enough time counters for activation and deactivation of lamp could be introduced.
{
if (alert_batt==false){time_BattAlertStart=millis();}
if (millis()-time_BattAlertStart > 5000){ // wait until voltage is low for more than 5s
digitalWrite(PIN_BATTLIGHT, HIGH);}
//analogWrite(PIN_BATTLIGHT, 254);
alert_batt=true;
if (diagDebug && !pauseDebug){
Serial.println("Low battery voltage!");
valueByte=73.5*value/4.8128;
Serial.print("Battery voltage [mv]: ");
Serial.println(valueByte);
}
}
else
{alert_batt=false;}
break;
case 4: // reset coolant alert
inhibit_clnt = false;
if (alert_batt ==false && alert_clnt ==false){
digitalWrite(PIN_BATTLIGHT, LOW);
//analogWrite(PIN_BATTLIGHT, 1);
}
break;
case 5:
// fuel once more ??
break;
case 6: // oil level
if (time_30sTimeFunc == 5 || time_30sTimeFunc == 15 || time_30sTimeFunc == 25)
{
if (!oilDebug){ //delete this row for real SW
time_StartOfOilLvl=millis();
digitalWrite(PIN_SENS_OILLVLACT,HIGH);
delay(2);
oillvl_1=analogRead(PIN_SENS_OILLVL); //
oillvl_active=true;
} //delete this row for real SW
if (oilDebug && !pauseDebug)
{
Serial.println("oil level sensor data");
time_StartOfOilLvl=millis();
value=analogRead(PIN_SENS_OILLVL); //
// Serial.print("Oil Time ");
Serial.print(millis()-time_StartOfOilLvl);
Serial.print(", ");
// Serial.print(" Oil bit ");
Serial.println(value);
//oillvl_1=value;
// valueByte=73.5*value/4.8128;
// Serial.print(" Oil Volt ");
// Serial.print(valueByte);
// Serial.print(" Oil ohm ");
// Serial.println(valueByte/258);
//-- for(index2=10;index2>0;index2--) {
digitalWrite(PIN_SENS_OILLVLACT,HIGH);
for (index=1;index<5000;index++){
// delay(2);
value=analogRead(PIN_SENS_OILLVL); //
// Serial.print("Oil Time ");
Serial.print(millis()-time_StartOfOilLvl);
// Serial.print(" Oil bit ");
Serial.print(", ");
Serial.println(value);
// valueByte=73.5*value/4.8128;
// Serial.print(" Oil Volt ");
// Serial.print(valueByte);
// Serial.print(" Oil ohm ");
// Serial.println(valueByte/258);
}
digitalWrite(PIN_SENS_OILLVLACT,LOW);
delay(index2*1000);
delay(20000);
time_StartOfOilLvl=millis();
digitalWrite(PIN_SENS_OILLVLACT,HIGH);
delay(2);
oillvl_1=analogRead(PIN_SENS_OILLVL); //
// oillvl_active=true;
delay(1000);
value=analogRead(PIN_SENS_OILLVL)-oillvl_1; //
Serial.print("Diff after 1000ms : ");
Serial.println(value);
valueByte=map(value, 0, 80, 77, 255);
analogWrite(PIN_OILLVL, valueByte); // full 77-87bit; empty 194-255bit
digitalWrite(PIN_SENS_OILLVLACT,LOW);
//oillvl_active = false;
//-- }
} // end of calibration logic
}
break;
case 7: // brake fluid level
if (digitalRead(PIN_SENS_BRKFLUIDLVL)==LOW) //low = GND
{
if (showbreakfluidlvl == 1){
digitalWrite(PIN_BATTLIGHT, HIGH); // active during 200ms
//analogWrite(PIN_BATTLIGHT, 254);
}
if (diagDebug && !pauseDebug){Serial.println("Low break fluid level!");}
}
break;
case 8:
break;
case 9: // reset brake fluid level
if (alert_batt ==false && alert_clnt ==false){
digitalWrite(PIN_BATTLIGHT, LOW);
//analogWrite(PIN_BATTLIGHT, 1);
}
break;
case 10: // count up for 30s timer
index_TimeFunc=0;
time_30sTimeFunc++;
if (time_30sTimeFunc >30){
time_30sTimeFunc=0;
}
break;
}
time_LastTimeFunc=millis();
}
// Serial.println(time_30sTimeFunc); //debugjux
}
|
_________________
|