heater: software pwm with delta sigma algorithm

@triffid points me to the delta sigma algorithm. This is pretty nice
for slow updating routines. Others than normal PWM, this scale better
for slow frequencies.

This algorithm is a mix of
https://www.mikrocontroller.net/topic/293454#3128867
and
https://github.com/Smoothieware/Smoothieware/blob/29e80/src/libs/Pwm.cpp#L55
This commit is contained in:
Nico Tonnhofer 2017-03-14 18:22:56 +01:00
parent fb83d2de57
commit 4abc3aa2f0
27 changed files with 197 additions and 88 deletions

View File

@ -147,6 +147,8 @@ static void clock_10ms(void) {
temp_sensor_tick();
soft_pwm_tick();
ifclock(clock_flag_250ms) {
clock_250ms();
}

View File

@ -226,7 +226,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO14, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -237,9 +238,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO14, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO10, 0, 1, 100)
DEFINE_HEATER(bed, DIO9, 0, 1, 100)
DEFINE_HEATER(fan, DIO8, 0, 1, 100)
DEFINE_HEATER(extruder, DIO10, 0, 2, 100)
DEFINE_HEATER(bed, DIO9, 0, 2, 100)
DEFINE_HEATER(fan, DIO8, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -226,7 +226,8 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO3, 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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -237,7 +238,7 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO3, THERMISTOR_EXTRUDER)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, AIO2, 0, 1, 100)
DEFINE_HEATER(extruder, AIO2, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
//DEFINE_HEATERS_END

View File

@ -221,7 +221,8 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO5, 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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -232,7 +233,7 @@ DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO5, THERMISTOR_EXTRUDER)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO6, 0, 1, 100)
DEFINE_HEATER(extruder, DIO6, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
//DEFINE_HEATERS_END

View File

@ -225,14 +225,13 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, PIO1_0,THERMISTOR_BED)
for this pin, e.g. for a MOSFET with a driver.
Set 'pwm' to ...
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.
>=2 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.
It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM at 100Hz.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
with slow switches, like solid state relays. A too high frequency can

View File

