2 #include "libs/Module.h"
3 #include "libs/Kernel.h"
5 #include "TemperatureControl.h"
7 TemperatureControl::TemperatureControl(){
11 void TemperatureControl::on_module_loaded(){
13 // We start now desiring any temp
14 this->desired_adc_value
= UNDEFINED
;
17 this->on_config_reload(this);
19 this->acceleration_factor
= 10;
21 // Setup pins and timer
22 this->thermistor_pin
= new AnalogIn(p20
);
23 this->kernel
->slow_ticker
->attach( this, &TemperatureControl::thermistor_read_tick
);
24 this->heater_pwm
= new PwmOut(p22
);
25 this->heater_pwm
->write(0);
28 // Register for events
29 this->register_for_event(ON_GCODE_EXECUTE
);
34 // Get configuration from the config file
35 void TemperatureControl::on_config_reload(void* argument
){
37 this->readings_per_second
= this->kernel
->config
->value(readings_per_second_ckeckusm
)->by_default(5 )->as_number();
39 // Values are here : http://reprap.org/wiki/Thermistor
40 // TODO: WARNING : THIS WILL CHANGE and backward compatibility will be broken for config files that use this
41 this->r0
= this->kernel
->config
->value(temperature_control_r0_ckeckusm
)->by_default(100000)->as_number(); // Stated resistance eg. 100K
42 this->t0
= this->kernel
->config
->value(temperature_control_t0_ckeckusm
)->by_default(25 )->as_number() + 273.15; // Temperature at stated resistance, eg. 25C
43 this->beta
= this->kernel
->config
->value(temperature_control_beta_ckeckusm
)->by_default(4066 )->as_number(); // Thermistor beta rating. See http://reprap.org/bin/view/Main/MeasuringThermistorBeta
44 this->vadc
= this->kernel
->config
->value(temperature_control_vadc_ckeckusm
)->by_default(3.3 )->as_number(); // ADC Reference
45 this->vcc
= this->kernel
->config
->value(temperature_control_vcc_ckeckusm
)->by_default(3.3 )->as_number(); // Supply voltage to potential divider
46 this->r1
= this->kernel
->config
->value(temperature_control_r1_ckeckusm
)->by_default(0 )->as_number();
47 this->r2
= this->kernel
->config
->value(temperature_control_r2_ckeckusm
)->by_default(4700 )->as_number();
49 this->k
= this->r0
* exp( -this->beta
/ this->t0
);
52 this->vs
= r1
* this->vcc
/ ( r1
+ r2
);
53 this->rs
= r1
* r2
/ ( r1
+ r2
);
61 void TemperatureControl::on_gcode_execute(void* argument
){
62 Gcode
* gcode
= static_cast<Gcode
*>(argument
);
65 if( gcode
->has_letter('M') && gcode
->get_value('M') == 104 && gcode
->has_letter('S') ){
66 this->set_desired_temperature(gcode
->get_value('S'));
70 if( gcode
->has_letter('M') && gcode
->get_value('M') == 105 ){
71 this->kernel
->serial
->printf("get temperature: %f \r\n", this->get_temperature() );
75 void TemperatureControl::set_desired_temperature(double desired_temperature
){
76 this->desired_adc_value
= this->temperature_to_adc_value(desired_temperature
);
77 this->tail_adc_value
= this->temperature_to_adc_value(desired_temperature
-20);
78 this->head_adc_value
= this->temperature_to_adc_value(desired_temperature
+5);
81 double TemperatureControl::get_temperature(){
82 double temp
= this->new_thermistor_reading() ;
83 return this->adc_value_to_temperature( this->new_thermistor_reading() );
86 double TemperatureControl::adc_value_to_temperature(double adc_value
){
87 double v
= adc_value
* this->vadc
; // Convert from 0-1 adc value to voltage
88 double r
= this->rs
* v
/ ( this->vs
- v
); // Resistance of thermistor
89 return ( this->beta
/ log( r
/ this->k
)) - 273.15;
92 double TemperatureControl::temperature_to_adc_value(double temperature
){
93 double r
= this->r0
* exp( this->beta
* ( 1 / (temperature
+ 273.15) -1 / this->t0
) ); // Resistance of the thermistor
94 double v
= this->vs
* r
/ ( this->rs
+ r
); // Voltage at the potential divider
95 return v
/ this->vadc
* 1.00000; // The ADC reading
98 void TemperatureControl::thermistor_read_tick(){
100 double reading
= this->new_thermistor_reading();
101 if( this->desired_adc_value
!= UNDEFINED
){
102 double difference
= fabs( reading
- this->desired_adc_value
);
103 double adjustment
= difference
/ acceleration_factor
/ this->readings_per_second
;
104 if( reading
> this->tail_adc_value
){
105 this->heater_pwm
->write( 1 );
106 }else if( reading
< this->head_adc_value
){
107 this->pwm_value
-= adjustment
;
108 this->heater_pwm
->write( 0 );
110 if( reading
> this->desired_adc_value
){
111 this->pwm_value
+= adjustment
; // Heat up
113 this->pwm_value
-= adjustment
; // Heat down
115 this->pwm_value
= max( double(0), min( double(1), pwm_value
) );
116 this->heater_pwm
->write( pwm_value
);
122 double TemperatureControl::new_thermistor_reading(){
123 double new_reading
= this->thermistor_pin
->read();
125 if( this->queue
.size() < 15 ){
126 this->queue
.push_back( new_reading
);
127 //this->kernel->serial->printf("first\r\n");
130 double current_temp
= this->average_adc_reading();
131 double error
= fabs(new_reading
- current_temp
);
133 this->error_count
= 0;
135 this->queue
.pop_front(test
);
136 this->queue
.push_back( new_reading
);
139 if( this->error_count
> 4 ){
141 this->queue
.pop_front(test
);
149 double TemperatureControl::average_adc_reading(){
152 int reading_index
= this->queue
.head
;
153 while( reading_index
!= this->queue
.tail
){
155 total
+= this->queue
.buffer
[reading_index
];
156 reading_index
= this->queue
.next_block_index( reading_index
);