Själva ECU koden
Kod: Markera allt
// Förändrad 2018-12-01 och inlaggd 12/01, aktiv/inaktiv fungerar Denna fil fungarar bra.12/02
// utmärkt. max ändrat till strax under 4000 rpm ua. Tändläget verkar ua ochså.
// nu läser den av alla analogread i följd om 2 och 2.= fungerar!!
// batterispänningens inverkan grovjusterad = fungerar
// en individuell möjlig injustering per spridare finns med. Fungerar
// ändrad till att bara läsa av tand 9. Skall provas
// ändrad till max 2500 rpm om varvpin sätts låg. fungerar
// här är olika justerbara parametrar som påverkar enligt följande:
const byte totaltid = 10; // totaltid för case 15: x * motorns duration (13)(10)
const int tryckminskn = 60; // turbotrycket ställs in här, högre tal = mindre tryck (60)
const int lagstavarv = 450; // tomgångsvarvet 500 uS motsvarar ca 800 Rpm (500)(520)tuffar lite vid 520...nu 450
byte hogstavarv = 110; // fullgasvarvet 100 uS motsvarar ca 4200 RPM (100)(160 = ca 2500 RPM) (110)
const byte aggrfaktorlag = 3; // hur mycket spridar PWM skall öka vid belastning mellanvarv (6)(4)(3)
const byte aggrfaktorhog = 7; // hur mycket spridar PWM skall öka vid belastning högvarv (7)
const int minfart = 3800; // lägsta startvarv för spridarfunktion (3300 uS = 152 RPM)(3800 = 131 RPM)
const byte startmangd = 13; // avgör max startmäng 9 = 1,5 vevaxelpulser = 9 grader ontid (9)(11) <-------------provat 13 (startmotorvarv)
const float maxdeltalag = 3.0; // max insprutningstid mellanvarv mdutation * 6.0 ger 3 vevaxelpulser = 18 gr ontid (9.0)(6.0)(4.0)<---------proat 3.0
const byte lagmangd = 4; // max lågvarvsmängd 4 = 2 vevaxelpulser = 12 grader ontid (under tomgångsvarv)(4)
const int tid1 = 2500; // tid 1 är för att hitta pulsluckan vid start/lågvarv < 300 RPM (2500)
const int tid2 = 1500; // tid 2 är för att hitta pulsluckan i mellanvarv 1100--> (1500)
const int tid3 = 1000; // tid 3 är för att hitta pulsluckan i alla andra förekommande varv 1100--> (1000)
const int tid4 = 100; // tid 4 är för att hitta pulsluckan på högsta varvtal (100)
const float senasteinspr = 6.0; // senaste insprutningstid (vid tomgång)(7.0 = 3,5 vevaxelpulser = 21 grader delaytid(7.0) 5.0 <--------------prova
const byte tidigasteinspr =110; // kortaste insprutningsfördröjning (vid maxvarv)(60=t19=24grFödp)(30=t20=18grFödp)(60)(100)max 255
const int sprtroghet = 400; // ett grundvärde för spridarnas påslagsfördröjning i uS. (400)
const int sprdiff1 = 0; // en ev tidigareläggning av spridare 1 om den avviker i startfördröjning (uS)
const int sprdiff2 = 0; // en ev tidigareläggning av spridare 2 om den avviker i startfördröjning (uS)
const int sprdiff3 = 0; // en ev tidigareläggning av spridare 3 om den avviker i startfördröjning (uS)
const int sprdiff4 = 0; //20 // en ev tidigareläggning av spridare 4 om den avviker i startfördröjning (uS)
const byte maxstopp = 60; // en varvtalsbegränsare som + på högstavarv (microsek)(60)
int vevpin = 2; // pulsingång vevaxelgivare, (aktivt hög).
int kampin = 3; // kamaxelgivarens ingång, (aktivt låg).
int varvpin = 4; // en varvbegränsningspinne
int pulsutpin = 7; // pulsutgång 2 pulser per varv (kontrollutgång för övervakningen).
int sprpins [] ={11,10,9,8}; // till spridarna (blir aktivt höga)
int Disable = 12; // aktivt hög stoppar utsignalerna till spridarna
int sprControl = 13; // kontrollutgång för spridare till övervakningen
unsigned long delvalue; // delvärde av pulstid i uS.
unsigned int ondelay; // tillslagsfördröjning spridare i uS (mS)(inne i case 18)
long puls, priv, delta; // senaste, föregående och delta (totalöppningstid) i uS(mS)
float error; // error = varvfelet i decimalform
float starttandf, finKorr; // starttand i decimalform för att få startfördröjningstid och finkorrigering av öppninstiden +-.
float mduration, bduration; // varvfelet = motorduration/börduration i decimalform
byte tand = 0; // vevpin räknare 0 till 28, i alla fall till 26
byte gas; // gas 0-255
byte pekare = 0 ; // pekare för att välja rätt spridarutgång, startar på 0
byte kamtand = 0; // Kamtand för att sluta detektera kamaxelgivaren efter 51 (max 255)tänder, startar på 0
int fasttid = 300; // Fasttid = tid,tid2 eller tid3 beroende på varvtal, startar alltid på 300 uS
byte analogval; // En switch/case till analogread
// int turbotryck; // turbotryck
int battVolt = 400; // mäter systemspänning till spridare
// int variabel1; // bra att ha variabel 1
// int variabel2; // bra att ha variabel 2
// int ambTemp = 300; // mäter omgivningstemperaturen
// int atmtryck = 330; // mäter atmosfärstrycket
int sprstartkorr = 400; // spridarstartkorregering i uS, spänningsberoende (400)
int sprtroghetklar; // korrektion för den inbyggda påslagströgheten i spridarna
int spridardiff; // en ev. individuell spridartid korrigering (uS)
void setup()
{
pinMode(vevpin, INPUT_PULLUP); // satt vevpin som ingång (2) Testar nu med pullup...
pinMode(kampin, INPUT); // satt kampin som ingång (3)
pinMode(sprpins[pekare], OUTPUT); // spridarutgångar satta som arrey (11,10,9,8)
pinMode(sprControl, OUTPUT); // en spridarutgång som blir hög varje gång en spridare öppnas (13)(Övervakningen)
pinMode(Disable, INPUT_PULLUP); // ECU väljare Hög = on, Låg = off (12)
pinMode(pulsutpin, OUTPUT); // satt pulsutpin som utgång (2 pulser per varv)(7)(övervakningen)
pinMode(varvpin, INPUT_PULLUP); // satt varvpin som ingång (4) varvtalsbegränsare
// Serial.begin(250000);
}
//______________________________________________________________________
void loop()
{
// Det får plats ca 1700 klockcykler mellan varje x tal(case) (1 till 17)
// Det tar lite mer än 100 mikrosek att läsa av en analogingång,
// så ingen analogRead här, skall vara i case 17!
if (digitalRead(Disable)==LOW) // Disable låg stänger av ECU:n och gör den passiv
{
delta = 0; // Genom att delta (insprutningstid) förblir 0.
pinMode(sprpins[pekare], INPUT); // Gör om spridarutgångarna till ingångar för att ej belasta
pinMode(sprControl, INPUT); // Gör om spridarcontrollen till ingång för att ej belasta
}
else
{
pinMode(sprpins[pekare], OUTPUT); // Vid aktiv igen så gäller spridarutgångarna som utgångar igen.
pinMode(sprControl, OUTPUT); // Vid aktiv så gäller spridarcontrollen som utgång igen
} //*Detta är normalläget, samma som i setup*
if(digitalRead(varvpin)==LOW) // om varvpin är låg
{
hogstavarv = hogstavarv + maxstopp; // så blir maxvarv tex 2500 Rpm
}
else
{
// maxvarv blir 4200 Rpm
}
if (kamtand <= 256) // när kamtanden är räknad 251 gånger så slutar den detektera kampin.
{
if (digitalRead(kampin)== HIGH)// varje gång kamaxelns hempuls detekteras så resetas 4 räknaren
{
pekare = 0; // resetas till 0. Denna funktion läses utanför switch.
kamtand ++; // räknar upp kamtandräknaren vid varje kampin låg upp till max.
}
}
switch (tand) // här startar switch och case, tandräknaren stegar fram ett steg (case)
{
case 1: // Detta case ger första pulstid
delvalue = priv; // Första pulstid läggs in som deltid 1
break;
case 2: // Detta case ger andra pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
sprstartkorr =map(battVolt, 150, 700, 0, 400); // batterispänningen blir spridartidskorrigering
sprstartkorr = constrain(sprstartkorr,200,400);
break;
case 3: // Detta case ger tredje pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 4: // Detta case ger fjärde pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 5: // Detta case ger femte pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 6: // Detta case ger sexte pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 7: // Detta case ger sjunde pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 8: // Detta case ger motorns börvärde från gaspoten som blir lägsta och högsta varvtal
// och åttonde pulstid
bduration =map(gas,0, 255, lagstavarv, hogstavarv); // ställs in högst upp
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 9: //Detta case ger nionde pulstid
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
break;
case 10: // detta case räknar ut tidsdiff per spridare plus systemspänningsdiff
sprtroghetklar = sprtroghet + spridardiff - sprstartkorr; // spridartröghet klart värde räknas ut här
// och ger motorns verkliga fart baserat på dom 11 första tänderna
delvalue = priv + delvalue; // föregående pulstid + föregående deltid läggs ihop
mduration = delvalue/14; // Motorns totala pulstid i mikrosek dividerat med 12 ger motorns duration vid drift
// och räknar ut skillnaden mellan är och börvärde - 1 = error
error = (mduration / bduration)-1;
if (error <=0.) // om error under noll
{
error = 0.; // förblir error 0 för att ej få minusvärden
}
break; // felet i uS mellan är och börvärde för motorns fart
case 11: // Detta case för insprutningsfördröjning i gånger, ställs högst upp
starttandf = mduration /tidigasteinspr; // starttandf, ett flyt-tal = motorns duration/ minsta duration/max RPM. ställs högst upp
if (starttandf >= senasteinspr) // om fördröjning över målvärdet, som vid tex startvarv (ställs in högst upp)
{
starttandf = senasteinspr; // blir det målvärdet ändå
}
break;
case 12: // Detta case ger förtändningen
ondelay = (mduration * starttandf); // tillslagsfördröjning = motorns duration * starttandsfördröjning (decimaltal)
break; // Ondelay uS = mduration uS * starttandf i decimalform
case 13: // Detta case ger motorns karaktärstik på arbetsvarv
if (mduration >=161) // "mellanvarv"
{ // Felkorrigeringsvärde som ger spridaröppningstid i uS
delta = mduration * error * aggrfaktorlag; // aggrfaktor låg avgör hur mycket extra ontid spridarna får vid belastning lägre varv
if (delta >= maxdeltalag * mduration) // om delta är mer än max tillåten delta x mduration
{
delta = maxdeltalag * mduration; // förblir delta max tillåten
}
}
if (mduration <= 160) // "högvarv"
{
delta = mduration * error * aggrfaktorhog; // Felkorrigeringsvärde som ger spridaröppningstid i uS
} // aggrfaktor hög avgör hur mycket extra on tid spridarna får vid belastning högre varv
break;
case 14: // Detta case ger mjukstarten
if (mduration >= 700) // Vid lite över startfart
{
delta = lagmangd * mduration; // blir det mjukstart som justeras via lågmängd högst upp
}
// och absolut längsta insprutningstid
if (delta + ondelay >= totaltid * mduration) // om delta och ondelay i uS blir mer än totaltid
{ // så justeras endast delta ner
delta = (totaltid * mduration)-ondelay;// Absolut max insprutningstid (delta), ställs högst upp
} // denna justering gäller bara på högvarv, hög belastning
break;
case 15: // Detta case är insprutningsfasen "spridar-on-off-mode"
if (ondelay >=10000) // Om ondelay är mer än 10000 uS. ( < 300RPM )
{ // går tiden över från uS till mS.
ondelay = ondelay/1000; // Ondelay uS blir mS.
delta = delta/1000; // Delta uS blir mS.
// avgör om tillräcklig fart är uppnådd för motorstart
if(mduration >= minfart) // motorn måste upp i x fart för att få bränsle, ställs högst upp (minfart i uS)
{
delta = 0; // och delta(insprutningstid)resetas
}
// och startmängden vid motorstart
if ((delta * 4)>= startmangd) // här ställs startmängden in (högst upp)
{
delta = startmangd; // så det blir rätt startmängd/slag (5 = 0,75 tänder = 4,5 vevgrader)
}
delay(ondelay); // Fördröjer starttiden x antal mS beroende på varvtalet (mdurationen)
digitalWrite (sprpins[pekare],HIGH); // Spridarpinne hög,insprutning börjar. sprpins [pekare 8,9,10 eller 11].
digitalWrite(sprControl, HIGH); // Kontrollpinne som går hög vid varje insprutningstillfälle.
delay(delta); // Här läggs insprutningstiden in som sen fördröjer processorn i delta mS
digitalWrite (sprpins[pekare],LOW); // Spridarpinne låg,insprutning avslutad sprpins [pekare 8,9,10 eller 11].
digitalWrite (sprControl, LOW); // Kontrollpinne som går låg efter varje insprutningstillfälle.
} // Detta paket används vid låga farter såsom start/lågvarv < 250 RPM
else // Eller om delay är mindre än 10000 uS. (> 300 RPM)
{
if (delta > 25) // Delta under 25 uS har inget värde
{
delta = delta + sprtroghetklar; // Delta över 25 blir x delta + trögheten i spridaren (ca 250-500 uS)
}
ondelay = ondelay - sprtroghetklar; // tidigarelägger insprutningstart med hänsyn till spridartrögheten
delayMicroseconds(ondelay); // Fördröjer starttiden i ondelay uS beroende på varvtalet (mdurationen)
digitalWrite (sprpins[pekare],HIGH); // Spridarpinne hög,insprutning börjar. sprpins [pekare 11,10,9 eller 8].
digitalWrite(sprControl, HIGH); // Kontrollpinne som går hög vid varje insprutningstillfälle.
delayMicroseconds(delta); // Här läggs insprutningstiden in som sen fördröjer processorn i on spridare delta uS
digitalWrite (sprpins[pekare],LOW); // insprutning avslutad sprpins [pekare 8,9,10 eller 11] går låg.
digitalWrite (sprControl, LOW); // Kontrollpinne som går låg efter varje insprutningstillfälle.
} //Detta paket används vid varv (250 -> RPM = nästan alltid, förutom vid motorstart)
break; //Dessa paket tar 1 till 6 tänder att genomföra beroende på varvtal och belastning
case 16: // är mellan tand 19 och 24
switch (analogval)
{
case 0:
gas = analogRead(A0)>>2; // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
// turbotryck = analogRead(A4);
break;
case 1:
// variabel1 = analogRead(A1)>>5; //(enginetmp) 0 till 512 0,1 Volt/10 grad använder LM-35 tempgivare (skiftad 1 gång)
battVolt = analogRead(A7); // skall vara A7!!
break;
case 2:
gas = analogRead(A0)>>2; // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
//turbotryck = analogRead(A4); // analogingång för turbotryck 0 till 127 (skiftad 3 gånger)ambTemp = analogRead(A3);
break;
case 3:
// variabel2 = analogRead(A2)>>3; // (turboAirTemp) skall vara turboAirTemp,
// atmtryck = analogRead(A6); // analogingång för lufttrycket max 255
break;
case 4:
gas = analogRead(A0)>>2; // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
/// turbotryck = analogRead(A4); // analogingång för turbotryck 0 till 127 (skiftad 3 gånger)
break;
case 5:
// tidigasteinspr = analogRead(A2)>>2; // A7!!
// ambTemp = analogRead(A3);
break;
}
analogval ++; // räkna upp analogval 1 steg
if (analogval > 5) // när analogval har blivit 5 så
{
analogval = 0; // resettas analogval till 0 igen
}
break; // analalogRead tar ca 120 uS att läsa = 1-2 tänder vid fullvarv
}
//______________________________________________________________________________________________________
tand ++ ; // räkna upp ett steg för varje ny puls, kommer via pulseIn()funkt.
priv = puls; // lägger in den förra pulstiden i värdet "priv" (uS)
if (mduration >1800) // när motorn går på allra lägsta varv (start)
{
fasttid = tid1; // används tid1 (4000 uS i grundinställning)
}
if ((mduration > 1200)|| (mduration < 1800))
{
fasttid = tid2;
}
if ((mduration > 500)||(mduration < 1200)) // Om motorn går under 1100 RPM
{
fasttid = tid3; // används tid2 (1200 uS i grundinställning)
}
if (mduration <500) // Om motorn går över 1100 RPM
{
fasttid = tid4; // används tid3 (300 uS i grundinställning)
}
puls = pulseIn(vevpin, LOW, 30000); // Ett färdigt kommando som väntar in nästa puls (tand = case).
// vid stillastående motor blir det en timeout
// efter 0,03 Sek
if (puls > priv + fasttid) // jämför om ny pulstid i uS är större än föregående + fasttid.
{
digitalWrite (pulsutpin, HIGH); // utpin blir hög när pulsluckan återgår till pulser
tand = 0; // resetar 0 till 28 räknaren som bara har hunnit räkna mellan 19 och 27 tänder
pekare ++; // och räknar upp spridarpinpekräknare
if (pekare > 3) // när fjärde pinnen är nådd börjar den om igen
{
pekare = 0; // spridarpinne 1 är igång igen (1 = D11)
} // Denna if-sats är bara sann varje halv-varv vid luckan
}
if (pekare == 0) // om spridarpekaren pekar på 0 (ben D11)
{
spridardiff = sprdiff4; // skall det individuella värdet för spridare 4 hämtas
}
if (pekare == 1) // om spridarpekaren pekar på 1 (ben D10)
{
spridardiff = sprdiff2; // skall det individuella värdet för spridare 2 hämtas
}
if (pekare == 2) // om osv... upp till 3 (fjärde spridaren)
{
spridardiff = sprdiff1; // ben D9
}
if (pekare == 3)
{
spridardiff = sprdiff3; // ben D8
}
if (puls < priv - fasttid) // jämför on ny pulstid är mindre än förgående - fasttid.
{
digitalWrite (pulsutpin, LOW); // utpin blir låg igen nästa uppgång i pulståget.
}
}
// end void loop()
Kod: Markera allt
#include <LiquidCrystal.h> // hjälpprogram för displayen
char x; // x = A eller B som aktiv ECU
int ecuAktiv = 3; // ingång för att känna aktiv ECU.
int inpin = 2; // pulsingång 2 pulser per varv till beräkning av motor/propvarv.
int motorvarvut = 9; // till motorns varvräknare PWM
int propvarvut = 10; // till propellervarvräknare PWM
int gasvalue; // gasvärde från poten 0-1023
int sprSignalin = 8; // ansluts till valfri spridarutgång eller sprcontrol, valfritt
float sprTid; // spridaröppningstid i % (av halvt motorvarv)
float liter; // liter/timma
int rs=4, en=5, d4=6, d5=11, d6=12, d7=13; // till displayanslutningar
LiquidCrystal lcd(rs,en,d4,d5,d6,d7); // till display
long varvtalprop; // propellerns varvtalsvärde i uS
long puls, varvtalmotor; // pulstid och motorvarvtalsvärde i uS
int readECUAvoltage; // innan volt på ECU A 1-1023
int readECUaltvoltage; // innan volt på ECU B 1-1023
int readbattVoltage; // innan volt på nödbatterit 1-1023
int engineTemp; // motortemp 0-130 grader
int turboAirTemp; // laddlufttemp 0-130 grader
int ambientTemp; // omgivningstemp -20 -> 60 grader
int atmTryck; // atmosfärstryck 1030 till 700 mBar
float ECUAvoltage; // ECU A 0,0 till 6,0 volt
float ECUaltvoltage; // ECU B 0,0 till 6,0 volt
int turbotryck;
void setup()
{
pinMode(ecuAktiv, INPUT_PULLUP); // satt aktiv ECU som ingång med pålappmotstånd
pinMode(motorvarvut, OUTPUT); // till motorvarvräknare PWM
pinMode(propvarvut, OUTPUT); // till propvarvräknare PWM
pinMode(sprSignalin, INPUT); // från en valfri spridare eller från sprControll
pinMode(inpin, INPUT); // ingång för att beräkna motor/propvarvtal
lcd.begin(8,2); // startanrop av 4 radig display x 20 tecken
lcd.setCursor(0,0); // börjar första raden längst till vänster
lcd.print("Diesel ECU ver.1.0"); // visar versionsnummer
lcd.setCursor(0,1); // börjar andra raden längst till vänster
lcd.print("Byggd av J Berglund"); // visar byggd av ...
lcd.setCursor(0,2); // börjar tredje raden längst till vänster
lcd.print("Motor VW PD 135 hp"); // visar motortyp & hk
lcd.setCursor(0,3); // börjar fjärde raden längst till vänster
lcd.print("Mjukvara 1.0 rev 0"); // visar mjukvara nummer (motor)
Serial.begin(250000); // startar serial utgång till datorn 250000 Baud
delay(4000); // för att visa displaydata dom första 4 sekunderna vid uppstart
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,2);
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print(" ");
}
void loop() // efter 4 sekunder startar den ändlösa loopen
{
gasvalue = analogRead(A0); // läser av gasreglagevärde 1-1023
turbotryck = analogRead(A4); // läser av turbotrycket 1-1023
atmTryck = analogRead(A6); // läser av atmosfärstrycket 1-1023
readECUAvoltage = analogRead(A7); // läser av ECU A spänning 1-1023
readECUaltvoltage = analogRead(A5); // läser av ECU B batterispänning 1-1023
engineTemp = (5.0* analogRead(A1)*100.)/1024; // LM-35 tempgivare blir motortemp C grader
turboAirTemp = analogRead(A2); // NTC motstånd som mäter laddlufttemp C grader
ambientTemp = analogRead(A3); // läser av omgivnings NTC motståndet 1-1023
gasvalue = map(gasvalue,0,1023,0,100); // gasreglaget blir 0 till 100 % effekt börvärde
turbotryck = map(turbotryck,0,1023,100,3000); // turbotrycket blir 400 till 4000 mBar
atmTryck = map(atmTryck, 0,1023,100, 3000); // atmosfärstrycket blir ocalibrerat mBar.
ECUAvoltage = readECUAvoltage *(8.0/1023.0); // ECU A drivspänning till 10 volt
ECUaltvoltage = readECUaltvoltage *(28.3/1023.); // ECU B batteripänning till 23,5 volt
ambientTemp =map(ambientTemp,0,1023,60,-20); // omgivningstemperatur -20 till 60 G c med en NTC
turboAirTemp = map(turboAirTemp,0,1023,60,-20);
sprTid = pulseIn(sprSignalin, HIGH); // mäter in valfri spridares ontid i uS
sprTid = sprTid/puls*100.; // gör om ontiden från uS till procent
liter = sprTid * varvtalmotor /1500; // visar liter/timma baserat på spridaröppningstid
// och antal öppningar via motorns vartal, /150 skall provas ut...
if (digitalRead(ecuAktiv)== HIGH) // känner av vilken ECU som är aktiv
{
x = 'A'; // om A är hög visas A som aktiv
}
else
{
x = 'B'; // om A är låg visas B som aktiv
}
lcd.setCursor(0,0); // börjar första raden längst till vänster
lcd.print("MOTORVARV "); // skriver "Propeller"
lcd.setCursor(10,0);
lcd.print(" ");
lcd.setCursor(10,0);
lcd.print(varvtalmotor); // skriver av aktuellt motorvarv
lcd.setCursor(14,0); // börjar första raden 15 steg in
lcd.print(" "); // skriver "tomrum"
lcd.print("RPM"); // skriver " RPM"
lcd.setCursor(0,1); // börjar andra raden längst till vänster
lcd.print("EFFEKTSETTING "); // skriver "effektsetting"
lcd.setCursor(14,1);
lcd.print(" ");
lcd.setCursor(14,1);
lcd.print(gasvalue); // läser av aktuellt gasreglage värde i procent
lcd.setCursor(18,1);
lcd.print(" %"); // skriver "%"
lcd.setCursor(0,2); // börjar tredje raden längst till vänster
lcd.print("Motortemp "); // skriver "motortemp"
lcd.print(engineTemp); // läser av aktuell motortemp i C grader
lcd.print(" gr. C."); // skriver " gr. C."
lcd.setCursor(0,3); // börjar fjärde raden längst till vänster
lcd.print("FUELFLOW "); // skriver "fuelflow"
lcd.print(liter); // läser av aktuellt litervärde
lcd.print(" L/h"); // skriver "l/h"
Serial.print("Gasvalue "); // skriver ut div realtidsvärden
Serial.print(gasvalue); // samtliga värden är självförklarande
Serial.print("% "); // via datorns monitor...
Serial.print("Turbovalue ");
Serial.print(turbotryck);
Serial.print(" mBar ");
Serial.print("Turbo Air Temp ");
Serial.print(turboAirTemp);
Serial.println(" Grader C.");
Serial.print("Absoluttryck ");
Serial.print(atmTryck);
Serial.print(" mBAR ");
Serial.print("ECU A ");
Serial.print(ECUAvoltage);
Serial.print(" Volt ");
Serial.print("ECU B ");
Serial.print(ECUaltvoltage);
Serial.println(" Volt");
Serial.print("Engine Temp ");
Serial.print(engineTemp);
Serial.print(" Grader C. ");
Serial.print("Ambient Temp ");
Serial.print(ambientTemp);
Serial.print(" Grader C.");
Serial.print(" ECU ");
Serial.print(x);
Serial.println(" Aktiv");
Serial.print("Motor ");
Serial.print(varvtalmotor);
Serial.print(" RPM");
Serial.print(" Propeller ");
Serial.print(varvtalprop);
Serial.println(" RPM ");
if (varvtalmotor >=3400) // max pulslängd tomgång, >= 3400 mikrosek
{
varvtalmotor = 3400; // om stillastående/startmotorvarv så blir motorvarvet noll till ev varvräknare
}
varvtalmotor = map(varvtalmotor,0,5100,255,0); // 100 till 5100 uS görs om till 0 till 255 (PWM)
analogWrite(motorvarvut,varvtalmotor); // ger ut en pwm signal 0 till 255 beroende på motorns varvtal
analogWrite(propvarvut,varvtalmotor); // ger ut en pwm signal 0 till 255 beroende på propellerns varvtal
Serial.print("Pulswidth "); // fortsättning div realtidsvärden
Serial.print(varvtalmotor);
Serial.print(" spridare ");
Serial.print(sprTid);
Serial.print(" % open ");
Serial.println("*Sent from displaycontrol(botton)*");
delay(100); // fördjöjning för att inte bli översvämmad av data
puls = pulseIn(inpin, LOW); // väntar in nästa puls, Triggar på nersidan
// vid stillastående motor blir det en timeout varje sekund.
varvtalmotor = (1000000/puls)*30.06; // pulsbrädden görs om till RPM motor
varvtalprop = varvtalmotor *0.625; // RPM motor görs om till RPM propeller
}
// end of loop____________________
En liten funktionbeskrivning av ECU:n
0 - 129 RPM under startvarv ställs in med "minfart" vid vilken duration som insprutningen skall börja 3800 är ca 130 RPM
130 - 230 RPM "startmangd" reglerar här 12 ( x 1,2 ) ger ca 14 grader ontid, 20 ger ca 26 grader ontid.
230 - 480 RPM " lågmangd" reglerar här 2 (x3) ger ca 6 grader ontid, 3 ger c 9 grader ontid.
480 - 2800 RPM "aggrfaktorlag" reglerar här hur fort den skall reglera upp vid underfart och
"maxdeltalag" sätter maxgränsen 3.0 (x3) blir 9 grader ontid och 5.0 blir 15 grader ontid
2800 - maxvarv "aggrfaktorhog" reglerar här hur fort den skall reglera upp vid underfart och
"totaltid" sätter maxgränsen 10 (* motorns duration) på hur länge en insprutning överhuvudtaget får vara.
"senasteinspr" 6.0 (x3) fördröjer här insprutningens början 18 grader från det att den är i case 15
Högre tal ger senare tändning...
"senareinsprdrift" 8.0 (x3) ger en annan förtändning när motorn väl statat och kommit upp till brytvarvat "omslagstartdrift" när det nya värdet gäller växlar den inte tillbaka till det gamla mer än vid en ECU-reset.
Så alltså, möjlighet till två separata tändkurvor.
"tidigasteinsprutning" 110 högre tal ger tidigare tändning (max 255) (Detta värde är inte linjärt utan det händer mycket i början och mindre på slutet) Denna justering gäller från tomgångsvarv upp till maxvarv och är linjärt med varvtalsökningen.
"lagstavarv" är lägsta tomgångsvarv 580 är börvärde uS vilket motsvarar ca 600 RPM högre värde ger lägre varv.
"hogstavarv" är högsta varvtal 90 är börvärde uS vilket motsvarar ca 3800 RPM högre värde ger lägre varv.
Själva varvtalsregleringen arbetar enligt undervarvsprincipen, den kan aldrig nå målvärdet då insprutningen uteblir utan den måste ligga lite under och balansera. Trotts detta så följer regleringen slaviskt, motorn kommer aldrig i självsvängning, ökar direkt effekten vid allra minsta undervarv utan att skjuta över.
"omslagmillimicro" 13000 bestämmer när case 15 ändrar från millisekunder i uträkning spridare på tider till mikrosekunder för samma uträkningar. Mikrosekunder ger 1000 gånger bättre precision och körs vid varvtal över 230 RPM, dvs nästan alltid. (Pga. för stora tal så klarar inte Arduinon av mikrosekunder under ca 200 Rpm så därför måste millisekunder användas istället då)
"omslagmellanhogvarv" 160 uS duration bestämmer när aggretionsfaktorn låg/hög växlas.
Durationen är tiden mellan två tänder/2 då pulseIn() bara räknar halva tiden. Så 400 uS pulstid blir 200 uS i ECU-programmet. Dessa durationsvärden ingår i många uträkningar.
Här är koden för realtidsklocka och SD-korts sparning med monitorfunktion via USB&dator
Kod: Markera allt
#include <SD.h> // SD bibliotek, hjälpprogram för sd-kortet
#include <DS3234.h> // DS3234 bibliotek, hjälpprogram för klockmodulen
char x; // x = A eller B som aktiv ECU
int ecuAktiv = 3; // ingång för att avgöra aktiv ECU.
int inpin = 2; // pulsingång 2 pulser per varv till beräkning av motor/propvarv.
int gasvalue; // gasvärde från poten 0-1023
int sprSignalin = 8; // ansluts till valfri spridarutgång eller sprcontrol, valfritt
float sprTid; // spridaröppningstid i % (av halvt motorvarv)
float liter; // liter/timma
int chipSelect = 6; // chip select pin for the MicroSD Card Adapter
long varvtalprop; // propellerns varvtalsvärde i uS
long puls, varvtalmotor; // pulstid och motorvarvtalsvärde i uS
int readECUAvoltage; // innan volt på ECU A 1-1023
int readECUaltvoltage; // innan volt på ECU B 1-1023
int engineTemp; // motortemp 0-130 grader
int turboAirTemp; // laddlufttemp 0-130 grader
int ambientTemp; // omgivningstemp -20 -> 60 grader
int atmTryck; // atmosfärstryck 1030 till 700 mBar
float ECUAvoltage; // ECU A 0,0 till 6,0 volt
float ECUaltvoltage; // ECU B 0,0 till 6,0 volt
int turbotryck; // turbotryck
String tid; // en string där tiden sparas
String datum; // en string där datum sparas
int temp; // en int där temp från RTC sparas
byte antalLoop = 0; // antal loop hur många varv loopen skall gå mellan skrivningarna
byte loopvarde;
DS3234 rtc(10); // RTC:ns CS anslutning (SS)
File motor; // filnamn "motor" är vald
void setup()
{
pinMode(ecuAktiv, INPUT_PULLUP); // satt aktiv ECU som ingång med pålappmotstånd
pinMode(sprSignalin, INPUT); // från en valfri spridare eller från sprControll
pinMode(inpin, INPUT); // ingång för att beräkna motor/propvarvtal
Serial.begin(250000); // startar seriell data
pinMode(chipSelect, OUTPUT); // chip select pin satt som utgång
if (!SD.begin(chipSelect)) // väljer in sd-kortet
{
Serial.println("Could not initialize SD card."); // Hjälptext om kort/fil saknas
}
if (SD.exists("motor.txt")) // Om kort och fil finns
{
Serial.println("File exists."); // hjälptext om att filen finns
} // När "file exists" visas då sparas datan på kortet.
/*rtc.begin(); // Här ställer man in klockan en gång
rtc.setTime(19, 24, 0); // Ställ tiden till 12:00:00 (24tim visning)
rtc.setDate(10, 2, 2018); // Ställ datum till February den 2:a, 2018
*/ // detta används bara för att ställa RTC modulen en gång vid batteribyte
}
void loop()
{
rtc.begin(); // startar klockvisning
datum = rtc.getDateStr(); // lägger in aktuellt datum i String datum
tid = rtc.getTimeStr(); // lägger in aktuell tid i String tid
temp = rtc.getTemp(); // lägger in aktuell chiptemp (C) i int temp
if((varvtalmotor <=1500)&&(varvtalmotor >=3600))
{
loopvarde = 3;
}
else
{
loopvarde = 10;
}
antalLoop ++; // räknar upp loopen ett steg varje varv
if(antalLoop >=loopvarde) // när loppvärdet, antal loopvarv är räknade.
{
antalLoop = 0; // då resetas loopräknaren till 0 igen
}
switch (antalLoop) // antal Loop blir switchfunktion
{
case 0: // case 0 är första case vilket betyder: "skriv till SD-kortet"
// case 1-10 betyder: hoppa över "skriv till SD-kortet"
motor = SD.open("motor.txt", FILE_WRITE); // öppnar "motor.txt" för att skriva in data
if (motor) // om filen "motor" finns
{
motor.print(datum); // skiver in datum från String datum
motor.print(" ");
motor.print(tid); // skriver in tid från String tid
motor.print("--");
motor.print(temp); // skriver in ECU temp från int temp
motor.print(", PS "); // PS = Power Setting
motor.print(gasvalue); // gasvärde i %
motor.print(", RPM "); // skriver RPM
motor.print(varvtalmotor); // motorns varvtal per minut
motor.print(", TP "); // TP = Turbo Pressure i mBar
motor.print(turbotryck); // turbotrycksvärdet i mBar
motor.print(", ECU V "); // ECU V = ECU:ns batterispänning
motor.print(ECUaltvoltage); // skriver i volt med två decimaler
motor.print(", TOT "); // TOT = Turbons Out Temp
motor.print(turboAirTemp); // skriver temperaturen i celsius
motor.print(", CT "); // CT = Cooling Temp
motor.print(engineTemp); // skriver temperaturen i celsius
motor.print(", AP "); // AP = Ambient Pressure
motor.print(atmTryck); // skriver trycket i mBar
motor.print(", AT "); // AT = Ambient Temp
motor.print(ambientTemp); // skriver temperaturen i celsius
motor.print(", IT "); // IT = Injector onTime
motor.print(sprTid); // skriver ut i %
motor.println("%"); // % tecken
motor.close(); // efter skrivning så stängs filen
}
else
{
Serial.println("Could not open file (writing)."); // om kort saknas/trasigt skrivs detta istället.
}
break; // händelsedata skrivs bara in till SD-kortet var tionde gång
}
delay(1000); // Ger ett nytt värde ca var annan sekund (1000 milli + pulseIn x 2 á max 100 milli)
gasvalue = analogRead(A0); // läser av gasreglagevärde 1-1023
turbotryck = analogRead(A4); // läser av turbotrycket 1-1023
atmTryck = analogRead(A6); // läser av atmosfärstrycket 1-1023
readECUAvoltage = analogRead(A7); // läser av ECU A spänning 1-1023
readECUaltvoltage = analogRead(A5); // läser av ECU B batterispänning 1-1023
engineTemp = (5.0* analogRead(A1)*100.)/1024; // LM-35 tempgivare blir motortemp C grader
turboAirTemp = analogRead(A2); // NTC motstånd som mäter laddlufttemp C grader
ambientTemp = analogRead(A3); // läser av omgivnings NTC motståndet 1-1023
gasvalue = map(gasvalue,0,1023,0,100); // gasreglaget blir 0 till 100 % effekt börvärde
turbotryck = map(turbotryck,0,1023,100,3000); // turbotrycket blir 400 till 4000 mBar
atmTryck = map(atmTryck, 0,1023,100, 3000); // atmosfärstrycket blir ocalibrerat mBar.
ECUAvoltage = readECUAvoltage *(8.0/1023.0); // ECU A drivspänning till 10 volt
ECUaltvoltage = readECUaltvoltage *(28.3/1023.); // ECU B batteripänning till 23,5 volt
ambientTemp =map(ambientTemp,0,1023,60,-20); // omgivningstemperatur -20 till 60 G c med en NTC
turboAirTemp = map(turboAirTemp,0,1023,60,-20);
sprTid = pulseIn(sprSignalin, HIGH); // mäter in valfri spridares ontid i uS
sprTid = sprTid/puls*100.; // gör om ontiden från uS till procent
liter = sprTid * varvtalmotor /1500; // visar liter/timma baserat på spridaröppningstid
// 1500 är godtyckligt som verkar att stämma inom 25 %
// och antal öppningar via motorns vartal, /1500 skall provas ut...
if (digitalRead(ecuAktiv)== HIGH) // känner av vilken ECU som är aktiv
{
x = 'A'; // om A är hög visas A som aktiv
}
else
{
x = 'B'; // om A är låg visas B som aktiv
}
Serial.print(datum); // hämtar datum från String datum
Serial.print(" ");
Serial.print(tid); // hämtar tid från String tid
Serial.print(" -- ");
Serial.print("Internal ECU temp: ");
Serial.print(temp); // hämtar intern ECU (klock) temp från int temp
Serial.println("C");
Serial.print("Gasvalue "); // skriver ut div realtidsvärden
Serial.print(gasvalue); // via serial.print (250000)
Serial.print("% "); // samtliga värden är självförklarande...
Serial.print("Turbovalue ");
Serial.print(turbotryck);
Serial.print(" mBar ");
Serial.print("Turbo Air Temp ");
Serial.print(turboAirTemp);
Serial.println(" Grader C.");
Serial.print("Absoluttryck ");
Serial.print(atmTryck);
Serial.print(" mBAR ");
Serial.print("ECU A ");
Serial.print(ECUAvoltage);
Serial.print(" Volt ");
Serial.print("ECU B ");
Serial.print(ECUaltvoltage);
Serial.println(" Volt");
Serial.print("Engine Temp ");
Serial.print(engineTemp);
Serial.print(" Grader C. ");
Serial.print("Ambient Temp ");
Serial.print(ambientTemp);
Serial.print(" Grader C.");
Serial.print(" ECU ");
Serial.print(x);
Serial.println(" Aktiv");
Serial.print("Motor ");
Serial.print(varvtalmotor);
Serial.print(" RPM");
Serial.print(" Propeller ");
Serial.print(varvtalprop);
Serial.println(" RPM ");
if (varvtalmotor >=3400) // max pulslängd tomgång, >= 3400 mikrosek
{
varvtalmotor = 3400; // om stillastående/startmotorvarv så blir motorvarvet noll till ev varvräknare
}
varvtalmotor = map(varvtalmotor,0,5100,0,255); // 100 till 5100 uS görs om till 0 till 255 (PWM)
Serial.print("Pulswidth "); // fortsättning div realtidsvärden
Serial.print(varvtalmotor);
Serial.print(" spridare ");
Serial.print(sprTid);
Serial.print(" % open ");
Serial.println("*Sent from SD-card Control (top)*");
Serial.println(" "); // slut på utskrift
delay(1000);
puls = pulseIn(inpin, LOW); // väntar in nästa puls, Triggar på nersidan
// vid stillastående motor blir det en timeout varje sekund.
varvtalmotor = (1000000/puls)*30.06; // pulsbrädden görs om till RPM motor
varvtalprop = varvtalmotor *0.625; // RPM motor görs om till RPM propeller
}
// end of loop____________________