Re: ECU- styrning till en VW pumpdysediesel.
Postat: 3 januari 2019, 21:34:24
Kul med framsteg!
Svenskt forum för elektroniksnack.
https://elektronikforumet.com/forum/
Kod: Markera allt
// Förändrad 2019-01-04 och inlagd 2019-01-04 förtändningen går åt fel håll på höga varv...
// 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 i gasen så analogvärde 20 är tomgång och analogvärde 210 är fullfart Fungerar
// ändrad till att starta insprutningsmodulen på tand 15 fungerar
// mjukstarten är förbättrad och går in vid ca 200 RPM och varar till ca 450 RPM fungerar
// några fler constanter har kommit till bla. gaspotmin, gaspotmax, utanvärde, fungerar
// En dubbel förtändning har kommit till, en för start och en för drift.
// här är olika justerbara parametrar som påverkar enligt följande:
const byte totaltid =13; // totaltid för case 15: x * motorns duration (10)
const int lagstavarv = 480; // tomgångsvarvet 500 uS motsvarar ca 800 Rpm (530)
byte hogstavarv = 110; // fullgasvarvet 100 uS motsvarar ca 4200 RPM (90)
const byte aggrfaktorlag = 3; // hur mycket spridar PWM skall öka vid belastning mellanvarv (3)
const byte aggrfaktorhog = 10; // hur mycket spridar PWM skall öka vid belastning högvarv (7)
const int minfart = 3800; // lägsta startvarv för spridarfunktion (3800 = 131 RPM)
const byte startmangd = 20; // avgör max startmängd 16 ca 19 grader ontid (16) mellan 131 till 200 RPM (absolut första början)
const float maxdeltalag = 3.0; // max insprutningstid mellanvarv mdutation * 3.0 ger 1,5 vevaxelpulser = 9 gr ontid (3.0) max ontid vid 450 till 2000 RPM
const byte lagmangd = 5; // max lågvarvsmängd 2 = 1 vevaxelpuls = 6 grader ontid (under tomgångsvarv)(2) 200 till 450 RPM (mjukstartsmängd)
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 = 800; // tid 3 är för att hitta pulsluckan i alla andra förekommande varv 1100--> (1000)
const int tid4 = 90; // tid 4 är för att hitta pulsluckan på högsta varvtal (100)
float senasteinspr = 9.0; // senaste insprutningstid (vid start upp till tomgång)(6.0 = 3 vevaxelpulser = 18 grader delaytid(6.0) Tomgångsförtändning (högre tal ger senare tändning)
const float senasteinsprdrift =10.5;// Vid tomgång/drift ges en ny "senasteinsprutningstid" som behålls sedan.
const byte tidigasteinspr =180; // kortaste insprutningsfördröjning vid maxvarv, högre tal ger tidigare tändning(110)(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; // 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)
const int omslagstartdrift = 900; // Bestämmer när mjukstarten går ur (omslagspunkt) (900 = brytvarv 450 RPM)
const int omslagmellanhogvarv = 160;// bestämmer omslaget när aggresionsfaktor mellan/hög växlar (ca 2000 RPM)
const int omslagmillimicro= 13000; // omslag från milli till micro i case 15 (vid startvarv ca 200 RPM, baseras på ondelay i us)
const byte utanvarde = 25; // om delta under vist värde utanvärde, nollas
const byte gaspotmin = 20; // gaspotens minsta tillåtna värde
const byte gaspotmax = 210; // gaspotens största tillåtna värde
int vevpin = 2; // pulsingång vevaxelgivare.
int kampin = 3; // kamaxelgivarens ingång.
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 (mS inne i case 15)
long puls, priv, delta; // senaste, föregående och delta (totalöppningstid) i uS(mS)
float error; // error = varvtalsfelet 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 x tänder (max 255), startar på 0
int fasttid = 300; // Fasttid = börjar alltid på 300 för att sedan ställa in mer rätt (tid1 till tid4)
byte analogval; // En switch/case till analogread
int battVolt = 400; // mäter systemspänning till spridare grundsatt till 400 för att snabba på start
int sprstartkorr = 400; // spridarstartkorregering i uS, spänningsberoende grundsatt till 400 för att snabba på start
int sprtroghetklar; // korrektion för den inbyggda påslagströgheten i spridarna
int spridardiff; // en ev. individuell spridartid korrigering (uS)
int variabel1;
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 16!
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 enligt tidigare
}
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 + batterispänningskontroll
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);// för att hålla färdigvärdet inom 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
gas = constrain(gas,gaspotmin, gaspotmax); // först skall invärdet vara mellan min och max oavsett gaspotens verkliga värde (om utanför)
bduration =map (gas,gaspotmin, gaspotmax, lagstavarv, hogstavarv); // gör om gas analogvärde till lägsta/högsta uS värde
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
// 400 + 20/0/0/20 - (200-400)
// 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 14 ger motorns duration vid drift
// Serial.println(mduration);
// 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.
if (starttandf >= senasteinspr) // om fördröjning över målvärdet, som vid tex startvarv
{
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 Mellan 160 uS och 900 uS
if ((mduration >=omslagmellanhogvarv)||(mduration <=omslagstartdrift)) // från ca 450 RPM och upp till ca 2000 RPM (mer än 160 men mindre än 900
{ // 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 < omslagmellanhogvarv) // "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 >= omslagstartdrift) // Vid lite över startfart mellan 200 RPM till ca 450 RPM
{
delta = lagmangd * mduration; // blir det mjukstart som justeras via lågmängd
}
// 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),
} // denna justering gäller bara på högvarv, hög belastning
break;
case 16: // Detta case är insprutningsfasen "spridar-on-off-mode"
if (ondelay >=omslagmillimicro) // Om ondelay är mer än 13000 uS. (från 131 till 203 RPM räknas alla spridarvärden i mS)13000 = 203 RPM
{ // 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, (minfart i uS)
{
delta = 0; // vid underfart, delta(insprutningstid)nollas
}
// och startmängden vid motorstart
if ((delta * 4)>= startmangd) // här ställs startmängden in
{
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. spridare x strömsätts [pekare 8,9,10 eller 11].
digitalWrite(sprControl, HIGH); // Kontrollpinne som blir 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 spridare x stängs av [pekare 8,9,10 eller 11].
digitalWrite (sprControl, LOW); // Kontrollpinne som går tillbaka till låg efter varje insprutningstillfälle.
} // Detta paket används vid låga farter såsom start/lågvarv < 203 RPM
else // Eller om delay är mindre än 13000 uS. (> 203 RPM)
{
if (delta > utanvarde) // Delta under utanvärde uS har inget värde
{
delta = delta + sprtroghetklar; // Delta blir delta + trögheten i spridaren (ca 200-500 uS)som tröghetskompensation
}
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); // Insprutning börjar. spridare x strömsätts [pekare 11,10,9 eller 8].
digitalWrite(sprControl, HIGH); // Kontrollpinne som blir hög vid varje insprutningstillfälle.
delayMicroseconds(delta); // Här läggs insprutningstiden in som sen fördröjer processorn i delta uS
digitalWrite (sprpins[pekare],LOW); // Spridarpinne låg,insprutning avslutad spridare x stängs av [pekare 8,9,10 eller 11]
digitalWrite (sprControl, LOW); // Kontrollpinne som går tillbaka till låg efter varje insprutningstillfälle.
} //Detta paket används vid varv (203 -> 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 17:
if (mduration < omslagstartdrift)
{
senasteinspr = senasteinsprdrift;
}
else
{
}
break;
case 18: // är mellan tand 17 och 23
switch (analogval)
{
case 0:
gas = analogRead(A0)>>2; // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
break;
case 1:
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)
break;
case 3:
//variabel1 = analogRead(A1)>>2;
break;
case 4:
gas = analogRead(A0)>>2; // analogingång för gasreglage 0 till 255( skiftad 2 gånger)
break;
case 5:
// tom
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
}
if ((mduration > 1200)|| (mduration < 1800)) // om motorn går lite mer än startvarv
{
fasttid = tid2; // används tid2
}
if ((mduration > 500)||(mduration < 1200)) // Om motorn går under 1100 RPM
{
fasttid = tid3; // används tid3
}
if (mduration <500) // Om motorn går över 1100 RPM
{
fasttid = tid4; // används tid4 (dom flesta driftvarv)
}
puls = pulseIn(vevpin, LOW, 30000); // Detta kommando 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 har hunnit räkna mellan 16 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()