speeduino-personal/speeduino/auxiliaries.ino

182 lines
6.6 KiB
Arduino
Raw Normal View History

/*
Speeduino - Simple engine management for the Arduino Mega 2560 platform
Copyright (C) Josh Stewart
A full copy of the license may be found in the projects root directory
*/
2017-02-14 21:51:01 -08:00
integerPID boostPID(&MAPx100, &boost_pwm_target_value, &boostTargetx100, configPage3.boostKP, configPage3.boostKI, configPage3.boostKD, DIRECT); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
/*
2015-08-20 06:21:27 -07:00
Fan control
*/
void initialiseFan()
{
2017-05-31 01:13:04 -07:00
if( configPage4.fanInv == 1 ) { fanHIGH = LOW; fanLOW = HIGH; }
else { fanHIGH = HIGH; fanLOW = LOW; }
2016-10-26 13:03:42 -07:00
digitalWrite(pinFan, fanLOW); //Initiallise program with the fan in the off state
currentStatus.fanOn = false;
}
void fanControl()
{
2017-05-31 01:13:04 -07:00
if( configPage4.fanEnable == 1 )
2016-10-26 13:03:42 -07:00
{
int onTemp = (int)configPage4.fanSP - CALIBRATION_TEMPERATURE_OFFSET;
int offTemp = onTemp - configPage4.fanHyster;
2017-05-31 01:13:04 -07:00
if ( (!currentStatus.fanOn) && (currentStatus.coolant >= onTemp) ) { digitalWrite(pinFan,fanHIGH); currentStatus.fanOn = true; }
if ( (currentStatus.fanOn) && (currentStatus.coolant <= offTemp) ) { digitalWrite(pinFan, fanLOW); currentStatus.fanOn = false; }
2016-10-26 13:03:42 -07:00
}
}
2015-08-20 06:21:27 -07:00
void initialiseAuxPWM()
{
#if defined(CORE_AVR)
TCCR1B = 0x00; //Disbale Timer1 while we set it up
TCNT1 = 0; //Reset Timer Count
TIFR1 = 0x00; //Timer1 INT Flag Reg: Clear Timer Overflow Flag
TCCR1A = 0x00; //Timer1 Control Reg A: Wave Gen Mode normal (Simply counts up from 0 to 65535 (16-bit int)
TCCR1B = (1 << CS12); //Timer1 Control Reg B: Timer Prescaler set to 256. 1 tick = 16uS. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
#endif
boost_pin_port = portOutputRegister(digitalPinToPort(pinBoost));
boost_pin_mask = digitalPinToBitMask(pinBoost);
2015-09-26 23:41:07 -07:00
vvt_pin_port = portOutputRegister(digitalPinToPort(pinVVT_1));
vvt_pin_mask = digitalPinToBitMask(pinVVT_1);
boost_pwm_max_count = 1000000L / (16 * configPage3.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) 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
2015-09-29 00:21:00 -07:00
vvt_pwm_max_count = 1000000L / (16 * configPage3.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
2017-05-31 01:13:04 -07:00
//TIMSK1 |= (1 << OCIE1A); <---- Not required as compare A is turned on when needed by boost control
ENABLE_VVT_TIMER(); //Turn on the B compare unit (ie turn on the interrupt)
boostPID.SetOutputLimits(percentage(configPage1.boostMinDuty, boost_pwm_max_count) , percentage(configPage1.boostMaxDuty, boost_pwm_max_count));
2017-02-14 21:51:01 -08:00
boostPID.SetTunings(configPage3.boostKP, configPage3.boostKI, configPage3.boostKD);
boostPID.SetMode(AUTOMATIC); //Turn PID on
currentStatus.boostDuty = 0;
boostCounter = 0;
}
2015-08-20 06:21:27 -07:00
void boostControl()
{
2017-05-31 01:13:04 -07:00
if( configPage3.boostEnabled==1 )
2015-09-26 23:41:07 -07:00
{
2017-05-31 01:13:04 -07:00
if(currentStatus.MAP >= 100)
2017-05-12 01:14:14 -07:00
{
2017-05-31 01:13:04 -07:00
MAPx100 = currentStatus.MAP * 100;
boost_cl_target_boost = get3DTableValue(&boostTable, currentStatus.TPS, currentStatus.RPM) * 2; //Boost target table is in kpa and divided by 2
//If flex fuel is enabled, there can be an adder to the boost target based on ethanol content
if( configPage1.flexEnabled == 1 )
{
int16_t boostAdder = (((int16_t)configPage1.flexBoostHigh - (int16_t)configPage1.flexBoostLow) * currentStatus.ethanolPct) / 100;
boostAdder = boostAdder + configPage1.flexBoostLow; //Required in case flexBoostLow is less than 0
boost_cl_target_boost = boost_cl_target_boost + boostAdder;
}
boostTargetx100 = boost_cl_target_boost * 100;
currentStatus.boostTarget = boost_cl_target_boost >> 1; //Boost target is sent as a byte value to TS and so is divided by 2
if(currentStatus.boostTarget > 0)
{
if( (boostCounter & 31) == 1) { boostPID.SetTunings(configPage3.boostKP, configPage3.boostKI, configPage3.boostKD); } //This only needs to be run very infrequently, once every 32 calls to boostControl(). This is approx. once per second
boostPID.Compute();
currentStatus.boostDuty = (unsigned long)(boost_pwm_target_value * 100UL) / boost_pwm_max_count;
ENABLE_BOOST_TIMER(); //Turn on the compare unit (ie turn on the interrupt)
2017-05-31 01:13:04 -07:00
}
else
{
//If boost target is 0, turn everything off
DISABLE_BOOST_TIMER(); //Turn off timer
BOOST_PIN_LOW();
2017-05-31 01:13:04 -07:00
}
}
else
{
//Boost control does nothing if kPa below 100
DISABLE_BOOST_TIMER(); //Turn off timer
BOOST_PIN_LOW(); //Make sure solenoid is off (0% duty)
2017-05-12 01:14:14 -07:00
}
2015-09-26 23:41:07 -07:00
}
else { DISABLE_BOOST_TIMER(); } // Disable timer channel
boostCounter++;
2015-09-26 23:41:07 -07:00
}
void vvtControl()
{
2017-05-31 01:13:04 -07:00
if( configPage3.vvtEnabled == 1 )
2015-09-26 23:41:07 -07:00
{
byte vvtDuty = get3DTableValue(&vvtTable, currentStatus.TPS, currentStatus.RPM);
if(vvtDuty == 0)
{
//Make sure solenoid is off (0% duty)
VVT_PIN_LOW();
DISABLE_VVT_TIMER();
}
else if (vvtDuty >= 100)
{
//Make sure solenoid is on (100% duty)
VVT_PIN_HIGH();
DISABLE_VVT_TIMER();
}
else
{
vvt_pwm_target_value = percentage(vvtDuty, vvt_pwm_max_count);
ENABLE_VVT_TIMER();
}
2015-09-26 23:41:07 -07:00
}
else { DISABLE_VVT_TIMER(); } // Disable timer channel
}
2015-09-26 23:41:07 -07:00
//The interrupt to control the Boost PWM
#if defined(CORE_AVR)
ISR(TIMER1_COMPA_vect)
#elif defined (CORE_TEENSY)
static inline void boostInterrupt() //Most ARM chips can simply call a function
#endif
2015-09-26 23:41:07 -07:00
{
if (boost_pwm_state)
{
BOOST_PIN_LOW(); // Switch pin to low
BOOST_TIMER_COMPARE = BOOST_TIMER_COUNTER + (boost_pwm_max_count - boost_pwm_cur_value);
2015-09-26 23:41:07 -07:00
boost_pwm_state = false;
}
else
{
BOOST_PIN_HIGH(); // Switch pin high
BOOST_TIMER_COMPARE = BOOST_TIMER_COUNTER + boost_pwm_target_value;
2015-09-26 23:41:07 -07:00
boost_pwm_cur_value = boost_pwm_target_value;
boost_pwm_state = true;
}
2015-09-26 23:41:07 -07:00
}
2015-08-20 06:21:27 -07:00
2015-09-26 23:41:07 -07:00
//The interrupt to control the VVT PWM
#if defined(CORE_AVR)
ISR(TIMER1_COMPB_vect)
#elif defined (CORE_TEENSY)
static inline void vvtInterrupt() //Most ARM chips can simply call a function
#endif
2015-09-26 23:41:07 -07:00
{
if (vvt_pwm_state)
{
VVT_PIN_LOW(); // Switch pin to low
VVT_TIMER_COMPARE = VVT_TIMER_COUNTER + (vvt_pwm_max_count - vvt_pwm_cur_value);
2015-09-26 23:41:07 -07:00
vvt_pwm_state = false;
}
else
{
VVT_PIN_HIGH(); // Switch pin high
VVT_TIMER_COMPARE = VVT_TIMER_COUNTER + vvt_pwm_target_value;
2015-09-26 23:41:07 -07:00
vvt_pwm_cur_value = vvt_pwm_target_value;
vvt_pwm_state = true;
}
2015-09-26 23:41:07 -07:00
}
2016-01-12 22:06:55 -08:00
#if defined(CORE_STM32)
//YET TO BE IMPLEMENTED ON STM32
2016-10-06 23:34:27 -07:00
void initialiseAuxPWM() { }
void boostControl() { }
2016-10-06 23:34:27 -07:00
void vvtControl() { }
2016-01-12 22:06:55 -08:00
#endif