Arduino UNO ECU

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Stenhammar
Inlägg: 21
Blev medlem: 9 april 2015, 20:18:25

Arduino UNO ECU

Inlägg av Stenhammar »

Hej alla motorintresserade programmerare! Jag håller på med ett mycket förenklat Arduino elektroniskt tändssystem som avser ersätta brytarsystem på förgasarmotorer (veteranbilar och flygplan). Jag har utgått från en VW typ 1 motor som även används på flygplan (jag är flygtekniker). Detta projektet blev ett sätt för mig att fördjupa mig lite inom programmering eftersom jag läser till automationsingenjör nu (examen juni 2016).

Finns det någon där ute som kan hjälpa mig med mitt program och se om det går att göra ännu mer tillförlitligt och driftsäkert? Jag behöver även hjälp med hur jag ska testa systemet/programmet för att se att tändkurvan stämmer i verkligheten. Jag kan ju så klart testa på en motor direkt, men det tar lite tid. Jag funderar på att testa på gräsklipparen innan jag kör på en bilmotor.
Koden klistrar jag in här.
Här är en video på min labbplatta med vevaxelsimulator (propellern) och två dioder som visar signalerna till tändboxen.
Det är anpassat för "smarta" wasted spark tändboxar (2 tändstift per spole) med inbyggd logik.

Jag bifogar ett utkast på en systembeskrivning och kod.

Koden är även här:

Kod: Markera allt

/****Simple Electronic Ignition System. By Anders Stenhammar. 2016**********/

// To be able to manipulate the AVR processor timers:
#include <Avr/interrupt.h>
#include <Avr/io.h>

//Pin definitions:
const byte HallPin1 = 2; // Pin nr 2  to Hall sensor
const byte HallPin2 = 3; // Pin nr 3 is also to Hall sensor
const int Ign1Pin = 8;  // (PORTB,0)
const int Ign2Pin = 11; // (PORTB,3)

volatile long int microseconds;              // The microsecondcounter value.
volatile unsigned int cranktime;         // Time from 3 degrees to where the coil should start to load.
volatile byte IgnSystem;                 // Statusword for active ign system.
volatile byte dwellTime;                 // The time the coil should charge (default is 0,004 seconds.

// RPM variables:
volatile byte half_revolutions;
volatile unsigned int rpm;
volatile unsigned int timeold;

/***********************************************************************/
void setup() {
  
  dwellTime = 3000;               // Runningdwell: 3000uS. (Crankingdwell: 4000uS.)
  half_revolutions = 0;        
  rpm = 0;                     
  timeold = 0;                
  IgnSystem = 0;               // No ignition system is active.

  pinMode(Ign1Pin, OUTPUT);    // Initialize the Ignition 1 pin as an output.
  pinMode(Ign2Pin, OUTPUT);    // -"-
  bitClear(PORTB, 3);          // (digitalWrite(Ign2Pin, LOW);)  Turn the ignition off in case it's on
  bitClear(PORTB, 0);          //  -"-

  attachInterrupt(digitalPinToInterrupt(HallPin1), SensorOn, RISING);   //Hall sensor DI for Ignition 1
  attachInterrupt(digitalPinToInterrupt(HallPin2), SensorOff, FALLING); //-"- 2

  /********** Setup timer2*************/
  noInterrupts();
  TCCR2A = 0;               // Turn off Control register for waveform generation
  TCCR2B = 0;               // Turn off noise cancelling, turn off edge select, waveform gen mode 0, no clock source
  TCCR2A |= (1 << WGM21);   // Turn on CTC mode (so it will start again) automatically
  TIMSK2 |= (1 << OCIE2A);  // Set interrupt on compare match.
  OCR2A = 8;                // Prescaler of 64 gives 4uS per tick, 4uS * 8 = 32uS (32uS = 1 degree at ~5100rpm).
  TCNT2  = 0;               // Reset timer counter to 0
  microseconds = 0;         // Reset the ms counter variable.
  interrupts();
}
//========================================================================
/* The interrupt action for magnet 1: The Timer starts to count up 32 uS at a time.
**********************/
void SensorOn () {

  if ((rpm < 300) & (IgnSystem == 0)) {   // When cranking (starting), the coil nr 2 will charge at once.
    bitSet(PORTB, 3); //Turn on coil 1 charging immediately, Cranking dwell will then be 1ms longer than normal.
    IgnSystem = 2;    // Statusword to know witch system is to be hot.
  }
  if ((rpm >= 300) & (IgnSystem == 2) ) {  // When running (not starting), the coil nr 1 will charge after cranktime in the ISR below.
    IgnSystem = 1;             //Statusword to know witch system is to be hot.
  }

  TCCR2B |= (1 << CS22);     // Load 64 prescaler / And this starts the timer2!

  /********* RPM calculations: **********/
  half_revolutions++;        //For the RPM calculations
  if (half_revolutions >= 2) {
    rpm = 60 * 1000000 / (micros() - timeold) * half_revolutions;
    timeold = micros();
    half_revolutions = 0;
  }
}
/*========================================================================
 The interrupt action for magnet 2: The Timer starts to count up 32uS at a time.
********************************/
void SensorOff () {

  if ((rpm < 300) & (IgnSystem == 0))  {    // When cranking (starting), the coil nr 1 will charge at once.
    bitSet(PORTB, 0);  //Turn on coil 2 charging immediately,  Cranking dwell will then be 1ms longer than normal.
    IgnSystem = 1;     //Statusword to know witch system is to be hot.
  }
  if ((rpm >= 300) & (IgnSystem == 1) ) {   // When running (not starting), the coil nr 2 will charge after cranktime in the ISR below.
    IgnSystem = 2;             //Statusword to know witch system is to be hot.
  }
  TCCR2B |= (1 << CS22);     // Load 64 prescaler / And this starts the timer2!
  
/********* RPM calculations: **********/
  half_revolutions++;        //For the RPM calculations
  if (half_revolutions >= 2) {
    rpm = 60 * 1000000 / (micros() - timeold) * half_revolutions;
    timeold = micros();
    half_revolutions = 0;
  }
}
/*=============================================================================
 The Interrupt Service Routine for Timer2 that will be executed each time the timer reach the compare match register (1ms).
*****************Milliseconds****************/

