Properly handling when PWM frequency is slower than 1khz
[clinton/Smoothieware.git] / src / modules / tools / laser / Laser.cpp
index ee5c978..8ee4d95 100644 (file)
@@ -44,6 +44,7 @@ Laser::Laser()
     laser_on = false;
     scale= 1;
     manual_fire= false;
+    fire_duration = 0;
 }
 
 void Laser::on_module_loaded()
@@ -95,7 +96,7 @@ 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
@@ -112,7 +113,8 @@ void Laser::on_module_loaded()
     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);
 }
 
@@ -134,19 +136,38 @@ void Laser::on_console_line_received( void *argument )
     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;
@@ -224,7 +245,19 @@ bool Laser::get_laser_power(float& power) const
 // 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)) {
@@ -265,3 +298,9 @@ void Laser::on_halt(void *argument)
         manual_fire= false;
     }
 }
+
+float Laser::get_current_power() const
+{
+       float p= pwm_pin->read();
+    return (this->pwm_inverting ? 1 - p : p) * 100;
+}