heater: add max_pwm and software pwm also for stm32

This commit is contained in:
Nico Tonnhofer 2017-03-21 14:58:06 +01:00
parent fbe1af4013
commit bcb6964ceb
3 changed files with 61 additions and 25 deletions

View File

@ -193,15 +193,19 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, PB_0, THERMISTOR_EXTRUDER)
* *
\***************************************************************************/
#ifndef DEFINE_HEATER
#define DEFINE_HEATER(...)
#endif
/** \def FORCE_SOFTWARE_PWM
Force software pwm when pwm is sets to 1.
Normally any pwm value >= 1 will set the pin to hardware pwm, if available.
When FORCE_SOFTWARE_PWM is defined, pwm = 1 is always set to software pwm.
*/
// #define FORCE_SOFTWARE_PWM
/** \def HEATER_PIN
Heater pins a user should be able to choose from in configtool. All
commented out.
*/
//#define HEATER_PIN AIO2
//#define HEATER_PIN PA_5
/** \def DEFINE_HEATER
Define your heaters and devices here.
@ -227,14 +231,25 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, PB_0, THERMISTOR_EXTRUDER)
for this pin, e.g. for a MOSFET with a driver.
Set 'pwm' to ...
1 for using PWM on a PWM-able pin and on/off on other pins.
0 for using on/off on a PWM-able pin, too.
frequency in Hertz (Hz) on ARM based controllers to set PWM frequency of
this pin's output. Frequency isn't always accurate, Teacup
will choose the closest possible one. FAST_PWM is ignored
on such controllers. Valid range is 2 to 200'000 Hz.
1 on AVR based controllers for using Pulse Width Modulation (PWM)
on a pin supporting it. PWM frequency can be influenced only
somewhat and only globally with FAST_PWM.
0 for using a PWM-able pin in on/off mode.
Using PWM usually gives smoother temperature control but can conflict
with slow switches, like solid state relays. PWM frequency can be
influenced globally with FAST_PWM, see below.
with slow switches, like solid state relays. A too high frequency can
overheat MOSFETs; a too low frequency can make your heater to emit audible
noise; so choose wisely.
Pins which don't allow PWM are operated in software pwm mode.
*/
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, PA_5, 0, 10000, 100)

View File

@ -247,7 +247,7 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, PIO1_0,THERMISTOR_BED)
overheat MOSFETs; a too low frequency can make your heater to emit audible
noise; so choose wisely.
Pins which don't allow PWM are always operated in on/off mode.
Pins which don't allow PWM are operated in software pwm mode.
*/
//DEFINE_HEATERS_START

View File

@ -48,7 +48,7 @@
frequency, so you should bother about PWM_SCALE only of you need frequencies
below 6 Hz.
*/
#define PWM_SCALE 255
#define PWM_SCALE 1020
// some helper macros
#define _EXPANDER(pre, val, post) pre ## val ## post
@ -68,23 +68,44 @@ typedef struct {
__IO uint32_t* bsrr;
};
uint16_t masked_pin;
uint8_t uses_pwm;
uint16_t max_value; ///< max value for the heater, for PWM in percent * 256
pwm_type_t pwm_type; ///< saves the pwm-type: NO_PWM, SOFTWARE_PWM, HARDWARE_PWM
uint8_t invert; ///< Wether the heater pin signal needs to be inverted.
} heater_definition_t;
// When pwm >= 2 it's hardware pwm, if the pin has hardware pwm.
// When pwm == 1 it's software pwm.
// pwm == 0 is no pwm at all.
// Use this macro only in DEFINE_HEATER_ACTUAL-macros.
#define PWM_TYPE(pwm, pin) (((pwm) >= HARDWARE_PWM_START) ? ((pin ## _TIMER) ? HARDWARE_PWM : SOFTWARE_PWM) : (pwm))
#undef DEFINE_HEATER_ACTUAL
#define DEFINE_HEATER_ACTUAL(name, pin, invert, pwm, ...) \
{ \
{ pwm && pin ## _TIMER ? \
&(pin ## _TIMER-> EXPANDER(CCR, pin ## _CHANNEL,)) : \
&(pin ## _PORT->BSRR) }, \
MASK(pin ## _PIN), \
pwm && pin ## _TIMER \
#define DEFINE_HEATER_ACTUAL(name, pin, invert, pwm, max_value) \
{ \
{ (PWM_TYPE(pwm, pin) == HARDWARE_PWM) ? \
&(pin ## _TIMER-> EXPANDER(CCR, pin ## _CHANNEL,)) : \
&(pin ## _PORT->BSRR) }, \
MASK(pin ## _PIN), \
(PWM_TYPE(pwm, pin) != SOFTWARE_PWM) ? \
((max_value * 64 + 12) / 25) : \
(uint16_t)(255UL * 100 / max_value), \
PWM_TYPE(pwm, pin), \
invert ? 1 : 0 \
},
static const heater_definition_t heaters[NUM_HEATERS] = {
#include "config_wrapper.h"
};
#undef DEFINE_HEATER_ACTUAL
// We test any heater if we need software-pwm
#define DEFINE_HEATER_ACTUAL(name, pin, invert, pwm, ...) \
| (PWM_TYPE(pwm, pin) == SOFTWARE_PWM)
static const uint8_t software_pwm_needed = 0
#include "config_wrapper.h"
;
#undef DEFINE_HEATER_ACTUAL
/** Initialise heater subsystem.
Initialise PWM timers, etc. Inspired by heater-arm_lpc11xx.c (pwm.c in LPC1343CodeBase):
@ -156,7 +177,7 @@ void heater_init() {
// Auto-generate pin setup.
#undef DEFINE_HEATER_ACTUAL
#define DEFINE_HEATER_ACTUAL(name, pin, invert, pwm, ...) \
if (pwm && pin ## _TIMER) { \
if (PWM_TYPE(pwm, pin) == HARDWARE_PWM) { \
uint32_t freq; \
uint8_t macro_mask; \
if (pin ## _TIMER == TIM1) { \
@ -223,22 +244,22 @@ void heater_init() {
heater, every few milliseconds by its PID handler. Using M106 on an output
with a sensor changes its setting only for a short moment.
*/
void heater_set(heater_t index, uint8_t value) {
void do_heater(heater_t index, uint8_t value) {
if (index < NUM_HEATERS) {
heaters_runtime[index].heater_output = value;
if (heaters[index].uses_pwm) {
if (heaters[index].pwm_type == HARDWARE_PWM) {
// Remember, we scale, and duty cycle is inverted.
*heaters[index].ccr = (uint32_t)value * (PWM_SCALE / 255);
*heaters[index].ccr = (uint32_t)((heaters[index].max_value * value) * (PWM_SCALE / 255) / 256);
if (DEBUG_PID && (debug_flags & DEBUG_PID))
sersendf_P(PSTR("PWM %su = %lu\n"), index, *heaters[index].ccr);
}
else {
*(heaters[index].bsrr) =
heaters[index].masked_pin << ((value >= HEATER_THRESHOLD) ? 0 : 16);
heaters[index].masked_pin <<
((value >= HEATER_THRESHOLD && ! heaters[index].invert) ?
0 : 16);
}
if (value)
power_on();