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.
Fork of Smoothie by
Switch.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 #include "libs/Module.h" 00009 #include "libs/Kernel.h" 00010 #include "libs/SerialMessage.h" 00011 #include <math.h> 00012 #include "Switch.h" 00013 #include "libs/Pin.h" 00014 #include "modules/robot/Conveyor.h" 00015 #include "PublicDataRequest.h" 00016 #include "SwitchPublicAccess.h" 00017 00018 00019 #include "MRI_Hooks.h" 00020 00021 #define startup_state_checksum CHECKSUM("startup_state") 00022 #define startup_value_checksum CHECKSUM("startup_value") 00023 #define input_pin_checksum CHECKSUM("input_pin") 00024 #define input_pin_behavior_checksum CHECKSUM("input_pin_behavior") 00025 #define toggle_checksum CHECKSUM("toggle") 00026 #define momentary_checksum CHECKSUM("momentary") 00027 #define input_on_command_checksum CHECKSUM("input_on_command") 00028 #define input_off_command_checksum CHECKSUM("input_off_command") 00029 #define output_pin_checksum CHECKSUM("output_pin") 00030 #define output_on_command_checksum CHECKSUM("output_on_command") 00031 #define output_off_command_checksum CHECKSUM("output_off_command") 00032 00033 Switch::Switch(){} 00034 00035 Switch::Switch(uint16_t name){ 00036 this->name_checksum = name; 00037 //this->dummy_stream = &(StreamOutput::NullStream); 00038 } 00039 00040 void Switch::on_module_loaded(){ 00041 this->input_pin_state = true; 00042 this->switch_state = true; 00043 this->switch_changed = false; 00044 00045 register_for_event(ON_CONFIG_RELOAD); 00046 this->register_for_event(ON_GCODE_RECEIVED); 00047 this->register_for_event(ON_GCODE_EXECUTE); 00048 this->register_for_event(ON_MAIN_LOOP); 00049 this->register_for_event(ON_GET_PUBLIC_DATA); 00050 this->register_for_event(ON_SET_PUBLIC_DATA); 00051 00052 // Settings 00053 this->on_config_reload(this); 00054 00055 // input pin polling 00056 THEKERNEL->slow_ticker->attach( 100, this, &Switch::pinpoll_tick); 00057 00058 // PWM 00059 THEKERNEL->slow_ticker->attach(1000, &output_pin, &Pwm::on_tick); 00060 } 00061 00062 00063 // Get config 00064 void Switch::on_config_reload(void* argument){ 00065 this->input_pin.from_string( THEKERNEL->config->value(switch_checksum, this->name_checksum, input_pin_checksum )->by_default("nc")->as_string())->as_input(); 00066 this->input_pin_behavior = THEKERNEL->config->value(switch_checksum, this->name_checksum, input_pin_behavior_checksum )->by_default(momentary_checksum)->as_number(); 00067 std::string input_on_command = THEKERNEL->config->value(switch_checksum, this->name_checksum, input_on_command_checksum )->by_default("")->as_string(); 00068 std::string input_off_command = THEKERNEL->config->value(switch_checksum, this->name_checksum, input_off_command_checksum )->by_default("")->as_string(); 00069 this->output_pin.from_string(THEKERNEL->config->value(switch_checksum, this->name_checksum, output_pin_checksum )->by_default("nc")->as_string())->as_output(); 00070 this->output_on_command = THEKERNEL->config->value(switch_checksum, this->name_checksum, output_on_command_checksum )->by_default("")->as_string(); 00071 this->output_off_command = THEKERNEL->config->value(switch_checksum, this->name_checksum, output_off_command_checksum )->by_default("")->as_string(); 00072 this->switch_state = THEKERNEL->config->value(switch_checksum, this->name_checksum, startup_state_checksum )->by_default(false)->as_bool(); 00073 this->switch_value = THEKERNEL->config->value(switch_checksum, this->name_checksum, startup_value_checksum )->by_default(this->output_pin.max_pwm())->as_number(); 00074 if(this->switch_state) 00075 this->output_pin.set(this->switch_value); 00076 else 00077 this->output_pin.set(0); 00078 00079 set_low_on_debug(output_pin.port_number, output_pin.pin); 00080 00081 // Set the on/off command codes, Use GCode to do the parsing 00082 input_on_command_letter= 0; 00083 input_off_command_letter= 0; 00084 00085 if(!input_on_command.empty()) { 00086 Gcode gc(input_on_command, NULL); 00087 if(gc.has_g){ 00088 input_on_command_letter= 'G'; 00089 input_on_command_code= gc.g; 00090 } else if(gc.has_m) { 00091 input_on_command_letter= 'M'; 00092 input_on_command_code= gc.m; 00093 } 00094 } 00095 if(!input_off_command.empty()) { 00096 Gcode gc(input_off_command, NULL); 00097 if(gc.has_g){ 00098 input_off_command_letter= 'G'; 00099 input_off_command_code= gc.g; 00100 } else if(gc.has_m) { 00101 input_off_command_letter= 'M'; 00102 input_off_command_code= gc.m; 00103 } 00104 } 00105 00106 } 00107 00108 bool Switch::match_input_gcode(const Gcode* gcode) const { 00109 return ((input_on_command_letter == 'M' && gcode->has_m && gcode->m == input_on_command_code) || 00110 (input_on_command_letter == 'G' && gcode->has_g && gcode->g == input_on_command_code)); 00111 } 00112 00113 bool Switch::match_output_gcode(const Gcode* gcode) const { 00114 return ((input_off_command_letter == 'M' && gcode->has_m && gcode->m == input_off_command_code) || 00115 (input_off_command_letter == 'G' && gcode->has_g && gcode->g == input_off_command_code)); 00116 } 00117 00118 void Switch::on_gcode_received(void* argument){ 00119 Gcode* gcode = static_cast<Gcode*>(argument); 00120 // Add the gcode to the queue ourselves if we need it 00121 if (match_input_gcode(gcode) || match_output_gcode(gcode)) { 00122 THEKERNEL->conveyor->append_gcode(gcode); 00123 } 00124 } 00125 00126 // Turn pin on and off 00127 void Switch::on_gcode_execute(void* argument){ 00128 Gcode* gcode = static_cast<Gcode*>(argument); 00129 00130 if(match_input_gcode(gcode)) { 00131 if (gcode->has_letter('S')) 00132 { 00133 int v = gcode->get_value('S') * output_pin.max_pwm() / 256.0; 00134 if (v) { 00135 this->output_pin.pwm(v); 00136 this->switch_value = v; 00137 this->switch_state = true; 00138 } 00139 else { 00140 this->output_pin.set(0); 00141 this->switch_state = false; 00142 } 00143 00144 } else { 00145 // Turn pin on 00146 this->output_pin.pwm(this->switch_value); 00147 this->switch_state = true; 00148 } 00149 00150 } else if(match_output_gcode(gcode)) { 00151 // Turn pin off 00152 this->output_pin.set(0); 00153 this->switch_state = false; 00154 } 00155 } 00156 00157 void Switch::on_get_public_data(void* argument){ 00158 PublicDataRequest* pdr = static_cast<PublicDataRequest*>(argument); 00159 00160 if(!pdr->starts_with(switch_checksum)) return; 00161 00162 if(!pdr->second_element_is(this->name_checksum)) return; // likely fan, but could be anything 00163 00164 // ok this is targeted at us, so send back the requested data 00165 // this must be static as it will be accessed long after we have returned 00166 static struct pad_switch pad; 00167 pad.name= this->name_checksum; 00168 pad.state= this->switch_state; 00169 pad.value= this->switch_value; 00170 00171 pdr->set_data_ptr(&pad); 00172 pdr->set_taken(); 00173 } 00174 00175 void Switch::on_set_public_data(void* argument){ 00176 PublicDataRequest* pdr = static_cast<PublicDataRequest*>(argument); 00177 00178 if(!pdr->starts_with(switch_checksum)) return; 00179 00180 if(!pdr->second_element_is(this->name_checksum)) return; // likely fan, but could be anything 00181 00182 // ok this is targeted at us, so set the value 00183 if(pdr->third_element_is(state_checksum)) { 00184 bool t= *static_cast<bool*>(pdr->get_data_ptr()); 00185 this->switch_state = t; 00186 pdr->set_taken(); 00187 } 00188 else if(pdr->third_element_is(value_checksum)) { 00189 float t= *static_cast<float*>(pdr->get_data_ptr()); 00190 this->switch_value = t; 00191 pdr->set_taken(); 00192 } 00193 } 00194 00195 void Switch::on_main_loop(void* argument){ 00196 if(this->switch_changed){ 00197 if(this->switch_state){ 00198 this->send_gcode( this->output_on_command, &(StreamOutput::NullStream) ); 00199 this->output_pin.pwm(this->switch_value); 00200 }else{ 00201 this->send_gcode( this->output_off_command, &(StreamOutput::NullStream) ); 00202 this->output_pin.set(0); 00203 } 00204 this->switch_changed=false; 00205 } 00206 } 00207 00208 //TODO: Make this use InterruptIn 00209 //Check the state of the button and act accordingly 00210 uint32_t Switch::pinpoll_tick(uint32_t dummy){ 00211 // If pin changed 00212 bool current_state = this->input_pin.get(); 00213 if(this->input_pin_state != current_state){ 00214 this->input_pin_state = current_state; 00215 // If pin high 00216 if( this->input_pin_state ){ 00217 // if switch is a toggle switch 00218 if( this->input_pin_behavior == toggle_checksum ){ 00219 this->flip(); 00220 // else default is momentary 00221 } 00222 else{ 00223 this->flip(); 00224 } 00225 // else if button released 00226 }else{ 00227 // if switch is momentary 00228 if( !this->input_pin_behavior == toggle_checksum ){ 00229 this->flip(); 00230 } 00231 } 00232 } 00233 return 0; 00234 } 00235 00236 void Switch::flip(){ 00237 this->switch_state = !this->switch_state; 00238 this->switch_changed = true; 00239 } 00240 00241 void Switch::send_gcode(std::string msg, StreamOutput* stream) { 00242 struct SerialMessage message; 00243 message.message = msg; 00244 message.stream = stream; 00245 THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message ); 00246 } 00247
Generated on Tue Jul 12 2022 20:09:02 by
1.7.2