@ -230,9 +230,11 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO2, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
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.
@ -241,8 +243,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO2, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO4, 0, 1, 100)
DEFINE_HEATER(bed, DIO3, 0, 1, 100)
DEFINE_HEATER(extruder, DIO4, 0, 2, 100)
DEFINE_HEATER(bed, DIO3, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -231,7 +231,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -242,8 +243,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO4, 0, 1, 100)
DEFINE_HEATER(bed, DIO3, 0, 1, 100)
DEFINE_HEATER(extruder, DIO4, 0, 2, 100)
DEFINE_HEATER(bed, DIO3, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -230,7 +230,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -241,9 +242,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO13, 0, 1, 100)
DEFINE_HEATER(bed, DIO12, 0, 1, 100)
DEFINE_HEATER(fan, DIO4, 0, 0, 100)
DEFINE_HEATER(extruder, DIO13, 0, 2, 100)
DEFINE_HEATER(bed, DIO12, 0, 2, 100)
DEFINE_HEATER(fan, DIO4, 0, 1, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -228,7 +228,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO7, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -239,8 +240,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO7, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO11, 0, 1, 100)
DEFINE_HEATER(bed, DIO3, 0, 1, 100)
DEFINE_HEATER(extruder, DIO11, 0, 2, 100)
DEFINE_HEATER(bed, DIO3, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -247,7 +247,8 @@
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict

View File

@ -227,7 +227,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO1, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -238,9 +239,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO1, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO10, 0, 1, 100)
DEFINE_HEATER(bed, DIO8, 0, 1, 100)
DEFINE_HEATER(fan, DIO9, 0, 1, 100)
DEFINE_HEATER(extruder, DIO10, 0, 2, 100)
DEFINE_HEATER(bed, DIO8, 0, 2, 100)
DEFINE_HEATER(fan, DIO9, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -232,7 +232,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO14, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -243,9 +244,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO14, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO10, 0, 1, 100)
DEFINE_HEATER(bed, DIO8, 0, 1, 100)
DEFINE_HEATER(fan, DIO9, 0, 1, 100)
DEFINE_HEATER(extruder, DIO10, 0, 2, 100)
DEFINE_HEATER(bed, DIO8, 0, 2, 100)
DEFINE_HEATER(fan, DIO9, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -230,7 +230,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO11, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -241,9 +242,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO11, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO2, 0, 1, 100)
DEFINE_HEATER(bed, DIO9, 0, 1, 100)
DEFINE_HEATER(fan, DIO8, 0, 1, 100)
DEFINE_HEATER(extruder, DIO2, 0, 2, 100)
DEFINE_HEATER(bed, DIO9, 0, 2, 100)
DEFINE_HEATER(fan, DIO8, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -228,7 +228,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -239,8 +240,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO13, 0, 1, 100)
DEFINE_HEATER(bed, DIO14, 0, 1, 100)
DEFINE_HEATER(extruder, DIO13, 0, 2, 100)
DEFINE_HEATER(bed, DIO14, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -228,7 +228,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -239,8 +240,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO12, 0, 1, 100)
DEFINE_HEATER(bed, DIO13, 0, 1, 100)
DEFINE_HEATER(extruder, DIO12, 0, 2, 100)
DEFINE_HEATER(bed, DIO13, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -228,7 +228,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -239,8 +240,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO3, 0, 1, 100)
DEFINE_HEATER(bed, DIO4, 0, 1, 100)
DEFINE_HEATER(extruder, DIO3, 0, 2, 100)
DEFINE_HEATER(bed, DIO4, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -229,7 +229,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -240,9 +241,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO3, 0, 1, 100)
DEFINE_HEATER(bed, DIO6, 0, 1, 100)
DEFINE_HEATER(fan, DIO5, 0, 1, 100)
DEFINE_HEATER(extruder, DIO3, 0, 2, 100)
DEFINE_HEATER(bed, DIO6, 0, 2, 100)
DEFINE_HEATER(fan, DIO5, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -226,7 +226,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -237,9 +238,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO15, 0, 1, 100)
DEFINE_HEATER(bed, DIO14, 0, 1, 100)
DEFINE_HEATER(fan, DIO16, 0, 0, 100)
DEFINE_HEATER(extruder, DIO15, 0, 2, 100)
DEFINE_HEATER(bed, DIO14, 0, 2, 100)
DEFINE_HEATER(fan, DIO16, 0, 1, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -226,7 +226,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -237,9 +238,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO10, 0, 1, 100)
DEFINE_HEATER(bed, DIO9, 0, 1, 100)
DEFINE_HEATER(fan, DIO8, 0, 0, 100)
DEFINE_HEATER(extruder, DIO10, 0, 2, 100)
DEFINE_HEATER(bed, DIO9, 0, 2, 100)
DEFINE_HEATER(fan, DIO8, 0, 1, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -228,7 +228,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
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.
2 for using PWM on a PWM-able pin. It will force to 1 on none-PWM-able pins.
1 for using software emulated PWM.
0 for using on/off on a PWM-able pin, too.
Using PWM usually gives smoother temperature control but can conflict
@ -239,9 +240,9 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED)
//DEFINE_HEATERS_START
// name pin invert pwm max_pwm
DEFINE_HEATER(extruder, DIO13, 0, 1, 100)
DEFINE_HEATER(bed, DIO12, 0, 1, 100)
DEFINE_HEATER(fan, DIO4, 0, 1, 100)
DEFINE_HEATER(extruder, DIO13, 0, 2, 100)
DEFINE_HEATER(bed, DIO12, 0, 2, 100)
DEFINE_HEATER(fan, DIO4, 0, 2, 100)
#define HEATER_EXTRUDER HEATER_extruder
#define HEATER_BED HEATER_bed

View File

