Arduino ECU med övervakning och loggningsfunktion

Janson1
Inlägg: 1338
Blev medlem: 1 december 2016, 09:06:02
Ort: Marks Kommun

Arduino ECU med övervakning och loggningsfunktion

Inlägg av Janson1 »

Jag har byggt mitt alster på Arduinokod i Aruinos utvecklingsmiljö. Jag har 4 st Arduino NANO som agerar ECU A, B, nutidsövervakning via LCD 4x20 tecken och sparningsArduino som sparar på SD-kort var tredje till var tionde sekund beroende på effektsettingen/motorvarv. Man kan koppla in datorn via monitorn och se nutidsdata på både nutidsövervakningsArduinon och sparningsArduinon. Det som hela Arduinosystemet skall driva är en dieselmotor med enhetsinjektorer (den går inte en meter utan tidskritisk elektronik) från VW. För själva utprovningen av motorn så sitter den i en Grålle traktor just nu. Senare är den tänkt att användas i ett flygplan...
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()
 
Den ena övervakningskoden för display:

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____________________

Här är en bild under "utvecklingen". En annan Arduino får agera dieselmotor från startvarv till fullvarv.
0.jpg
En bild på själva mönsterkortet till ECU:n som nu sitter i traktorn
1.jpg
Kretsschemat för dito
2.jpg
Här syns den lilla lådan där ECU:na och dess övervakning bor.
3.jpg
Här själva displayen, el på men ej startad motor.
4.jpg
Och här är traktorn som får agera provbänk...
5.jpg
Här ett par klipp:

Du har inte behörighet att öppna de filer som bifogats till detta inlägg.