diff --git a/reference/speeduino.ini b/reference/speeduino.ini index fe6ff760..94df42e9 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -360,7 +360,7 @@ page = 1 fanWhenOff = bits, U08, 70, [0:0], "No", "Yes" fanWhenCranking = bits, U08, 70, [1:1], "No", "Yes" useDwellMap = bits, U08, 70, [2:2], "No", "Yes" - unused_fan_bits = bits, U08, 70, [3:4] + fanEnable = bits, U08, 70, [3:4], "Off", "On/Off", "PWM", "INVALID" rtc_mode = bits, U08, 70, [5:6], "Off", "On-board", "INVALID", "INVALID" incorporateAFR = bits, U08, 70, [7:7], "No", "Yes" @@ -698,7 +698,7 @@ page = 6 ; Begin fan control vairables fanInv = bits, U08, 120, [0:0], "No", "Yes" - fanEnable = bits, U08, 120, [1:1], "Off", "On/Off" + fanUnused = bits, U08, 120, [1:1], "Off", "On/Off" fanPin = bits, U08, 120, [2:7], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID" #if CELSIUS fanSP = scalar, U08, 121, "C", 1.0, -40, -40, 215.0, 0 @@ -1012,7 +1012,8 @@ page = 9 boostByGear5 = scalar, U08, 160, { bitStringValue(boostByGearLabels , boostByGearEnabled) }, 2.0, 0.0, 0.0, 511.0, 0 boostByGear6 = scalar, U08, 161, { bitStringValue(boostByGearLabels , boostByGearEnabled) }, 2.0, 0.0, 0.0, 511.0, 0 - unused10_160 = array, U08, 162, [30], "", 1, 0, 0, 255, 0 + PWMFanDuty = array, U08, 162, [4], "%", 0.5, 0, 0, 100, 1 + unused10_160 = array, U08, 166, [26], "", 1, 0, 0, 255, 0 page = 10 #if CELSIUS @@ -1728,6 +1729,7 @@ menuDialog = main menu = "&Accessories" subMenu = fanSettings, "Thermo Fan" + subMenu = pwmFan, "PWM Fan Curve", { fanEnable == 2 } subMenu = LaunchControl, "Launch Control / Flat Shift" subMenu = fuelpump, "Fuel Pump" subMenu = NitrousControl, "Nitrous" @@ -2481,13 +2483,18 @@ menuDialog = main dialog = fanSettings,"Fan Settings",7 topicHelp = "https://wiki.speeduino.com/en/configuration/Thermo_fan" + displayOnlyField = !"No PWM Fan available on MCU", blankfield, {intcan_available == 0 && fanEnable == 2},{intcan_available == 0 && fanEnable == 2} field = "Fan Mode", fanEnable field = "Allow fan when off", fanWhenOff, { fanEnable } field = "Allow fan when cranking", fanWhenCranking, { fanEnable } field = "Fan output pin", fanPin, { fanEnable } field = "Fan Output Inverted", fanInv, { fanEnable } - field = "Fan switching temperature", fanSP, { fanEnable } - field = "Fan hysteresis", fanHyster, { fanEnable } + field = "Fan switching temperature", fanSP, { fanEnable == 1 } + field = "Fan hysteresis", fanHyster, { fanEnable == 1 } + field = "PWM fan frequency", fanFreq, { intcan_available && fanEnable == 2 } + + dialog = pwmFan, "PWM Fan Curve", + panel = pwm_fan_curve, dialog = stepper_idle, "Stepper Idle" field = "Step time (ms)", iacStepTime, { iacAlgorithm == 4 || iacAlgorithm == 5 } @@ -4179,6 +4186,16 @@ cmdVSSratio6 = "E\x99\x06" yBins = idleAdvValues size = 450, 200 +; PWM Fan duty curve based on temp input + curve = pwm_fan_curve, "Fan PWM Duty" + columnLabel = "Temp", "Duty %" + xAxis = -40, 215, 4 + yAxis = 0, 100, 4 + xBins = fanPWMBins, coolant + yBins = PWMFanDuty + gauge = cltGauge + size = 400, 400 + ; Curves for idle control ; Standard duty table for PWM valves curve = iacPwm_curve, "IAC PWM Duty" @@ -4597,6 +4614,7 @@ cmdVSSratio6 = "E\x99\x06" lambdaTargetGauge = lambdaTarget, "Target Lambda", "", 0.5, 1.5, 0.82, 0.89, 1.02, 1.09, 3, 3 IdleTargetGauge = CLIdleTarget, "Idle Target RPM", "RPM", 0, 2000, 300, 600, 1500, 1700, 0, 0 idleLoadGauge = idleLoad, "IAC Value", "%/Steps", 0, {maphigh}, 0, 20, {mapwarn}, {mapdang}, 0, 0 + FANdutyCycleGauge = fanDuty, "FAN Duty Cycle", "%", 0, 100, -1, -1, 101, 110, 1, 1 vvt1DutyCycleGauge= vvt1Duty, "VVT Duty Cycle", "%", 0, 100, -1, -1, 101, 110, 1, 1 vvt1TargetGauge = vvt1Target, "VVT Target Angle", "deg", 0, 100, 15, 25, 65, 75, 1, 1 vvt1AngleGauge = vvt1Angle, "VVT Angle", "deg", -20, 100, 0, -5, 70, 90, 1, 1 @@ -4605,7 +4623,7 @@ cmdVSSratio6 = "E\x99\x06" vvt2AngleGauge = vvt2Angle, "VVT2 Angle", "deg", -20, 100, 0, -5, 70, 90, 1, 1 WMIdutyCycleGauge = wmiPW, "WMI Duty Cycle", "%", 0, 100, -1, -1, 101, 110, 1, 1 - + gaugeCategory = "Sensor inputs" mapGauge = map, "Engine MAP", "kPa", 0, {maphigh}, 0, 20, {mapwarn}, {mapdang}, 0, 0 mapGauge_psi = map_psi, "Engine MAP (PSI)", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 @@ -4741,7 +4759,7 @@ cmdVSSratio6 = "E\x99\x06" ; you change it. ochGetCommand = "r\$tsCanId\x30%2o%2c" - ochBlockSize = 121 + ochBlockSize = 122 secl = scalar, U08, 0, "sec", 1.000, 0.000 status1 = scalar, U08, 1, "bits", 1.000, 0.000 @@ -4882,9 +4900,10 @@ cmdVSSratio6 = "E\x99\x06" advance2 = scalar, S08, 117, "deg", 1.000, 0.000 sd_status = scalar, U08, 118, "", 1.0, 0.0 emap = scalar, U16, 119, "kpa", 1.000, 0.000 - ;sd_filenum = scalar, U16, 117, "", 1, 0 - ;sd_error = scalar, U08, 119, "", 1, 0 - ;sd_phase = scalar, U08, 120, "", 1, 0 + fanDuty = scalar, U08, 121, "%", 0.5, 0.000 + ;sd_filenum = scalar, U16, 122, "", 1, 0 + ;sd_error = scalar, U08, 124, "", 1, 0 + ;sd_phase = scalar, U08, 125, "", 1, 0 #if CELSIUS coolant = { coolantRaw - 40 } ; Temperature readings are offset by 40 to allow for negatives @@ -5030,7 +5049,8 @@ cmdVSSratio6 = "E\x99\x06" entry = vvt2Angle, "VVT2 Angle", int, "%.1f", { vvt2Enabled > 0 } entry = vvt2Target, "VVT2 Target Angle",int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt entry = vvt2Duty, "VVT2 Duty", int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } - entry = loopsPerSecond, "Loops/s", int, "%d" + entry = fanDuty, "FAN Duty", int, "%d", { fanEnable == 2 } + entry = loopsPerSecond, "Loops/s", int, "%d" entry = auxin_gauge0, { stringValue(AUXin00Alias) }, int, "%d", {(caninput_sel0b != 0)} entry = auxin_gauge1, { stringValue(AUXin01Alias) }, int, "%d", { (caninput_sel1b != 0)} diff --git a/speeduino/auxiliaries.h b/speeduino/auxiliaries.h index 88870ea4..f84b0e1f 100644 --- a/speeduino/auxiliaries.h +++ b/speeduino/auxiliaries.h @@ -64,13 +64,17 @@ long boost_pwm_target_value; long boost_cl_target_boost; byte boostCounter; byte vvtCounter; +#if defined(PWM_FAN_AVAILABLE)//PWM fan not available on Arduino MEGA +volatile bool fan_pwm_state; +unsigned int fan_pwm_max_count; //Used for variable PWM frequency +volatile unsigned int fan_pwm_cur_value; +long fan_pwm_value; +void fanInterrupt(); +#endif uint32_t vvtWarmTime; bool vvtIsHot; bool vvtTimeHold; -byte fanHIGH = HIGH; // Used to invert the cooling fan output -byte fanLOW = LOW; // Used to invert the cooling fan output - volatile bool vvt1_pwm_state; volatile bool vvt2_pwm_state; volatile bool vvt1_max_pwm; diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index 5d2f1332..6e2f4735 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -21,18 +21,28 @@ Fan control */ void initialiseFan() { - if( configPage6.fanInv == 1 ) { fanHIGH = LOW; fanLOW = HIGH; } - else { fanHIGH = HIGH; fanLOW = LOW; } - digitalWrite(pinFan, fanLOW); //Initiallise program with the fan in the off state currentStatus.fanOn = false; - fan_pin_port = portOutputRegister(digitalPinToPort(pinFan)); fan_pin_mask = digitalPinToBitMask(pinFan); + FAN_OFF(); //Initiallise program with the fan in the off state + currentStatus.fanDuty = 0; + +#if defined(PWM_FAN_AVAILABLE) + DISABLE_FAN_TIMER(); //disable FAN timer if available + if ( configPage2.fanEnable == 2 ) // PWM Fan control + { + #if defined(CORE_TEENSY) + fan_pwm_max_count = 1000000L / (32 * configPage6.fanFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz + #endif + fan_pwm_value = 0; + } +#endif + } void fanControl() { - if( configPage6.fanEnable == 1 ) + if( configPage2.fanEnable == 1 ) // regular on/off fan control { int onTemp = (int)configPage6.fanSP - CALIBRATION_TEMPERATURE_OFFSET; int offTemp = onTemp - configPage6.fanHyster; @@ -62,6 +72,68 @@ void fanControl() currentStatus.fanOn = false; } } + else if( configPage2.fanEnable == 2 )// PWM Fan control + { + bool fanPermit = false; + if ( configPage2.fanWhenOff == true) { fanPermit = true; } + else { fanPermit = BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN); } + if (fanPermit == true) + { + if(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) && (configPage2.fanWhenCranking == 0)) + { + currentStatus.fanDuty = 0; //If the user has elected to disable the fan during cranking, make sure it's off + currentStatus.fanOn = false; + #if defined(PWM_FAN_AVAILABLE)//PWM fan not available on Arduino MEGA + DISABLE_FAN_TIMER(); + #endif + } + else + { + currentStatus.fanDuty = table2D_getValue(&fanPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //In normal situation read PWM duty from the table + #if defined(PWM_FAN_AVAILABLE) + fan_pwm_value = halfPercentage(currentStatus.fanDuty, fan_pwm_max_count); //update FAN PWM value last + if (currentStatus.fanDuty > 0) + { + currentStatus.fanOn = true; // update fan on status. Is this even used anywhere?? + ENABLE_FAN_TIMER(); + } + #endif + } + } + else if (!fanPermit) + { + currentStatus.fanDuty = 0; ////If the user has elected to disable the fan when engine is not running, make sure it's off + } + + #if defined(PWM_FAN_AVAILABLE) + if(currentStatus.fanDuty == 0) + { + //Make sure fan has 0% duty) + FAN_OFF(); + currentStatus.fanOn = false; + DISABLE_FAN_TIMER(); + } + else if (currentStatus.fanDuty == 200) + { + //Make sure fan has 100% duty + FAN_ON(); + DISABLE_FAN_TIMER(); + } + #else //Just in case if user still has selected PWM fan in TS, even though it warns that it doesn't work on mega. + if(currentStatus.fanDuty == 0) + { + //Make sure fan has 0% duty) + FAN_OFF(); + currentStatus.fanOn = false; + } + else if (currentStatus.fanDuty > 0) + { + //Make sure fan has 100% duty + FAN_ON(); + currentStatus.fanOn = true; + } + #endif + } } void initialiseAuxPWM() @@ -714,3 +786,23 @@ void boostDisable() } } } + +#if defined(PWM_FAN_AVAILABLE) +//The interrupt to control the FAN PWM. Mega2560 doesn't have enough timers, so this is only for the ARM chip ones + void fanInterrupt() +{ + if (fan_pwm_state == true) + { + FAN_OFF(); + FAN_TIMER_COMPARE = FAN_TIMER_COUNTER + (fan_pwm_max_count - fan_pwm_cur_value); + fan_pwm_state = false; + } + else + { + FAN_ON(); + FAN_TIMER_COMPARE = FAN_TIMER_COUNTER + fan_pwm_value; + fan_pwm_cur_value = fan_pwm_value; + fan_pwm_state = true; + } +} +#endif \ No newline at end of file diff --git a/speeduino/board_stm32_generic.h b/speeduino/board_stm32_generic.h index 88bb03bf..4281f4c2 100644 --- a/speeduino/board_stm32_generic.h +++ b/speeduino/board_stm32_generic.h @@ -71,21 +71,21 @@ #ifndef PB11 //Hack for F4 BlackPills #define PB11 PB10 #endif - +#define PWM_FAN_AVAILABLE /* *********************************************************************************************************** * Schedules * Timers Table for STM32F1 * TIMER1 TIMER2 TIMER3 TIMER4 -* 1 - 1 - INJ1 1 - IGN1 1 - oneMSInterval +* 1 - FAN 1 - INJ1 1 - IGN1 1 - oneMSInterval * 2 - BOOST 2 - INJ2 2 - IGN2 2 - * 3 - VVT 3 - INJ3 3 - IGN3 3 - * 4 - IDLE 4 - INJ4 4 - IGN4 4 - * * Timers Table for STM32F4 -* TIMER1 TIMER2 TIMER3 TIMER4 TIMER5 TIMER8 -* 1 - 1 - INJ1 1 - IGN1 1 - IGN5 1 - INJ5 1 - oneMSInterval +* TIMER1 TIMER2 TIMER3 TIMER4 TIMER5 TIMER11 +* 1 - FAN 1 - INJ1 1 - IGN1 1 - IGN5 1 - INJ5 1 - oneMSInterval * 2 - BOOST 2 - INJ2 2 - IGN2 2 - IGN6 2 - INJ6 2 - * 3 - VVT 3 - INJ3 3 - IGN3 3 - IGN7 3 - INJ7 3 - * 4 - IDLE 4 - INJ4 4 - IGN4 4 - IGN8 4 - INJ8 4 - @@ -188,10 +188,15 @@ #define ENABLE_VVT_TIMER() (TIM1)->SR = ~TIM_FLAG_CC3; (TIM1)->DIER |= TIM_DIER_CC3IE #define DISABLE_VVT_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC3IE + #define ENABLE_FAN_TIMER() (TIM1)->SR = ~TIM_FLAG_CC1; (TIM1)->DIER |= TIM_DIER_CC1IE + #define DISABLE_FAN_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC1IE + #define BOOST_TIMER_COMPARE (TIM1)->CCR2 #define BOOST_TIMER_COUNTER (TIM1)->CNT #define VVT_TIMER_COMPARE (TIM1)->CCR3 #define VVT_TIMER_COUNTER (TIM1)->CNT + #define FAN_TIMER_COMPARE (TIM1)->CCR1 + #define FAN_TIMER_COUNTER (TIM1)->CNT /* *********************************************************************************************************** diff --git a/speeduino/board_stm32_generic.ino b/speeduino/board_stm32_generic.ino index 91f89f81..15026409 100644 --- a/speeduino/board_stm32_generic.ino +++ b/speeduino/board_stm32_generic.ino @@ -62,10 +62,13 @@ void initBoard() //2uS resolution Min 8Hz, Max 5KHz boost_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow freqneucies up to 511Hz vvt_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle + fan_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.fanFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle //Need to be initialised last due to instant interrupt + Timer1.setMode(1, TIMER_OUTPUT_COMPARE); Timer1.setMode(2, TIMER_OUTPUT_COMPARE); Timer1.setMode(3, TIMER_OUTPUT_COMPARE); + Timer1.attachInterrupt(1, fanInterrupt); Timer1.attachInterrupt(2, boostInterrupt); Timer1.attachInterrupt(3, vvtInterrupt); @@ -97,7 +100,6 @@ void initBoard() Timer3.setMode(2, TIMER_OUTPUT_COMPARE); Timer3.setMode(3, TIMER_OUTPUT_COMPARE); Timer3.setMode(4, TIMER_OUTPUT_COMPARE); - Timer1.setMode(1, TIMER_OUTPUT_COMPARE); //Attach interupt functions //Injection diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index b031d46f..1373764c 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -69,6 +69,8 @@ extern "C" char* sbrk(int incr); #endif #endif +#define PWM_FAN_AVAILABLE + #ifndef LED_BUILTIN #define LED_BUILTIN PA7 #endif @@ -122,14 +124,14 @@ extern "C" char* sbrk(int incr); * Schedules * Timers Table for STM32F1 * TIMER1 TIMER2 TIMER3 TIMER4 -* 1 - free 1 - INJ1 1 - IGN1 1 - oneMSInterval +* 1 - FAN 1 - INJ1 1 - IGN1 1 - oneMSInterval * 2 - BOOST 2 - INJ2 2 - IGN2 2 - * 3 - VVT 3 - INJ3 3 - IGN3 3 - * 4 - IDLE 4 - INJ4 4 - IGN4 4 - * * Timers Table for STM32F4 * TIMER1 | TIMER2 | TIMER3 | TIMER4 | TIMER5 | TIMER11 -* 1 - free |1 - INJ1 |1 - IGN1 |1 - IGN5 |1 - INJ5 |1 - oneMSInterval +* 1 - FAN |1 - INJ1 |1 - IGN1 |1 - IGN5 |1 - INJ5 |1 - oneMSInterval * 2 - BOOST |2 - INJ2 |2 - IGN2 |2 - IGN6 |2 - INJ6 | * 3 - VVT |3 - INJ3 |3 - IGN3 |3 - IGN7 |3 - INJ7 | * 4 - IDLE |4 - INJ4 |4 - IGN4 |4 - IGN8 |4 - INJ8 | @@ -232,10 +234,15 @@ extern "C" char* sbrk(int incr); #define ENABLE_VVT_TIMER() (TIM1)->SR = ~TIM_FLAG_CC3; (TIM1)->DIER |= TIM_DIER_CC3IE #define DISABLE_VVT_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC3IE +#define ENABLE_FAN_TIMER() (TIM1)->SR = ~TIM_FLAG_CC1; (TIM1)->DIER |= TIM_DIER_CC1IE +#define DISABLE_FAN_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC1IE + #define BOOST_TIMER_COMPARE (TIM1)->CCR2 #define BOOST_TIMER_COUNTER (TIM1)->CNT #define VVT_TIMER_COMPARE (TIM1)->CCR3 #define VVT_TIMER_COUNTER (TIM1)->CNT +#define FAN_TIMER_COMPARE (TIM1)->CCR1 +#define FAN_TIMER_COUNTER (TIM1)->CNT /* *********************************************************************************************************** @@ -286,6 +293,7 @@ void fuelSchedule8Interrupt(HardwareTimer*); #endif void idleInterrupt(HardwareTimer*); void vvtInterrupt(HardwareTimer*); +void fanInterrupt(HardwareTimer*); void ignitionSchedule1Interrupt(HardwareTimer*); void ignitionSchedule2Interrupt(HardwareTimer*); void ignitionSchedule3Interrupt(HardwareTimer*); diff --git a/speeduino/board_stm32_official.ino b/speeduino/board_stm32_official.ino index ad8a7eb8..a88fcb0e 100644 --- a/speeduino/board_stm32_official.ino +++ b/speeduino/board_stm32_official.ino @@ -136,17 +136,22 @@ STM32RTC& rtc = STM32RTC::getInstance(); * Auxilliaries */ //2uS resolution Min 8Hz, Max 5KHz + boost_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow freqneucies up to 511Hz vvt_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle + fan_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.fanFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle //Need to be initialised last due to instant interrupt #if ( STM32_CORE_VERSION_MAJOR < 2 ) + Timer1.setMode(1, TIMER_OUTPUT_COMPARE); Timer1.setMode(2, TIMER_OUTPUT_COMPARE); Timer1.setMode(3, TIMER_OUTPUT_COMPARE); #else //2.0 forward + Timer1.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE); Timer1.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE); Timer1.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE); #endif + Timer1.attachInterrupt(1, fanInterrupt); Timer1.attachInterrupt(2, boostInterrupt); Timer1.attachInterrupt(3, vvtInterrupt); @@ -172,7 +177,6 @@ STM32RTC& rtc = STM32RTC::getInstance(); Timer3.setMode(2, TIMER_OUTPUT_COMPARE); Timer3.setMode(3, TIMER_OUTPUT_COMPARE); Timer3.setMode(4, TIMER_OUTPUT_COMPARE); - Timer1.setMode(1, TIMER_OUTPUT_COMPARE); #else //2.0 forward Timer2.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE); Timer2.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE); @@ -183,7 +187,6 @@ STM32RTC& rtc = STM32RTC::getInstance(); Timer3.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE); Timer3.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE); Timer3.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE); - Timer1.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE); #endif //Attach interrupt functions //Injection @@ -363,6 +366,7 @@ STM32RTC& rtc = STM32RTC::getInstance(); #endif void idleInterrupt(HardwareTimer*){idleInterrupt();} void vvtInterrupt(HardwareTimer*){vvtInterrupt();} + void fanInterrupt(HardwareTimer*){fanInterrupt();} void ignitionSchedule1Interrupt(HardwareTimer*){ignitionSchedule1Interrupt();} void ignitionSchedule2Interrupt(HardwareTimer*){ignitionSchedule2Interrupt();} void ignitionSchedule3Interrupt(HardwareTimer*){ignitionSchedule3Interrupt();} diff --git a/speeduino/board_teensy35.h b/speeduino/board_teensy35.h index a9befdc0..c3bb6776 100644 --- a/speeduino/board_teensy35.h +++ b/speeduino/board_teensy35.h @@ -31,6 +31,7 @@ #define SD_CONFIG SdioConfig(FIFO_SDIO) //Set Teensy to use SDIO in FIFO mode. This is the fastest SD mode on Teensy as it offloads most of the writes #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() + #define PWM_FAN_AVAILABLE #define pinIsReserved(pin) ( ((pin) == 0) || ((pin) == 1) || ((pin) == 3) || ((pin) == 4) ) //Forbiden pins like USB /* @@ -122,14 +123,20 @@ #define ENABLE_VVT_TIMER() FTM1_C1SC |= FTM_CSC_CHIE #define DISABLE_VVT_TIMER() FTM1_C1SC &= ~FTM_CSC_CHIE + + #define ENABLE_FAN_TIMER() FTM2_C1SC |= FTM_CSC_CHIE + #define DISABLE_FAN_TIMER() FTM2_C1SC &= ~FTM_CSC_CHIE #define BOOST_TIMER_COMPARE FTM1_C0V #define BOOST_TIMER_COUNTER FTM1_CNT #define VVT_TIMER_COMPARE FTM1_C1V #define VVT_TIMER_COUNTER FTM1_CNT + #define FAN_TIMER_COMPARE FTM2_C1V + #define FAN_TIMER_COUNTER FTM2_CNT void boostInterrupt(); void vvtInterrupt(); + void fanInterrupt(); /* *********************************************************************************************************** diff --git a/speeduino/board_teensy35.ino b/speeduino/board_teensy35.ino index 0357e15f..1d6aa11d 100644 --- a/speeduino/board_teensy35.ino +++ b/speeduino/board_teensy35.ino @@ -148,11 +148,18 @@ void initBoard() //Enable channel compare interrupt (This is currently disabled as not in use) //FTM1_C1SC |= FTM_CSC_CHIE; + FTM2_C1SC &= ~FTM_CSC_MSB; //According to Pg 965 of the K64 datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it + FTM2_C1SC |= FTM_CSC_MSA; //Enable Compare mode + //Enable channel compare interrupt (This is currently disabled as not in use) + //FTM1_C2SC |= FTM_CSC_CHIE; + //Enable IRQ Interrupt NVIC_ENABLE_IRQ(IRQ_FTM1); boost_pwm_max_count = 1000000L / (32 * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz vvt_pwm_max_count = 1000000L / (32 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz + fan_pwm_max_count = 1000000L / (32 * configPage6.fanFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz + } @@ -370,10 +377,10 @@ void ftm2_isr(void) //FTM2 only has 2 compare channels //Use separate variables for each test to ensure conversion to bool bool interrupt1 = (FTM2_C0SC & FTM_CSC_CHF); - bool interrupt2 = (FTM2_C1SC & FTM_CSC_CHF); //Not currently used + bool interrupt2 = (FTM2_C1SC & FTM_CSC_CHF); //For PWM Fan if(interrupt1) { FTM2_C0SC &= ~FTM_CSC_CHF; idleInterrupt(); } - else if(interrupt2) { FTM2_C1SC &= ~FTM_CSC_CHF; } //Add a callback function here if this is ever used + else if(interrupt2) { FTM2_C1SC &= ~FTM_CSC_CHF; fanInterrupt(); } //For PWM Fan } uint16_t freeRam() diff --git a/speeduino/board_teensy41.h b/speeduino/board_teensy41.h index dd85354e..28d3f35e 100644 --- a/speeduino/board_teensy41.h +++ b/speeduino/board_teensy41.h @@ -25,6 +25,7 @@ #define SD_CONFIG SdioConfig(FIFO_SDIO) //Set Teensy to use SDIO in FIFO mode. This is the fastest SD mode on Teensy as it offloads most of the writes #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() + #define PWM_FAN_AVAILABLE #define pinIsReserved(pin) ( ((pin) == 0) ) //Forbiden pins like USB /* @@ -132,10 +133,16 @@ #define ENABLE_VVT_TIMER() TMR3_CSCTRL0 |= TMR_CSCTRL_TCF2EN #define DISABLE_VVT_TIMER() TMR3_CSCTRL0 &= ~TMR_CSCTRL_TCF2EN + #define ENABLE_FAN_TIMER() TMR3_CSCTRL1 |= TMR_CSCTRL_TCF2EN + #define DISABLE_FAN_TIMER() TMR3_CSCTRL1 &= ~TMR_CSCTRL_TCF2EN + #define BOOST_TIMER_COMPARE PIT_LDVAL1 #define BOOST_TIMER_COUNTER 0 #define VVT_TIMER_COMPARE PIT_LDVAL2 #define VVT_TIMER_COUNTER 0 + //these probaply need to be PIT_LDVAL something??? + #define FAN_TIMER_COMPARE TMR3_COMP22 + #define FAN_TIMER_COUNTER TMR3_CNTR1 void boostInterrupt(); void vvtInterrupt(); diff --git a/speeduino/board_teensy41.ino b/speeduino/board_teensy41.ino index a7e9d4a3..22a4f083 100644 --- a/speeduino/board_teensy41.ino +++ b/speeduino/board_teensy41.ino @@ -63,6 +63,7 @@ void initBoard() //2uS resolution Min 8Hz, Max 5KHz boost_pwm_max_count = 1000000L / (2 * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow freqneucies up to 511Hz vvt_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle + fan_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle //TODO: Configure timers here diff --git a/speeduino/cancomms.h b/speeduino/cancomms.h index c7ba192a..090ba0bc 100644 --- a/speeduino/cancomms.h +++ b/speeduino/cancomms.h @@ -1,7 +1,7 @@ #ifndef CANCOMMS_H #define CANCOMMS_H -#define NEW_CAN_PACKET_SIZE 119 +#define NEW_CAN_PACKET_SIZE 122 #define CAN_PACKET_SIZE 75 #if ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ) diff --git a/speeduino/cancomms.ino b/speeduino/cancomms.ino index 4c24bdc9..50f495ef 100644 --- a/speeduino/cancomms.ino +++ b/speeduino/cancomms.ino @@ -340,6 +340,9 @@ void sendcanValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portTy fullStatus[116] = currentStatus.advance2; //advance 2 fullStatus[117] = currentStatus.nitrous_status; fullStatus[118] = currentStatus.TS_SD_Status; //SD card status + fullStatus[119] = lowByte(currentStatus.EMAP); //2 bytes for EMAP + fullStatus[120] = highByte(currentStatus.EMAP); + fullStatus[121] = currentStatus.fanDuty; for(byte x=0; x= 1) { fanControl(); // Fucntion to turn the cooling fan on/off } diff --git a/speeduino/updates.ino b/speeduino/updates.ino index 22af01f9..44e782ba 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -14,7 +14,7 @@ void doUpdates() { - #define CURRENT_DATA_VERSION 18 + #define CURRENT_DATA_VERSION 19 //Only the latest updat for small flash devices must be retained #ifndef SMALL_FLASH_MODE @@ -518,6 +518,14 @@ void doUpdates() storeEEPROMVersion(18); } + if(readEEPROMVersion() == 18) + { + configPage2.fanEnable = configPage6.fanUnused; // PWM Fan mode added, but take the previous setting of Fan in use. + + writeAllConfig(); + storeEEPROMVersion(19); + } + //Final check is always for 255 and 0 (Brand new arduino) if( (readEEPROMVersion() == 0) || (readEEPROMVersion() == 255) ) {