From a16916fa7497527de6a7dddf9d175ef95738786b Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Sat, 16 May 2015 21:06:54 +1000 Subject: [PATCH] Initial work on modular decoders --- decoders.h | 14 ++++++++++++ decoders.ino | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ speeduino.ino | 61 ++++++--------------------------------------------- 3 files changed, 81 insertions(+), 54 deletions(-) create mode 100644 decoders.h create mode 100644 decoders.ino diff --git a/decoders.h b/decoders.h new file mode 100644 index 00000000..318faf95 --- /dev/null +++ b/decoders.h @@ -0,0 +1,14 @@ +volatile unsigned long curTime; +volatile unsigned int curGap; +volatile unsigned int targetGap; + +volatile int toothCurrentCount = 0; //The current number of teeth (Onec sync has been achieved, this can never actually be 0 +volatile unsigned long toothLastToothTime = 0; //The time (micros()) that the last tooth was registered +volatile unsigned long toothLastMinusOneToothTime = 0; //The time (micros()) that the tooth before the last tooth was registered +volatile unsigned long toothOneTime = 0; //The time (micros()) that tooth 1 last triggered +volatile unsigned long toothOneMinusOneTime = 0; //The 2nd to last time (micros()) that tooth 1 last triggered +volatile int toothHistory[512]; +volatile int toothHistoryIndex = 0; + +volatile int triggerActualTeeth; +unsigned int triggerFilterTime, triggerToothAngle; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) diff --git a/decoders.ino b/decoders.ino new file mode 100644 index 00000000..c0430985 --- /dev/null +++ b/decoders.ino @@ -0,0 +1,60 @@ +/* +This file contains the various crank and cam wheel decoder functions. + +Each decoder must have the following 4 functions (Where xxxx is the decoder name): + +* triggerPri_xxxx - Called each time the primary (No. 1) crank/cam signal is triggered (Called as an interrupt, so variables must be declared volatile) +* triggerSec_xxxx - Called each time the secondary (No. 2) crank/cam signal is triggered (Called as an interrupt, so variables must be declared volatile) +* getRPM_xxxx - Returns the current RPM, as calculated by the decoder +* getCrankAngle_xxxx - Returns the current crank angle, as calculated b the decoder + +And each decoder must utlise at least the following variables: +* + +*/ + +/* +Name: Missing tooth wheel +Desc: A multi-tooth wheel with one of more 'missing' teeth. The first tooth after the missing one is considered number 1 and isthe basis for the trigger angle +Note: This does not currently support dual wheel (ie missing tooth + single tooth on cam) +*/ +void triggerPri_missingTooth() +{ + // http://www.msextra.com/forums/viewtopic.php?f=94&t=22976 + // http://www.megamanual.com/ms2/wheel.htm + noInterrupts(); //Turn off interrupts whilst in this routine + + curTime = micros(); + curGap = curTime - toothLastToothTime; + if ( curGap < triggerFilterTime ) { interrupts(); return; } //Debounce check. Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS) + toothCurrentCount++; //Increment the tooth counter + + //High speed tooth logging history + toothHistory[toothHistoryIndex] = curGap; + if(toothHistoryIndex == 511) + { toothHistoryIndex = 0; } + else + { toothHistoryIndex++; } + + //Begin the missing tooth detection + //If the time between the current tooth and the last is greater than 1.5x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after the gap + //if ( (curTime - toothLastToothTime) > (1.5 * (toothLastToothTime - toothLastMinusOneToothTime))) { toothCurrentCount = 1; } + if(configPage2.triggerMissingTeeth == 1) { targetGap = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 1; } //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to multiply by 3 then divide by 2. Much faster than multiplying by 1.5) + //else { targetGap = (10 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 2; } //Multiply by 2.5 (Checks for a gap 2.5x greater than the last one) + else { targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; } //Multiply by 2 (Checks for a gap 2x greater than the last one) + if ( curGap > targetGap ) + { + toothCurrentCount = 1; + toothOneMinusOneTime = toothOneTime; + toothOneTime = curTime; + currentStatus.hasSync = true; + startRevolutions++; //Counter + } + + toothLastMinusOneToothTime = toothLastToothTime; + toothLastToothTime = curTime; + + interrupts(); //Turn interrupts back on +} + +void triggerSec_missingTooth(){ return; } //This function currently is not used diff --git a/speeduino.ino b/speeduino.ino index 3384b4c3..dc8bef44 100644 --- a/speeduino.ino +++ b/speeduino.ino @@ -17,6 +17,7 @@ #include "corrections.h" #include "timers.h" #include "display.h" +#include "decoders.h" #ifdef __SAM3X8E__ //Do stuff for ARM based CPUs @@ -33,21 +34,14 @@ struct config1 configPage1; struct config2 configPage2; struct config3 configPage3; -int req_fuel_uS, triggerToothAngle, inj_opentime_uS; -volatile int triggerActualTeeth; -unsigned int triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) +int req_fuel_uS, inj_opentime_uS; #define MAX_RPM 10000 //This is the maximum rpm that the ECU will attempt to run at. It is NOT related to the rev limiter, but is instead dictates how fast certain operations will be allowed to run. Lower number gives better performance -volatile int toothCurrentCount = 0; //The current number of teeth (Onec sync has been achieved, this can never actually be 0 -volatile unsigned long toothLastToothTime = 0; //The time (micros()) that the last tooth was registered -volatile unsigned long toothLastMinusOneToothTime = 0; //The time (micros()) that the tooth before the last tooth was registered -volatile unsigned long toothOneTime = 0; //The time (micros()) that tooth 1 last triggered -volatile unsigned long toothOneMinusOneTime = 0; //The 2nd to last time (micros()) that tooth 1 last triggered -volatile int toothHistory[512]; -volatile int toothHistoryIndex = 0; volatile byte startRevolutions = 0; //A counter for how many revolutions have been completed since sync was achieved. volatile bool ignitionOn = true; //The current state of the ignition system +void (*trigger)(); //Pointer for the trigger function (Gets pointed to the relevant decoder) + struct table3D fuelTable; //8x8 fuel map struct table3D ignitionTable; //8x8 ignition map struct table3D afrTable; //8x8 afr target map @@ -148,6 +142,9 @@ void setup() triggerActualTeeth = configPage2.triggerTeeth - configPage2.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt inj_opentime_uS = configPage1.injOpen * 100; //Injector open time. Comes through as ms*10 (Eg 15.5ms = 155). + //Set the trigger function based on the decoder in the config + trigger = triggerPri_missingTooth; + //Begin the main crank trigger interrupt pin setup //The interrupt numbering is a bit odd - See here for reference: http://arduino.cc/en/Reference/AttachInterrupt //These assignments are based on the Arduino Mega AND VARY BETWEEN BOARDS. Please confirm the board you are using and update acordingly. @@ -586,49 +583,5 @@ void closeInjector1and4() { digitalWrite(pinInjector1, LOW); digitalWrite(pinInj void openInjector2and3() { digitalWrite(pinInjector2, HIGH); digitalWrite(pinInjector3, HIGH); BIT_SET(currentStatus.squirt, 1); } void closeInjector2and3() { digitalWrite(pinInjector2, LOW); digitalWrite(pinInjector3, LOW); BIT_CLEAR(currentStatus.squirt, 1); } -//The trigger function is called everytime a crank tooth passes the sensor -volatile unsigned long curTime; -volatile unsigned int curGap; -volatile unsigned int targetGap; -void trigger() - { - // http://www.msextra.com/forums/viewtopic.php?f=94&t=22976 - // http://www.megamanual.com/ms2/wheel.htm - noInterrupts(); //Turn off interrupts whilst in this routine - - curTime = micros(); - curGap = curTime - toothLastToothTime; - if ( curGap < triggerFilterTime ) { interrupts(); return; } //Debounce check. Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS) - toothCurrentCount++; //Increment the tooth counter - - //High speed tooth logging history - toothHistory[toothHistoryIndex] = curGap; - if(toothHistoryIndex == 511) - { toothHistoryIndex = 0; } - else - { toothHistoryIndex++; } - - //Begin the missing tooth detection - //If the time between the current tooth and the last is greater than 1.5x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after the gap - //if ( (curTime - toothLastToothTime) > (1.5 * (toothLastToothTime - toothLastMinusOneToothTime))) { toothCurrentCount = 1; } - if(configPage2.triggerMissingTeeth == 1) { targetGap = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 1; } //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to multiply by 3 then divide by 2. Much faster than multiplying by 1.5) - //else { targetGap = (10 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 2; } //Multiply by 2.5 (Checks for a gap 2.5x greater than the last one) - else { targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; } //Multiply by 2 (Checks for a gap 2x greater than the last one) - if ( curGap > targetGap ) - { - toothCurrentCount = 1; - toothOneMinusOneTime = toothOneTime; - toothOneTime = curTime; - currentStatus.hasSync = true; - startRevolutions++; //Counter - } - - toothLastMinusOneToothTime = toothLastToothTime; - toothLastToothTime = curTime; - - interrupts(); //Turn interrupts back on - - } -