Speeduino
Loading...
Searching...
No Matches
schedule_calcs.hpp
Go to the documentation of this file.
1#pragma once
2// Note that all functions with an underscore prefix are NOT part
3// of the public API. They are only here so we can inline them.
4
5#include "scheduler.h"
6#include "crankMaths.h"
7#include "maths.h"
8#include "timers.h"
9#include "preprocessor.h"
10#include "atomic.h"
11#include "statuses.h"
12
22{
23 // 0<=injAngle<=720°
24 // 0<=injChannelDegrees<=720°
25 // 0<pwDegrees<=??? (could be many crank rotations in the worst case!)
26 // 45<=CRANK_ANGLE_MAX_INJ<=720
27 // (CRANK_ANGLE_MAX_INJ can be as small as 360/nCylinders. E.g. 45° for 8 cylinder)
28
29 uint16_t startAngle = injAngle + schedule.channelDegrees;
30
31 while (startAngle<pwDegrees) { startAngle = startAngle + (uint16_t)CRANK_ANGLE_MAX_INJ; } // Avoid underflow
32 startAngle = startAngle - pwDegrees; // startAngle guaranteed to be >=0.
33 while (startAngle>=(uint16_t)CRANK_ANGLE_MAX_INJ) { startAngle = startAngle - (uint16_t)CRANK_ANGLE_MAX_INJ; } // Clamp to 0<=startAngle<=CRANK_ANGLE_MAX_INJ
34
35 return startAngle;
36}
37
42
44 // We can afford to be a bit loose updating the cache since injection timing doesn't
45 // need to be precise (the PW calcs liberally use approximations)
46 //
47 // 1% of a revolution at max RPM should be plenty accurate.
48 constexpr int16_t PW_DELTA_THRESHOLD = MIN_REVOLUTION_TIME/100U; // in µS
50 pCache->pwDegrees = timeToAngle(pw);
51 pCache->pw = pw;
52 }
53 return pCache->pwDegrees;
54}
55
64
70
72 if (angleOffset==0U) { // Optimize for zero channel angle - no need to adjust start & crank angles
74 }
75 // Realign the current crank angle and the desired start angle around 0 degrees for the given cylinder/output
76 // Eg: If cylinder 2 TDC is 180 degrees after cylinder 1 (E.g. a standard 4 cylinder engine), then
77 // adjusted crank angle is 180* less than the current crank angle and adjusted start angle is the desired open angle less 180*.
78 // Thus the cylinder is being treated relative to its own TDC, regardless of its offset
79 //
80 // This is done to avoid very small or very large deltas between crank angle and start angle.
84 maxAngle);
85}
86
96{
98
99 if (delta<0)
100 {
101 if (schedule._status != PENDING)
102 {
103 while(delta < 0) { delta += CRANK_ANGLE_MAX_INJ; }
104 }
105 else
106 {
107 delta = 0;
108 return 0U;
109 }
110 }
111 return angleToTime((uint16_t)delta);
112}
113
115 int16_t angle = (int16_t)(schedule.channelDegrees==0U ? CRANK_ANGLE_MAX_IGN : schedule.channelDegrees) - advance;
117 return angle;
118}
119
121 if (dischargeAngle>(int16_t)dwellAngle) {
122 return dischargeAngle - (int16_t)dwellAngle;
123 }
124 return dischargeAngle + CRANK_ANGLE_MAX_IGN - (int16_t)dwellAngle;
125}
126
132
133
139
144
156 constexpr uint8_t MIN_CYCLES_FOR_CORRECTION = 6U;
157
159 ATOMIC() { // Prevent race conditions with the timer interrupt.
160 // We only want to adjust the crank angle if we are running and the coil is charging or we are waiting for the timer to fire.
161 if( isRunning(schedule) ) {
162 if (schedule.dischargeAngle>crankAngle) {
163 // Coil is charging so change the charge time so the spark fires at
164 // the requested crank angle (this could reduce dwell time & potentially
165 // result in a weaker spark).
166 SET_COMPARE(schedule._compare, schedule._counter + angleToTimerTicks( schedule.dischargeAngle-crankAngle ));
167 }
168 }
169 else if( (schedule._status==PENDING) ) {
170 if ((current.startRevolutions > MIN_CYCLES_FOR_CORRECTION) && (schedule.chargeAngle>crankAngle)) {
171 // We are waiting for the timer to fire & start charging the coil.
172 // Keep dwell (I.e. duration) constant (for better spark) - instead adjust the waiting period so
173 // the spark fires at the requested crank angle.
174 SET_COMPARE(schedule._compare, schedule._counter + angleToTimerTicks( schedule.chargeAngle-crankAngle ));
175 }
176 } else {
177 // Unknown state, so no adjustment possible
178 }
179 }
180}
#define SET_COMPARE(compare, value)
Definition board_definition.h:86
int16_t CRANK_ANGLE_MAX_IGN
The number of crank degrees that the system tracks ignition over.
Definition crankMaths.cpp:14
int16_t CRANK_ANGLE_MAX_INJ
The number of crank degrees that the system tracks fuel injection over.
Definition crankMaths.cpp:15
Crank revolution based mathematical functions.
uint16_t timeToAngle(uint32_t time) noexcept
Converts a time interval in microsecods to the equivalent degrees of angular (crank) rotation at curr...
COMPARE_TYPE angleToTimerTicks(uint16_t angle) noexcept
Converts angular degrees to the equivalent timer ticks at current RPM.
static int16_t ignitionLimits(int16_t angle)
Makes one pass at nudging the angle to within [0,CRANK_ANGLE_MAX_IGN].
Definition crankMaths.h:54
uint32_t angleToTime(uint16_t angle) noexcept
Converts angular degrees to the time interval that amount of rotation will take at current RPM.
static constexpr uint16_t MIN_REVOLUTION_TIME
Minimum time in µS that one crank revolution can take.
Definition crankMaths.h:36
page_iterator_t advance(const page_iterator_t &iter)
Definition pages.cpp:529
#define FORCE_INLINE
Definition preprocessor.h:82
static uint32_t _calculateIgnitionTimeout(const IgnitionSchedule &schedule, int16_t crankAngle)
Definition schedule_calcs.hpp:140
static uint32_t calculateInjectorTimeout(const FuelSchedule &schedule, int16_t crankAngle, uint16_t openAngle)
Calculate the time in uS from now to when the injector should be opened.
Definition schedule_calcs.hpp:95
static uint16_t updatePwAngleCache(uint16_t pw, injectorAngleCalcCache *pCache)
Definition schedule_calcs.hpp:43
static int16_t _calculateSparkAngle(const IgnitionSchedule &schedule, int8_t advance)
Definition schedule_calcs.hpp:114
static FORCE_INLINE uint16_t _adjustToTDC(int16_t angle, uint16_t angleOffset, uint16_t maxAngle)
Definition schedule_calcs.hpp:65
static void adjustCrankAngle(const statuses &current, IgnitionSchedule &schedule, int16_t crankAngle)
Adjust the crank angle used to originally set the schedule.
Definition schedule_calcs.hpp:155
static int16_t _calculateCoilChargeAngle(uint16_t dwellAngle, int16_t dischargeAngle)
Definition schedule_calcs.hpp:120
static void calculateIgnitionAngles(IgnitionSchedule &schedule, uint16_t dwellAngle, int8_t advance)
Definition schedule_calcs.hpp:127
static uint16_t _calculateOpenAngle(FuelSchedule &schedule, uint16_t pwDegrees, uint16_t injAngle)
Compute the injector open angle for an injection channel.
Definition schedule_calcs.hpp:21
static void calculateIgnitionTrailingRotary(IgnitionSchedule &leading, uint16_t dwellAngle, int16_t rotarySplitDegrees, IgnitionSchedule &trailing)
Definition schedule_calcs.hpp:134
static FORCE_INLINE uint32_t _calculateAngularTime(const Schedule &schedule, uint16_t eventAngle, uint16_t crankAngle, uint16_t maxAngle)
Definition schedule_calcs.hpp:56
@ PENDING
Definition scheduler.h:56
@ OFF
Definition scheduler.h:54
static bool isRunning(const Schedule &schedule) noexcept
Is the schedule running? I.e. the action has started, but not finished. E.g. injector is open.
Definition scheduler.h:133
const config2 const config4 const config6 statuses & current
Definition scheduler_fuel_controller.cpp:402
uint16_t crankAngle
Definition scheduler_ignition_controller.cpp:462
uint16_t dwellAngle
Definition scheduler_ignition_controller.cpp:433
The statuses struct and related defines.
A fuel injection schedule.
Definition scheduler.h:207
An ignition schedule.
Definition scheduler.h:177
A schedule for a single output channel.
Definition scheduler.h:86
Definition array.h:14
Definition schedule_calcs.hpp:38
uint16_t pwDegrees
Definition schedule_calcs.hpp:40
uint16_t pw
Definition schedule_calcs.hpp:39
The status struct with current values for all 'live' variables.
Definition statuses.h:47