@ -15,12 +15,14 @@
/// \struct heater_definition_t
/// \brief simply holds pinout data- port, pin, pwm channel if used
#define U8_HEATER_PWM uint8_t *
typedef struct {
volatile uint8_t *heater_port; ///< pointer to port. DDR is inferred from this pointer too
uint8_t heater_pin; ///< heater pin, not masked. eg for PB3 enter '3' here, or PB3_PIN or similar
/// Wether the heater pin signal needs to be inverted.
uint8_t invert;
volatile uint8_t *heater_pwm; ///< pointer to 8-bit PWM register, eg OCR0A (8-bit) or ORC3L (low byte, 16-bit)
volatile U8_HEATER_PWM heater_pwm; ///< pointer to 8-bit PWM register, eg OCR0A (8-bit) or ORC3L (low byte, 16-bit)
uint16_t max_value;
} heater_definition_t;
@ -30,8 +32,8 @@ typedef struct {
&(pin ## _WPORT), \
pin ## _PIN, \
invert ? 1 : 0, \
pwm ? (pin ## _PWM) : NULL, \
((max_value * 64 + 12) / 25) \
(pwm >= HARDWARE_PWM) ? ((pin ## _PWM) ? (pin ## _PWM) : (U8_HEATER_PWM)SOFTWARE_PWM) : (U8_HEATER_PWM)pwm, \
((max_value * 64 + 12) / 25), \
},
static const heater_definition_t heaters[NUM_HEATERS] =
{
@ -39,6 +41,14 @@ static const heater_definition_t heaters[NUM_HEATERS] =
};
#undef DEFINE_HEATER_ACTUAL
// We test any heater if we need software-pwm
#define DEFINE_HEATER_ACTUAL(name, pin, invert, pwm, ...) \
| (((pwm >= HARDWARE_PWM) ? ((pin ## _PWM) ? HARDWARE_PWM : SOFTWARE_PWM) : pwm) == SOFTWARE_PWM)
static const uint8_t software_pwm_needed = 0
#include "config_wrapper.h"
;
#undef DEFINE_HEATER_ACTUAL
/// \brief initialise heater subsystem
/// Set directions, initialise PWM timers, read PID factors from eeprom, etc
@ -126,7 +136,7 @@ void heater_init() {
// setup pins
for (i = 0; i < NUM_HEATERS; i++) {
if (heaters[i].heater_pwm) {
if (heaters[i].heater_pwm >= (U8_HEATER_PWM)HARDWARE_PWM) {
*heaters[i].heater_pwm = heaters[i].invert ? 255 : 0;
// this is somewhat ugly too, but switch() won't accept pointers for reasons unknown
switch((uint16_t) heaters[i].heater_pwm) {
@ -216,17 +226,17 @@ void heater_init() {
anything done by this function is overwritten by heater_tick above if the heater has an associated temp sensor
*/
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].heater_pwm >= (U8_HEATER_PWM)HARDWARE_PWM) {
uint8_t pwm_value;
if (heaters[index].heater_pwm) {
value = (uint8_t)((heaters[index].max_value * value) / 256);
// Remember, we scale, and the timer inverts already.
pwm_value = (uint8_t)((heaters[index].max_value * value) / 256);
*(heaters[index].heater_pwm) = heaters[index].invert ?
(255 - value) : value;
(255 - pwm_value) : pwm_value;
if (DEBUG_PID && (debug_flags & DEBUG_PID))
sersendf_P(PSTR("PWM{%u = %u}\n"), index, *heaters[index].heater_pwm);

View File

@ -51,7 +51,7 @@
frequency, so you should bother about PWM_SCALE only of you need frequencies
below 3 Hz.
*/
#define PWM_SCALE 255
#define PWM_SCALE 1020
/** \struct heater_definition_t
@ -59,6 +59,8 @@
pin, PWM channel if used. After inititalisation we can no longer do the
#include "config_wrapper.h" trick.
*/
#define U8_HEATER_PWM uint8_t
typedef struct {
union {
/// Pointer to the match register which changes PWM duty.
@ -67,7 +69,7 @@ typedef struct {
__IO uint32_t* masked_port;
};
uint16_t max_value;
uint8_t uses_pwm;
U8_HEATER_PWM heater_pwm;;
uint8_t invert;
} heater_definition_t;
@ -78,7 +80,7 @@ typedef struct {
&(pin ## _TIMER->MR[pin ## _MATCH]) : \
&(pin ## _PORT->MASKED_ACCESS[MASK(pin ## _PIN)]) }, \
((max_value * 64 + 12) / 25), \
pwm && pin ## _TIMER, \
((pwm >= HARDWARE_PWM) ? ((pin ## _TIMER) ? HARDWARE_PWM : SOFTWARE_PWM) : pwm), \
invert ? 1 : 0 \
},
static const heater_definition_t heaters[NUM_HEATERS] = {
@ -86,6 +88,14 @@ static const heater_definition_t heaters[NUM_HEATERS] = {
};
#undef DEFINE_HEATER_ACTUAL
// We test any heater if we need software-pwm
#define DEFINE_HEATER_ACTUAL(name, pin, invert, pwm, ...) \
| (((pwm >= HARDWARE_PWM) ? ((pin ## _TIMER) ? HARDWARE_PWM : SOFTWARE_PWM) : pwm) == 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 pwm.c in LPC1343CodeBase:
@ -133,7 +143,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 >= HARDWARE_PWM) && pin ## _TIMER) { \
uint32_t freq; \
\
if (pin ## _TIMER == LPC_TMR16B0) { \
@ -187,13 +197,11 @@ 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].heater_pwm == HARDWARE_PWM) {
uint32_t pwm_value;
// Remember, we scale, and the timer inverts already.

View File

@ -74,6 +74,7 @@ EE_factor EEMEM EE_factors[NUM_HEATERS];
heater_runtime_t heaters_runtime[NUM_HEATERS];
soft_pwm_runtime_t soft_pwm_runtime[NUM_HEATERS];
/** Inititalise PID data structures.
@ -249,6 +250,60 @@ void heater_tick(heater_t h, temp_type_t type, uint16_t current_temp, uint16_t t
heater_set(h, pid_output);
}
/** \brief software PWM routine
*/
#define PWM_MAX 255
void heater_soft_pwm(heater_t index) {
if (software_pwm_needed) {
int16_t pwm;
pwm = heaters_runtime[index].heater_output;
// full off? then put it just off
if (pwm == 0) {
do_heater(index, 0);
return;
}
// here we are doing a small trick. normally this is
// sd_accu += pwm - (sd_dir * PWM_MAX)
// here we scale the (sd_dir * PWM_MAX) -part with the max_value.
// so we get a smooth PWM also for downscaled heaters. the "pwm"-value
// is from 0 to 255 in any case, but the sd_accu becomes bigger with
// smaller max_values.
soft_pwm_runtime[index].sd_accu += pwm - soft_pwm_runtime[index].sd_dir;
if (soft_pwm_runtime[index].sd_accu > 0) {
soft_pwm_runtime[index].sd_dir = PWM_MAX * 256 / heaters[index].max_value;
do_heater(index, 255);
}
else {
soft_pwm_runtime[index].sd_dir = 0;
do_heater(index, 0);
}
}
}
/**
Called every 10ms from clock.c. Tick the softPWM procedure when the heater needs it.
*/
void soft_pwm_tick() {
if (software_pwm_needed) {
uint8_t i;
for (i = 0; i < NUM_HEATERS; i++) {
if (heaters[i].heater_pwm == (U8_HEATER_PWM)SOFTWARE_PWM)
heater_soft_pwm(i);
}
}
}
/** \brief set heater value and execute it
*/
void heater_set(heater_t index, uint8_t value) {
heaters_runtime[index].heater_output = value;
do_heater(index, value);
}
/** \brief check whether all heaters are off
*/
uint8_t heaters_all_zero() {

View File

@ -64,6 +64,17 @@ typedef struct {
uint8_t heater_output;
} heater_runtime_t;
typedef struct {
/// sigma delta values for software pwm
int16_t sd_accu;
int16_t sd_dir;
} soft_pwm_runtime_t;
typedef enum {
NO_PWM = 0,
SOFTWARE_PWM = 1,
HARDWARE_PWM = 2
} pwm_type_t;
extern heater_runtime_t heaters_runtime[];
@ -73,6 +84,8 @@ void pid_init(void);
void heater_set(heater_t index, uint8_t value);
void heater_tick(heater_t h, temp_type_t type, uint16_t current_temp, uint16_t target_temp);
void soft_pwm_tick(void);
uint8_t heaters_all_zero(void);
#ifdef EECONFIG

View File

@ -11,6 +11,9 @@ void heater_set(heater_t index, uint8_t value) {
void heater_tick(heater_t h, temp_type_t type, uint16_t current_temp, uint16_t target_temp) {
}
void soft_pwm_tick() {
}
uint8_t heaters_all_zero(void) {
return 1;
}

View File

@ -63,7 +63,7 @@
DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO1, THERMISTOR_EXTRUDER)
DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO2, THERMISTOR_BED)
DEFINE_HEATER(extruder, DIO4, 0, 1, 100)
DEFINE_HEATER(extruder, DIO4, 0, 2, 100)
DEFINE_HEATER(bed, DIO3, 0, 1, 100)
#define HEATER_EXTRUDER HEATER_extruder

View File

@ -551,8 +551,8 @@ DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_EXTRUDER)
// #define HEATER_MAX_ACTIVE
// name pin invert pwm
DEFINE_HEATER(extruder, DIO4, 0, 1, 100)
DEFINE_HEATER(bed, DIO3, 0, 1, 100)
DEFINE_HEATER(extruder, DIO4, 0, 2, 100)
DEFINE_HEATER(bed, DIO3, 0, 2, 100)
/// and now because the c preprocessor isn't as smart as it could be,
/// uncomment the ones you've listed above and comment the rest.