Initial scheduler work

This commit is contained in:
Josh Stewart 2013-02-13 22:49:36 +11:00
parent aff1570ef7
commit 25253f0beb
4 changed files with 94 additions and 6 deletions

View File

@ -22,9 +22,14 @@ Need to calculate the req_fuel figure here, preferably in pre-processor macro
#include "utils.h"
#include "table.h"
#include "testing.h"
#include "scheduler.h"
//#include "TimerThree.h" //Enable this when switching to Mega
#include "TimerOne.h" //Enable this when using Leo based test board
//
float req_fuel = ((engineCapacity / engineInjectorSize) / engineCylinders / engineStoich) * 100; // This doesn't seem quite correct, but I can't find why. It will be close enough to start an engine
int req_fuel_uS = req_fuel * 1000; //Convert to uS and, importantly, an int. This is the only variable to be used in calculations
// Setup section
@ -43,7 +48,8 @@ volatile unsigned long toothLastMinusOneToothTime = 0; //The time (micros()) tha
int rpm = 0; //Stores the last recorded RPM value
struct table fuelTable;
unsigned long injectTime[engineCylinders]; //The system time in uS that each injector needs to next fire at
boolean intjectorNeedsFire[engineCylinders]; //Whether each injector needs to fire or not
void setup() {
@ -73,12 +79,13 @@ void setup() {
Serial.begin(9600);
dummyFuelTable(&fuelTable);
initialiseScheduler();
}
void loop()
{
delay(2500);
//Always check for sync
//Main loop runs within this clause
if (hasSync)
@ -87,7 +94,7 @@ void loop()
//Calculate the RPM based on the time between the last 2 teeth. I have no idea whether this will be accurate AT ALL, but it's fairly efficient and means there doesn't need to be another variable placed into the trigger interrupt
if (toothCurrentCount != 1) //We can't perform the RPM calculation if we're at the first tooth as the timing would be double (Well, we can, but it would need a different calculation and I don't think it's worth it, just use the last RPM value)
{
long revolutionTime = (triggerTeeth * (toothLastToothTime - toothLastMinusOneToothTime)); //The time in us that one revolution would take at current speed
long revolutionTime = (triggerTeeth * (toothLastToothTime - toothLastMinusOneToothTime)); //The time in uS that one revolution would take at current speed
rpm = US_IN_MINUTE / revolutionTime;
}
rpm = 1000;
@ -109,6 +116,10 @@ void loop()
//Serial.println(req_fuel * (float)(VE/100.0) * (float)(MAP/100.0) * (float)(100/100.0) + engineInjectorDeadTime);
//Serial.println( (float)(req_fuel * (float)(VE/100)) );
//Serial.println( (float)(VE/100.0));
Serial.print("Calling schedule at: ");
Serial.println(micros());
setSchedule1(openInjector2, 1000);
}
else
@ -137,6 +148,7 @@ void getSync()
//Interrupts
//These 2 functions simply trigger the injector driver off or on.
void openInjector2() { Serial.print("Interrupt finished at: "); Serial.println(micros());}
void openInjector() { digitalWrite(pinInjector, HIGH); } // Set based on an estimate of when to open the injector
void closeInjector() { digitalWrite(pinInjector, LOW); } // Is called x ms after the open time where x is calculated by the rpm, load and req_fuel

77
scheduler.h Normal file
View File

@ -0,0 +1,77 @@
/*
This scheduler is designed to maintain 2 schedules for use by the fuel and ignition systems.
It functions by waiting for the overflow vectors from each of the timers in use to overflow, which triggers an interrupt
//Technical
Currently I am prescaling the 8-bit timers to 256. This means that the counter increments every 16us and will overflow every 2017mS
Max Period = (Prescale)*(1/Frequency)*(2^17)
(See http://playground.arduino.cc/code/timer1)
Because the maximum overflow occurs roughly every 2 seconds, you cannot schedule anything to be more than 2 seconds in the future.
This also means that the precision of the scheduler is 16uS
/Features
This differs from most other schedulers in that its calls are non-recurring (IE You schedule an event at a certain time and once it has occurred, it will not reoccur unless you explicitely ask for it)
Each timer can have only 1 callback associated with it at any given time. If you call the setCallback function a 2nd time, the original schedule will be overwritten and not occur
Timer identification
The Adrduino timer2 is used for schedule 1
The Arduino timer3 is used for schedule 2
*/
#include <avr/interrupt.h>
#include <avr/io.h>
#define clockspeed 16000000
int schedule1Active;
int schedule2Active;
void (*schedule1Callback)();
void (*schedule2Callback)();
void initialiseScheduler()
{
// Much help in this from http://arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html
//Timer 2, which is actually timer 1
TCCR3B = 0x00; //Disbale Timer2 while we set it up
TCNT3 = 130; //Reset Timer Count to 130 out of 255
TIFR3 = 0x00; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK3 = 0x01; //Timer2 INT Reg: Timer2 Overflow Interrupt Enable
TCCR3A = 0x00; //Timer2 Control Reg A: Wave Gen Mode normal
TCCR3B = (1 << CS12); //Timer2 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
}
/*
This turns schedule 1 on, gives it a callback functino and resets the relevant timer based on the time in the future that this should be triggered
Args:
callback: The function to be called once the timeout is reach
timeout: The number of uS in the future that the callback should be triggered
*/
void setSchedule1(void (*callback)(), unsigned long timeout)
{
//We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
//As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
///TCNT2 = ((255 - (timeout>>4)) * 256) / clockspeed;
//TCNT2 = (timeout / 8192);
TCNT3 = 1;
schedule1Callback = callback; //Name the callback function
schedule1Active = 1; //Turn this schedule on
}
//Timer2 (schedule 1) Overflow Interrupt Vector
//This needs to call the callback function if one has been provided and rest the timer
ISR(TIMER3_OVF_vect)
{
if (schedule1Active > 0) //Check to see if this schedule is turn on
{
schedule1Callback(); //Replace with user provided callback
schedule1Active = 0; //Turn off the callback
}
TCNT3 = 0; //Reset Timer to 0 out of 255
TIFR3 = 0x00; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
}

View File

@ -2,7 +2,6 @@
This file is used for everything related to maps/tables including their definition, functions etc
*/
struct table {
//All tables must be the same size for simplicity
const static int xSize = 8;

View File

@ -1,6 +1,6 @@
/*
These are some utility functions and variables used through the main code
*/
*/
#define MS_IN_MINUTE 60000
#define US_IN_MINUTE 60000000