/* * TTDOnanOct13, 2017: * I am starting all over to produce an ignition driver for the Onan ECU project * I am using the TTDAug292017MoveCalcsOutOfNISR sketch as my base because it has NO drift. * * To Do: * Change the 180 to 360---okay * Change 3ms coil charge to 6 ms coil charge and make it a defined variable * NOte: I made it into a variable and that works, but changing to 6000 from 3000 gives lots of drift. * Note2: so, I will leave it at 3000 for now (no drift) and fix the advance stuff next. * Note3: I did fix the advance stuff and still no drift. Putting 6000 into makeSparks still shows no drift. * But it is apparently the advance formula where the coilTime at 6000 causes the problem. * Get rid of all advance stuff except for "run" * Set nosparks to anything less than 200 rpms * Set run to anything above 200 rpms * Set "run" advance to -20 degrees. * * Do these steps one at a time to verify that drift does not creep in. * I made timeLostinISR (the 1980 number in the makeOneDegree function) a constant variable so I can play with it versus * coilTime. */ #include #include //-------------------------------------------- //CTC Libraries, which are NOT used, are they? #include #include //--------------------------------------------------------------------------- volatile unsigned long _hits; volatile unsigned long currentMicros; volatile unsigned long previousStartTime; const int coilTime = 6000; const int timeLostinISR = (1980 +(coilTime-3000)); int rpm =0; int _rpm; int _previousRPM; unsigned long _startTime; int _rpmChange; int _pin; int _slotsPerRevolution; volatile unsigned long elapsedTime; volatile unsigned long etCorrected; volatile long _oneDegree; const int timer1Pin = 7; const int triggerPin = 8; const int strobeLed = 13; int coilPulsePot = A1; int triggerTime; int triggerMsec; volatile int triggerNorth = 0; volatile unsigned long delta; volatile int rpmTemp; volatile unsigned long advance = 0; long int advanceFormula; volatile unsigned int advanceRange; //Time range in microseconds for 1/2 of a rev. volatile float oneDegree; //The time it takes for the crank to advance one degree at the current rpm, I think. volatile long advancePeriod;//One element of the time to add to or subtract from 1/2 rev time before making a spark volatile unsigned long advanceDelay = 0; volatile unsigned long sparkDelay = 0; volatile boolean sparkOn = false; //Used to shut off sparks when not wanted. volatile boolean engineStopped = true; //To be used wherever I need it. Do these boolean variables need to be "volatile"? volatile boolean engineRunning =false; //Opposite of engineStopped; To be used wherever I need it volatile int sparkTimingDegrees = 0; //--------------------------------------------------------------------------- LiquidCrystal_I2C lcd(0x27, 2, 1, 0,4 ,5, 6, 7, 3, POSITIVE); // set the LCD I2C address //---------------------------------------------------------------------------- void setup() { pinMode(triggerPin, OUTPUT); pinMode(timer1Pin, OUTPUT); pinMode(strobeLed, OUTPUT); pinMode(coilPulsePot, INPUT); Serial.begin(115200); //--------------------------- lcd.begin(20,4); lcd.backlight(); lcd.clear(); lcd.begin(20, 4); // set up the LCD's number of columns and rows: lcd.print("RPM: S_hits TCNT1 N"); lcd.setCursor(0, 2); lcd.print("delta"); lcd.setCursor (7, 2); lcd.print("Loop"); //-------------------------- attachInterrupt(0, beam_interrupt, FALLING); pinMode(3, INPUT); attachInterrupt(1, beam_interruptN, FALLING); //--------------------Timer Compare Match Code--------------------------- // initialize Timer1 cli(); // disable global interrupts while doing this TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B // set compare match register to desired timer count: OCR1A = advance; //Initially setting OCR1A to zero because advance is declared as zero TCCR1B |= (1 << WGM12); // turn on CTC mode TCCR1B = _BV(CS00) | _BV(CS01); //Prescale = 64, but a little faster, maybe TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt: sei(); // enable global interrupts: } //----------------------------------------------------------------------- //Interrupt 0 ISR //Capture the 3 South Hall Semsor Falling Pulse for use in reading RPMs //Not used at present //---------------------------------------------------------------------- void beam_interrupt() //Capture 3 South magnets, Hall Effect sensor Falling pulse, { ++_hits; } //Interrupt 1 ISR //Capture the North Hall Sensor signal for use in trigger signal and also //use it in reading RPMs //------------------------------------------------------------------------ void beam_interruptN() { //Develop "oneDegree" by counting the time between N Magnets on the rotor //This is THE KEY value I use to calculate ignition timing and rpm currentMicros = micros(); elapsedTime = (currentMicros- previousStartTime); previousStartTime = currentMicros; //Start timer1, using Prescale value of 64 TCCR1B = _BV(CS00) | _BV(CS01); } //-------------------------------------------------- //Timer1 Compare Match ISR: This routine fires at the end of the icnition timing delay period ISR(TIMER1_COMPA_vect) { //global disable interrupts cli(); TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // Stop the counter TCNT1 = 0; //Rest the counter to zero digitalWrite(7, !digitalRead(7)); //This line is here for debugging, only to toggle an LED on Pin 7 //whenever timer1 reaches compare match to prove that the timer IS working makeSparks(); //Coil charging function. sei(); //Global enable interrupts } //------------------------------------------------------------------------------- //Here's where the sparks are made; Coil Charging begins for a set time, //times out, and ends with a spark and a Strobe LED void makeSparks() { if(sparkOn) { digitalWrite(triggerPin, HIGH); //This is where coil charging begins delayMicroseconds(coilTime); //This fixes Coil Charge peroid digitalWrite(triggerPin, LOW); //This is where the spark actually occurs. digitalWrite(strobeLed, HIGH); delayMicroseconds(50); //This is the on-period for the strobe. digitalWrite(strobeLed, LOW); } } //--------------Main Loop To Calculate RPM, Update LCD Display and Serial Monitor---------------- void loop() { //Beginning of Code to measure loop time unsigned long startLoopCount = micros(); //End of Code to measure loop time //make oneDegree etCorrected =elapsedTime +timeLostinISR; oneDegree = etCorrected/360.0; rpm =1000000 * 60/(oneDegree * 360); // time for one revolution; advance = ((((360.0 + sparkTimingDegrees)* oneDegree)-coilTime)/4.0); //This divide by 4 works well, //but still gives me OCR1A overlfow at about 127 rpm, but I can live with that. OCR1A = advance; //displayRPM_LCD(); //Only turned on for testing. Takes too long!!! displayRPM_Serial(); //Much shorter than I2C LCD. //Ignition delay calculations here: //--------------------------------- if (rpm <200) { //0 to 200 rpms; too slow, no sparks sparkOn = false; sparkTimingDegrees = 10; } else if (rpm >= 200) { // 200 to max rpms; running advancePeriod = (oneDegree * -20); sparkOn = true; sparkTimingDegrees = -20; } //End ignition delay code //----------------------- //Last part of Code to measure loop time unsigned long end = micros(); delta = end - startLoopCount; //End of Code to measure loop time } //------------------------------------------------------------ //End of the Loop-----End of the Loop----End Of The Loop==== //----------------------------------------------------------- void displayRPM_LCD() //IF it is turned on!!! { lcd.setCursor(0, 1); lcd.print(" "); //To clear the previous reading lcd.setCursor(0, 1); lcd.print(rpm); lcd.print(" "); lcd.print(_hits); lcd.setCursor(0, 3); lcd.print(" "); lcd.setCursor(0, 3); lcd.print(delta); } void displayRPM_Serial() { /* Serial.print(rpm); Serial.print(" "); Serial.print(delta); Serial.print(" "); Serial.print(oneDegree); Serial.print(" "); Serial.print(_hits); Serial.print(" "); Serial.print(OCR1A/rpm); Serial.print(" "); Serial.println(rpm/OCR1A); */ Serial.println(oneDegree); }