laser_on = false;
scale= 1;
manual_fire= false;
+ fire_duration = 0;
}
void Laser::on_module_loaded()
this->pwm_pin->write(this->pwm_inverting ? 1 : 0);
this->laser_maximum_power = THEKERNEL->config->value(laser_module_maximum_power_checksum)->by_default(1.0f)->as_number() ;
- // These config variables are deprecated, they have been replaced with laser_module_default_power and laser_module_minimum_power
+ // These config variables are deprecated, they have been replaced with laser_module_maximum_power and laser_module_minimum_power
this->laser_minimum_power = THEKERNEL->config->value(laser_module_tickle_power_checksum)->by_default(0)->as_number() ;
// Load in our preferred config variables
this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
this->register_for_event(ON_GET_PUBLIC_DATA);
- // no point in updating the power more than the PWM frequency, but no more than 1KHz
+ // no point in updating the power more than the PWM frequency, but not faster than 1KHz
+ ms_per_tick = 1000 / std::min(1000UL, 1000000/period);
THEKERNEL->slow_ticker->attach(std::min(1000UL, 1000000/period), this, &Laser::set_proportional_power);
}
if (cmd == "fire") {
string power = shift_parameter(possible_command);
if(power.empty()) {
- msgp->stream->printf("Usage: fire power%%|off\n");
+ msgp->stream->printf("Usage: fire power%% [durationms]|off|status\n");
return;
}
float p;
+ fire_duration = 0; // By default unlimited
+ if(power == "status") {
+ msgp->stream->printf("laser manual state: %s\n", manual_fire ? "on" : "off");
+ return;
+ }
if(power == "off" || power == "0") {
p= 0;
msgp->stream->printf("turning laser off and returning to auto mode\n");
-
}else{
p= strtof(power.c_str(), NULL);
p= confine(p, 0.0F, 100.0F);
- msgp->stream->printf("WARNING: Firing laser at %1.2f%% power, entering manual mode use fire off to return to auto mode\n", p);
+ string duration = shift_parameter(possible_command);
+ if(!duration.empty()) {
+ fire_duration=atoi(duration.c_str());
+ // Avoid negative values, its just incorrect
+ if (fire_duration < ms_per_tick) {
+ msgp->stream->printf("WARNING: Minimal duration is %d ms, not firing\n", ms_per_tick);
+ return;
+ }
+ // rounding to minimal value
+ if (fire_duration % ms_per_tick != 0) {
+ fire_duration = (fire_duration / ms_per_tick) * ms_per_tick;
+ }
+ msgp->stream->printf("WARNING: Firing laser at %1.2f%% power, for %ld ms, use fire off to stop test fire earlier\n", p, fire_duration);
+ } else {
+ msgp->stream->printf("WARNING: Firing laser at %1.2f%% power, entering manual mode use fire off to return to auto mode\n", p);
+ }
}
p= p/100.0F;
// called every millisecond from timer ISR
uint32_t Laser::set_proportional_power(uint32_t dummy)
{
- if(manual_fire) return 0;
+ if(manual_fire) {
+ // If we have fire duration set
+ if (fire_duration) {
+ // Decrease it each ms
+ fire_duration -= ms_per_tick;
+ // And if it turned 0, disable laser and manual fire mode
+ if (fire_duration <= 0) {
+ set_laser_power(0);
+ manual_fire = false;
+ }
+ }
+ return 0;
+ }
float power;
if(get_laser_power(power)) {
manual_fire= false;
}
}
+
+float Laser::get_current_power() const
+{
+ float p= pwm_pin->read();
+ return (this->pwm_inverting ? 1 - p : p) * 100;
+}