Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
TemperatureControl.cpp
00001 /* 00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). 00003 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 00004 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 00006 */ 00007 00008 // TODO : THIS FILE IS LAME, MUST BE MADE MUCH BETTER 00009 00010 #include "libs/Module.h" 00011 #include "libs/Kernel.h" 00012 #include <math.h> 00013 #include "TemperatureControl.h" 00014 #include "libs/Pin.h" 00015 00016 TemperatureControl::TemperatureControl(){} 00017 00018 TemperatureControl::TemperatureControl(uint16_t name){ 00019 this->name_checksum = name; 00020 this->error_count = 0; 00021 } 00022 00023 void TemperatureControl::on_module_loaded(){ 00024 00025 // We start not desiring any temp 00026 this->desired_adc_value = UNDEFINED; 00027 00028 // Settings 00029 this->on_config_reload(this); 00030 00031 this->acceleration_factor = 10; 00032 00033 this->kernel->slow_ticker->attach( 20, this, &TemperatureControl::thermistor_read_tick ); 00034 00035 // Register for events 00036 this->register_for_event(ON_GCODE_EXECUTE); 00037 this->register_for_event(ON_MAIN_LOOP); 00038 00039 } 00040 00041 void TemperatureControl::on_main_loop(void* argument){ } 00042 00043 // Get configuration from the config file 00044 void TemperatureControl::on_config_reload(void* argument){ 00045 00046 this->readings_per_second = this->kernel->config->value(temperature_control_checksum, this->name_checksum, readings_per_second_checksum)->by_default(5)->as_number(); 00047 00048 // Values are here : http://reprap.org/wiki/Thermistor 00049 this->r0 = 100000; 00050 this->t0 = 25; 00051 this->beta = 4066; 00052 this->vadc = 3.3; 00053 this->vcc = 3.3; 00054 this->r1 = 0; 00055 this->r2 = 4700; 00056 00057 // Preset values for various common types of thermistors 00058 ConfigValue* thermistor = this->kernel->config->value(temperature_control_checksum, this->name_checksum, thermistor_checksum); 00059 if( thermistor->value.compare("EPCOS100K" ) == 0 ){ // Default 00060 }else if( thermistor->value.compare("RRRF100K" ) == 0 ){ this->beta = 3960; 00061 }else if( thermistor->value.compare("RRRF10K" ) == 0 ){ this->beta = 3964; this->r0 = 10000; this->r1 = 680; this->r2 = 1600; 00062 }else if( thermistor->value.compare("Honeywell100K") == 0 ){ this->beta = 3974; 00063 }else if( thermistor->value.compare("Semitec" ) == 0 ){ this->beta = 4267; } 00064 00065 // Preset values are overriden by specified values 00066 this->r0 = this->kernel->config->value(temperature_control_checksum, this->name_checksum, r0_checksum )->by_default(100000)->as_number(); // Stated resistance eg. 100K 00067 this->t0 = this->kernel->config->value(temperature_control_checksum, this->name_checksum, t0_checksum )->by_default(25 )->as_number() + 273.15; // Temperature at stated resistance, eg. 25C 00068 this->beta = this->kernel->config->value(temperature_control_checksum, this->name_checksum, beta_checksum)->by_default(4066 )->as_number(); // Thermistor beta rating. See http://reprap.org/bin/view/Main/MeasuringThermistorBeta 00069 this->vadc = this->kernel->config->value(temperature_control_checksum, this->name_checksum, vadc_checksum)->by_default(3.3 )->as_number(); // ADC Reference 00070 this->vcc = this->kernel->config->value(temperature_control_checksum, this->name_checksum, vcc_checksum )->by_default(3.3 )->as_number(); // Supply voltage to potential divider 00071 this->r1 = this->kernel->config->value(temperature_control_checksum, this->name_checksum, r1_checksum )->by_default(0 )->as_number(); 00072 this->r2 = this->kernel->config->value(temperature_control_checksum, this->name_checksum, r2_checksum )->by_default(4700 )->as_number(); 00073 00074 // Thermistor math 00075 this->k = this->r0 * exp( -this->beta / this->t0 ); 00076 if( r1 > 0 ){ this->vs = r1 * this->vcc / ( r1 + r2 ); this->rs = r1 * r2 / ( r1 + r2 ); }else{ this->vs = this->vcc; this->rs = r2; } 00077 00078 // Thermistor pin for ADC readings 00079 this->thermistor_pin = this->kernel->config->value(temperature_control_checksum, this->name_checksum, thermistor_pin_checksum )->required()->as_pin(); 00080 this->kernel->adc->enable_pin(this->thermistor_pin); 00081 00082 // Heater pin 00083 this->heater_pin = this->kernel->config->value(temperature_control_checksum, this->name_checksum, heater_pin_checksum)->required()->as_pin()->as_output(); 00084 this->heater_pin->set(0); 00085 00086 } 00087 00088 void TemperatureControl::on_gcode_execute(void* argument){ 00089 Gcode* gcode = static_cast<Gcode*>(argument); 00090 00091 // Set temperature without waiting 00092 if( gcode->has_letter('M') && gcode->get_value('M') == 104 && gcode->has_letter('S') ){ 00093 this->set_desired_temperature(gcode->get_value('S')); 00094 } 00095 00096 // Set temperature and wait 00097 if( gcode->has_letter('M') && gcode->get_value('M') == 109 && gcode->has_letter('S') ){ 00098 this->set_desired_temperature(gcode->get_value('S')); 00099 00100 // Pause 00101 this->kernel->pauser->take(); 00102 this->waiting = true; 00103 00104 } 00105 00106 // Get temperature 00107 if( gcode->has_letter('M') && gcode->get_value('M') == 105 ){ 00108 gcode->stream->printf("get temperature: %f current:%f target:%f \r\n", this->get_temperature(), this->new_thermistor_reading(), this->desired_adc_value ); 00109 } 00110 } 00111 00112 void TemperatureControl::set_desired_temperature(double desired_temperature){ 00113 this->desired_adc_value = this->temperature_to_adc_value(desired_temperature); 00114 } 00115 00116 double TemperatureControl::get_temperature(){ 00117 double temp = this->new_thermistor_reading() ; 00118 return this->adc_value_to_temperature( this->new_thermistor_reading() ); 00119 } 00120 00121 double TemperatureControl::adc_value_to_temperature(double adc_value){ 00122 double v = adc_value * this->vadc; // Convert from 0-1 adc value to voltage 00123 double r = this->rs * v / ( this->vs - v ); // Resistance of thermistor 00124 return ( this->beta / log( r / this->k )) - 273.15; 00125 } 00126 00127 double TemperatureControl::temperature_to_adc_value(double temperature){ 00128 double r = this->r0 * exp( this->beta * ( 1 / (temperature + 273.15) -1 / this->t0 ) ); // Resistance of the thermistor 00129 double v = this->vs * r / ( this->rs + r ); // Voltage at the potential divider 00130 return v / this->vadc * 1.00000; // The ADC reading 00131 } 00132 00133 uint32_t TemperatureControl::thermistor_read_tick(uint32_t dummy){ 00134 if( this->desired_adc_value != UNDEFINED ){ 00135 if( this->new_thermistor_reading() > this->desired_adc_value ){ 00136 this->heater_pin->set(1); 00137 }else{ 00138 this->heater_pin->set(0); 00139 if( this->waiting ){ 00140 this->kernel->pauser->release(); 00141 this->waiting = false; 00142 } 00143 } 00144 } 00145 } 00146 00147 double TemperatureControl::new_thermistor_reading(){ 00148 00149 double new_reading = double( double(this->kernel->adc->read(this->thermistor_pin) / double(1<<12) ) ); 00150 00151 if( this->queue.size() < 15 ){ 00152 this->queue.push_back( new_reading ); 00153 return new_reading; 00154 }else{ 00155 double current_temp = this->average_adc_reading(); 00156 double error = fabs(new_reading - current_temp); 00157 if( error < 0.1 ){ 00158 this->error_count = 0; 00159 double test; 00160 this->queue.pop_front(test); 00161 this->queue.push_back( new_reading ); 00162 }else{ 00163 this->error_count++; 00164 if( this->error_count > 4 ){ 00165 double test; 00166 this->queue.pop_front(test); 00167 } 00168 } 00169 return current_temp; 00170 } 00171 } 00172 00173 00174 double TemperatureControl::average_adc_reading(){ 00175 double total; 00176 int j=0; 00177 int reading_index = this->queue.head; 00178 while( reading_index != this->queue.tail ){ 00179 j++; 00180 total += this->queue.buffer[reading_index]; 00181 reading_index = this->queue.next_block_index( reading_index ); 00182 } 00183 return total / j; 00184 } 00185 00186 00187
Generated on Tue Jul 12 2022 14:14:42 by
1.7.2