ISR(TIMER2_COMPA_vect) {

  /*********Counting microseconds*****************/
  microseconds = microseconds + 32;  // Increases the variable "microseconds" by 32 every time the ISR is executed).

  /************ coil charging*****************************/
  if (microseconds >= cranktime) {  //When the timer reaches the cranktime, then do this:

    if (IgnSystem == 1) {   //If ignitionsystem 1 is selected and not on, then:
      bitSet(PORTB, 0);     //Turn on coil 1 charging.
    } if (IgnSystem == 2) { // -"-
      bitSet(PORTB, 3);     // -"- coil 2 charging.
    }
  }
  /***********Discharge coilspark*******************************************/
  //If the microseconds has reached the cranktime and dwelltime, then:
  if (microseconds >= (cranktime + dwellTime)) {
    microseconds = 0;           // reset the ms counter variable
    //Turn off timer.
    TCCR2B  &= ~ (1 << CS22);   //clear the prescaler .
    TCNT2 = 0;                  // Reset the timer count to 0

    bitClear(PORTB, 0); // Stop charging coil 1. (Gives spark)
    bitClear(PORTB, 3); // -"- 2.
    }
    
    // If the engine has stopped or are still cranking, the IgnSystem is set to starting advance degrees.
    if (rpm < 300) {
      IgnSystem = 0;
    }
  }

/***********************************************************/
void loop() {

  //Calculate the cranktime dependent on the rpm. (cranktime= advance time - dwellTime)
  /********************Cranktime calculations ************
       RPM  Advance        Degrees             Cranktime     Time change
            -degrees BTDC  from Sensor           (uS)        for each RPM (uS)
       300    -3            180                100000           -100000
       400     9            171                71250            -288
       600     8            172                47778            -117
       1000    7            173                28833            -47
       1700    17           163                15980            -18
       2800    26           154                9167             -6
       3100    28           152                8172             -3
       4000    29           151                6292             -2
       
  */
  if (rpm <= 300) {
    cranktime = 0;
  } if ((rpm > 300) && (rpm <= 400)) {
    cranktime = (186400 - (rpm * 288)) - dwellTime;  // = (cranktime - (rpm - 300) * Time change for each RPM) - dwellTime;
  } if ((rpm > 400) && (rpm <= 600)) {
     cranktime = (118050 - (rpm * 117)) - dwellTime; // = (71250 - (rpm - 400) * 117) - dwellTime;
  } if ((rpm > 600) && (rpm <= 1000)) {
    cranktime = (75978 - (rpm * 47)) - dwellTime;  
  } if ((rpm > 1000) && (rpm <= 1700)) {
    cranktime = (46833 - (rpm * 18)) - dwellTime;
  } if ((rpm > 1700) && (rpm <= 2800)) {
    cranktime = (26180 - (rpm * 6)) - dwellTime;
  } if ((rpm > 2800) && (rpm <= 3100)) {
    cranktime = (10007 - (rpm * 3)) - dwellTime;
  } if ((rpm > 3100) && (rpm <= 4000)) {
    cranktime = (8732 - (rpm * 2)) - dwellTime;
  }
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.