Improved PWM speed sync, version bump
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Fri, 2 Nov 2018 10:32:38 +0000 (03:32 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Fri, 2 Nov 2018 10:32:38 +0000 (03:32 -0700)
12 files changed:
CHANGELOG.md
package-lock.json
package.json
src/avr/src/config.h
src/avr/src/line.c
src/avr/src/main.c
src/avr/src/pwm_spindle.c
src/avr/src/pwm_spindle.h
src/avr/src/spindle.c
src/avr/src/spindle.h
src/avr/src/stepper.c
src/py/bbctrl/__init__.py

index 9ba1168b62ff0b2b6ef787b90a3ffcec84605324..dc977b03519baa4499111e071a7d18017cc6fafd 100644 (file)
@@ -1,7 +1,7 @@
 Buildbotics CNC Controller Firmware Changelog
 ==============================================
 
-## v0.3.29
+## v0.4.0
  - Increased display precision of position and motor config.
  - Added support for 256 microstepping.
  - Smoother operation at 250k step rate by doubling clock as needed.
@@ -24,7 +24,7 @@ Buildbotics CNC Controller Firmware Changelog
  - Major improvements for LASER raster GCodes.
  - Fixed major bug in command queuing.
  - Ignore Program Number O-Codes.
- - Improved planning of colinear line segments.
+ - Improved planning of collinear line segments.
  - Allow PWM output up to 320kHz and no slower than 8Hz.
 
 ## v0.3.28
index 15e29b4523704223e49f11ee906743d3844181b3..c42f3e067af2333ce8d50cc67cba1ba3fadd0647 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "bbctrl",
-  "version": "0.3.29",
+  "version": "0.4.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
index 8eb06eb01e004c23ea947b47a9c481de769c519e..c56b9351d6f2e89782903e5f822f1779522cde44 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "bbctrl",
-  "version": "0.3.29",
+  "version": "0.4.0",
   "homepage": "http://buildbotics.com/",
   "repository": "https://github.com/buildbotics/bbctrl-firmware",
   "license": "GPL-3.0+",
index d8bb92dd2a6b3a0e2576261e5d804ace1b443f73..b96a4d3dfe4e1f5312e895b7dd089ec93300b491 100644 (file)
@@ -191,13 +191,17 @@ enum {
 
 
 // Serial settings
-#define SERIAL_BAUD              USART_BAUD_115200
+#define SERIAL_BAUD              USART_BAUD_230400 // 115200
 #define SERIAL_PORT              USARTC0
 #define SERIAL_DRE_vect          USARTC0_DRE_vect
 #define SERIAL_RXC_vect          USARTC0_RXC_vect
 #define SERIAL_CTS_THRESH        4
 
 
+// Spindle settings
+#define SPEED_QUEUE_SIZE         64
+#define SPEED_OFFSET             6 // ms
+
 // Input
 #define INPUT_BUFFER_LEN         128 // text buffer size (255 max)
 
index 7722a2422bd7e61fe3513d5c8cc7b393b1d15c22..b1f18e675422b36e73e511fb52a5efa121213da8 100644 (file)
@@ -136,7 +136,7 @@ static void _load_sync_speeds(float startT, float endT) {
     if (l.speed.time < 0 || endT < l.speed.time) break;
 
     // Queue speed
-    spindle_queue_speed(round(l.speed.time - startT), l.speed.speed);
+    spindle_set_speed(round(l.speed.time - startT), l.speed.speed);
     l.speed.time = -1; // Mark done
   }
 }
@@ -182,7 +182,6 @@ static stat_t _line_exec() {
       l.lineT += t;
 
     } else {
-      spindle_new_segment();
       exec_set_cb(0);
 
       // Last segment of last section
@@ -334,5 +333,5 @@ unsigned command_sync_speed_size() {return sizeof(speed_t);}
 
 void command_sync_speed_exec(void *data) {
   speed_t s = *(speed_t *)data;
-  spindle_queue_speed(0, s.speed);
+  spindle_set_speed(0, s.speed);
 }
index a6b34709c44a98b4fbf7c88890f6f3fb62d9ed93..f93bcf5898c8877104de2fd511560f8e19ba24c8 100644 (file)
@@ -42,7 +42,6 @@
 #include "analog.h"
 #include "exec.h"
 #include "state.h"
-#include "spindle.h"
 
 #include <avr/wdt.h>
 
@@ -69,7 +68,6 @@ int main() {
   vars_init();                    // configuration variables
   estop_init();                   // emergency stop handler
   command_init();                 // command queue
-  spindle_init();                 // spindle
 
   sei();                          // enable interrupts
 
index a7c36f40cebf36b44bf6c706a2bf103f7877b784..b905610c6809549f964348a6b48c9d899580aa93 100644 (file)
 #include <math.h>
 
 
+typedef struct {
+  uint8_t time;
+  uint16_t period;
+  bool clockwise;
+} update_t;
+
+
+#define RING_BUF_NAME update_q
+#define RING_BUF_TYPE update_t
+#define RING_BUF_INDEX_TYPE volatile uint8_t
+#define RING_BUF_SIZE SPEED_QUEUE_SIZE
+#include "ringbuf.def"
+
+
 typedef struct {
   float freq; // base frequency for PWM driver, in Hz
   float min_duty;
   float max_duty;
   float duty;
   float speed;
+  uint8_t time;
 } pwm_spindle_t;
 
 
@@ -56,12 +71,11 @@ static void _set_dir(bool clockwise) {
 }
 
 
-static void _update_pwm() {
-  float speed = spindle.speed;
+static void _update_clock(uint16_t period) {
+  if (estop_triggered()) period = 0;
 
   // Disable
-  if (!speed || estop_triggered()) {
-    spindle.duty = 0;
+  if (!period) {
     TIMER_PWM.CTRLB = 0; // Disable clock control of pin
     OUTCLR_PIN(SPIN_PWM_PIN);
     _set_enable(false);
@@ -70,23 +84,38 @@ static void _update_pwm() {
   _set_enable(true);
 
   // 100% duty
-  if (speed == 1 && spindle.max_duty == 1) {
-    spindle.duty = 1;
+  if (period == 0xffff) {
     TIMER_PWM.CTRLB = 0; // Disable clock control of pin
     OUTSET_PIN(SPIN_PWM_PIN);
     return;
   }
 
-  // Compute duty cycle
-  spindle.duty =
-    speed * (spindle.max_duty - spindle.min_duty) + spindle.min_duty;
-
   // Configure clock
   TIMER_PWM.CTRLB = TC1_CCAEN_bm | TC_WGMODE_SINGLESLOPE_gc;
-  TIMER_PWM.CCA = TIMER_PWM.PER * spindle.duty;
+  TIMER_PWM.CCA = period;
+}
+
+
+static float _compute_duty(float speed) {
+  if (!speed) return 0; // 0% duty
+  if (speed == 1 && spindle.max_duty == 1) return 1; // 100% duty
+  return speed * (spindle.max_duty - spindle.min_duty) + spindle.min_duty;
 }
 
 
+static uint16_t _compute_period(float speed) {
+  spindle.speed = speed;
+  spindle.duty = _compute_duty(speed);
+
+  if (!spindle.duty) return 0;
+  if (spindle.duty == 1) return 0xffff;
+  return TIMER_PWM.PER * spindle.duty;
+}
+
+
+static void _update_pwm() {_update_clock(_compute_period(spindle.speed));}
+
+
 static void _update_freq() {
   // Set clock period and optimal prescaler value
   float prescale = (F_CPU >> 16) / spindle.freq;
@@ -118,6 +147,8 @@ static void _update_freq() {
 
 
 void pwm_spindle_init() {
+  update_q_init();
+
   // Configure IO
   _set_dir(true);
   _set_enable(false);
@@ -142,16 +173,45 @@ void pwm_spindle_deinit(deinit_cb_t cb) {
 }
 
 
-void pwm_spindle_set(float speed) {
-  if (speed) _set_dir(0 < speed);
-  spindle.speed = fabs(speed);
-  _update_pwm();
+void pwm_spindle_set(uint8_t time, float speed) {
+  if (update_q_full()) update_q_init();
+
+  update_t d = {
+    (uint8_t)(spindle.time + time + SPEED_OFFSET),
+    _compute_period(fabsf(speed)),
+    0 < speed
+  };
+
+  update_q_push(d);
 }
 
 
 float pwm_spindle_get() {return spindle.speed;}
 
 
+void pwm_spindle_update() {
+  bool set = false;
+  uint16_t period;
+  bool clockwise;
+
+  while (!update_q_empty()) {
+    update_t d = update_q_peek();
+    if (spindle.time != d.time) break;
+    update_q_pop();
+    set = true;
+    period = d.period;
+    clockwise = d.clockwise;
+  }
+
+  if (set) {
+    _update_clock(period);
+    if (period) _set_dir(clockwise);
+  }
+
+  spindle.time++;
+}
+
+
 // Var callbacks
 float get_pwm_min_duty() {return spindle.min_duty * 100;}
 
index 1d467a1702d0721cc0af1bf0d44d3e45767a0a49..5ac5e547c6f425109e85c2607c0480adb65163f5 100644 (file)
@@ -32,5 +32,6 @@
 
 void pwm_spindle_init();
 void pwm_spindle_deinit(deinit_cb_t cb);
-void pwm_spindle_set(float speed);
+void pwm_spindle_set(uint8_t time, float speed);
 float pwm_spindle_get();
+void pwm_spindle_update();
index ca733cdf8e0620dd14a55d081c9e1b1aad5b501e..1965cae540ea0452c25a2d2e6627d579ab0e9d08 100644 (file)
 #include <math.h>
 
 
-#define SPEED_QUEUE_SIZE 32
-
-typedef struct {
-  int8_t time;
-  float speed;
-} speed_t;
-
-
-#define RING_BUF_NAME speed_q
-#define RING_BUF_TYPE speed_t
-#define RING_BUF_INDEX_TYPE volatile uint8_t
-#define RING_BUF_SIZE SPEED_QUEUE_SIZE
-#include "ringbuf.def"
-
-
 static struct {
   spindle_type_t type;
   float override;
@@ -58,7 +43,6 @@ static struct {
   float min_rpm;
   float max_rpm;
 
-  int8_t time;
   spindle_type_t next_type;
 
 } spindle = {
@@ -67,16 +51,10 @@ static struct {
 };
 
 
-void spindle_init() {
-  speed_q_init();
-  spindle_new_segment();
-}
-
-
 spindle_type_t spindle_get_type() {return spindle.type;}
 
 
-void _set_speed(float speed) {
+void spindle_set_speed(uint8_t time, float speed) {
   spindle.speed = speed;
 
   speed *= spindle.override;
@@ -90,7 +68,7 @@ void _set_speed(float speed) {
 
   switch (spindle.type) {
   case SPINDLE_TYPE_DISABLED: break;
-  case SPINDLE_TYPE_PWM: pwm_spindle_set(speed); break;
+  case SPINDLE_TYPE_PWM: pwm_spindle_set(time, speed); break;
   case SPINDLE_TYPE_HUANYANG: huanyang_set(speed); break;
   default: vfd_spindle_set(speed); break;
   }
@@ -111,61 +89,18 @@ float _get_speed() {
 }
 
 
-void spindle_stop() {_set_speed(0);}
+void spindle_stop() {spindle_set_speed(0, 0);}
 
 
 bool spindle_is_reversed() {return spindle.reversed;}
 
 
 void spindle_update() {
-  while (!speed_q_empty()) {
-    speed_t s = speed_q_peek();
-    if (s.time == -1 || spindle.time < s.time) break;
-    speed_q_pop();
-    _set_speed(s.speed);
-  }
-
-  spindle.time++;
-}
-
-
-void spindle_next_segment() {
-  while (!speed_q_empty()) {
-    speed_t s = speed_q_next();
-    if (s.time == -1) break;
-    _set_speed(s.speed);
-  }
-
-  spindle.time = 0;
-  spindle_update();
-}
-
-
-void spindle_new_segment() {
-  speed_t s = {-1, 0};
-  if (!speed_q_full()) speed_q_push(s);
-}
-
-
-void spindle_queue_speed(int8_t time, float speed) {
-  if (speed_q_empty()) spindle_new_segment();
-
-  speed_t s = {time, speed};
-
-#if 1
-  if (!speed_q_full()) speed_q_push(s);
-
-#else
-  speed_t *last = speed_q_back();
-
-  if ((speed_q_empty() || last->time != time) && !speed_q_full())
-    speed_q_push(s);
-  else if (last->time == time) last->speed = speed;
-#endif
+  if (spindle.type == SPINDLE_TYPE_PWM) pwm_spindle_update();
 }
 
 
-static void _update_speed() {_set_speed(spindle.speed);}
+static void _update_speed() {spindle_set_speed(0, spindle.speed);}
 
 
 static void _deinit_cb() {
@@ -179,7 +114,7 @@ static void _deinit_cb() {
   default: vfd_spindle_init(); break;
   }
 
-  _set_speed(spindle.speed);
+  spindle_set_speed(0, spindle.speed);
 }
 
 
@@ -204,7 +139,7 @@ void set_tool_type(uint8_t value) {
 
 
 float get_speed() {return _get_speed();}
-void set_speed(float speed) {spindle_queue_speed(0, speed);}
+void set_speed(float speed) {spindle_set_speed(0, speed);}
 bool get_tool_reversed() {return spindle.reversed;}
 
 
index 1947aa6e374bd0b1a207813c56e1c76075c28e0d..7626f41e33c0fa49a535ff18d2820454849154fb 100644 (file)
@@ -46,11 +46,8 @@ typedef enum {
 typedef void (*deinit_cb_t)();
 
 
-void spindle_init();
 spindle_type_t spindle_get_type();
 void spindle_stop();
 bool spindle_is_reversed();
 void spindle_update();
-void spindle_next_segment();
-void spindle_new_segment();
-void spindle_queue_speed(int8_t time, float speed);
+void spindle_set_speed(uint8_t time, float speed);
index 89397c185c00447c006ca1685c2897d333302ab5..6e6904aae53acb3e5d17a2f8340143c8da6095d4 100644 (file)
@@ -165,8 +165,6 @@ static void _load_move() {
     return;
   }
 
-  spindle_next_segment();
-
   // Start move
   if (st.move_type == MOVE_TYPE_LINE)
     for (int motor = 0; motor < MOTORS; motor++)
index 098a80fe8e81431be8cd2c65b337be3f1da2a1dc..d18c7fa2e4432e857ad3825d88392baaf6246363 100644 (file)
@@ -91,7 +91,7 @@ def parse_args():
                         help = 'HTTP address to bind')
     parser.add_argument('-s', '--serial', default = '/dev/ttyAMA0',
                         help = 'Serial device')
-    parser.add_argument('-b', '--baud', default = 115200, type = int,
+    parser.add_argument('-b', '--baud', default = 230400, type = int,
                         help = 'Serial baud rate')
     parser.add_argument('--i2c-port', default = 1, type = int,
                         help = 'I2C port')