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
19{
20 // 0<=injAngle<=720°
21 // 0<=injChannelDegrees<=720°
22 // 0<pwDegrees<=??? (could be many crank rotations in the worst case!)
23 // 45<=CRANK_ANGLE_MAX_INJ<=720
24 // (CRANK_ANGLE_MAX_INJ can be as small as 360/nCylinders. E.g. 45° for 8 cylinder)
25
26 uint16_t startAngle = injAngle + schedule.channelDegrees;
27
28 while (startAngle<pwDegrees) { startAngle = startAngle + (uint16_t)CRANK_ANGLE_MAX_INJ; } // Avoid underflow
29 startAngle = startAngle - pwDegrees; // startAngle guaranteed to be >=0.
30 while (startAngle>=(uint16_t)CRANK_ANGLE_MAX_INJ) { startAngle = startAngle - (uint16_t)CRANK_ANGLE_MAX_INJ; } // Clamp to 0<=startAngle<=CRANK_ANGLE_MAX_INJ
31
32 return startAngle;
33}
34
39
41 // We can afford to be a bit loose updating the cache since injection timing doesn't
42 // need to be precise (the PW calcs liberally use approximations)
43 //
44 // 1% of a revolution at max RPM should be plenty accurate.
45 constexpr int16_t PW_DELTA_THRESHOLD = MIN_REVOLUTION_TIME/100U; // in µS
48 pCache->pw = pw;
49 }
50 return pCache->pwDegrees;
51}
52
61
67
69 if (angleOffset==0U) { // Optimize for zero channel angle - no need to adjust start & crank angles
71 }
72 // Realign the current crank angle and the desired start angle around 0 degrees for the given cylinder/output
73 // Eg: If cylinder 2 TDC is 180 degrees after cylinder 1 (E.g. a standard 4 cylinder engine), then
74 // adjusted crank angle is 180* less than the current crank angle and adjusted start angle is the desired open angle less 180*.
75 // Thus the cylinder is being treated relative to its own TDC, regardless of its offset
76 //
77 // This is done to avoid very small or very large deltas between crank angle and start angle.
81 maxAngle);
82}
83
93{
95
96 if (delta<0)
97 {
98 if (schedule._status != PENDING)
99 {
100 while(delta < 0) { delta += CRANK_ANGLE_MAX_INJ; }
101 }
102 else
103 {
104 delta = 0;
105 return 0U;
106 }
107 }
109}
110
112 int16_t angle = (int16_t)(schedule.channelDegrees==0U ? CRANK_ANGLE_MAX_IGN : schedule.channelDegrees) - advance;
114 return angle;
115}
116
118 if (dischargeAngle>(int16_t)dwellAngle) {
119 return dischargeAngle - (int16_t)dwellAngle;
120 }
121 return dischargeAngle + CRANK_ANGLE_MAX_IGN - (int16_t)dwellAngle;
122}
123
129
130
136
141
153 constexpr uint8_t MIN_CYCLES_FOR_CORRECTION = 6U;
154
156 ATOMIC() { // Prevent race conditions with the timer interrupt.
157 // 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.
158 if( isRunning(schedule) ) {
159 if (schedule.dischargeAngle>crankAngle) {
160 // Coil is charging so change the charge time so the spark fires at
161 // the requested crank angle (this could reduce dwell time & potentially
162 // result in a weaker spark).
163 SET_COMPARE(schedule._compare, schedule._counter + angleToTimerTicks( schedule.dischargeAngle-crankAngle ));
164 }
165 }
166 else if( (schedule._status==PENDING) ) {
167 if ((currentStatus.startRevolutions > MIN_CYCLES_FOR_CORRECTION) && (schedule.chargeAngle>crankAngle)) {
168 // We are waiting for the timer to fire & start charging the coil.
169 // Keep dwell (I.e. duration) constant (for better spark) - instead adjust the waiting period so
170 // the spark fires at the requested crank angle.
171 SET_COMPARE(schedule._compare, schedule._counter + angleToTimerTicks( schedule.chargeAngle-crankAngle ));
172 }
173 } else {
174 // Unknown state, so no adjustment possible
175 }
176 }
177}
static integerPID_ideal boostPID & currentStatus
Definition auxiliaries.cpp:188
#define SET_COMPARE(compare, value)
Definition board_definition.h:80
Crank revolution based mathematical functions.
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:51
uint32_t angleToTimeMicroSecPerDegree(uint16_t angle) noexcept
Converts angular degrees to the time interval that amount of rotation will take at current RPM.
uint16_t timeToAngleDegPerMicroSec(uint32_t time) noexcept
Converts a time interval in microsecods to the equivalent degrees of angular (crank) rotation at curr...
static constexpr uint16_t MIN_REVOLUTION_TIME
Minimum time in µS that one crank revolution can take.
Definition crankMaths.h:36
int16_t CRANK_ANGLE_MAX_IGN
Definition globals.cpp:32
int16_t CRANK_ANGLE_MAX_INJ
The number of crank degrees that the system track over. Typically 720 divided by the number of squirt...
Definition globals.cpp:33
static TIntegral readSerialIntegralTimeout(void)
Reads an integral type, timing out if necessary.
Definition comms.cpp:175
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:137
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:92
static uint16_t updatePwAngleCache(uint16_t pw, injectorAngleCalcCache *pCache)
Definition schedule_calcs.hpp:40
static int16_t _calculateSparkAngle(const IgnitionSchedule &schedule, int8_t advance)
Definition schedule_calcs.hpp:111
static FORCE_INLINE uint16_t _adjustToTDC(int16_t angle, uint16_t angleOffset, uint16_t maxAngle)
Definition schedule_calcs.hpp:62
static int16_t _calculateCoilChargeAngle(uint16_t dwellAngle, int16_t dischargeAngle)
Definition schedule_calcs.hpp:117
static void calculateIgnitionAngles(IgnitionSchedule &schedule, uint16_t dwellAngle, int8_t advance)
Definition schedule_calcs.hpp:124
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:18
static void adjustCrankAngle(IgnitionSchedule &schedule, int16_t crankAngle)
Adjust the crank angle used to originally set the schedule.
Definition schedule_calcs.hpp:152
static void calculateIgnitionTrailingRotary(IgnitionSchedule &leading, uint16_t dwellAngle, int16_t rotarySplitDegrees, IgnitionSchedule &trailing)
Definition schedule_calcs.hpp:131
static FORCE_INLINE uint32_t _calculateAngularTime(const Schedule &schedule, uint16_t eventAngle, uint16_t crankAngle, uint16_t maxAngle)
Definition schedule_calcs.hpp:53
@ PENDING
Definition scheduler.h:57
@ OFF
Definition scheduler.h:55
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:134
uint16_t crankAngle
Definition scheduler_ignition_controller.cpp:437
uint16_t dwellAngle
Definition scheduler_ignition_controller.cpp:408
A fuel injection schedule.
Definition scheduler.h:208
An ignition schedule.
Definition scheduler.h:178
A schedule for a single output channel.
Definition scheduler.h:87
Definition schedule_calcs.hpp:35
uint16_t pwDegrees
Definition schedule_calcs.hpp:37
uint16_t pw
Definition schedule_calcs.hpp:36