From ee06599f7cd223326c53384d531290446a48bcb9 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Fri, 2 Nov 2018 03:32:38 -0700 Subject: [PATCH] Improved PWM speed sync, version bump --- CHANGELOG.md | 4 +- package-lock.json | 2 +- package.json | 2 +- src/avr/src/config.h | 6 ++- src/avr/src/line.c | 5 +-- src/avr/src/main.c | 2 - src/avr/src/pwm_spindle.c | 90 ++++++++++++++++++++++++++++++++------- src/avr/src/pwm_spindle.h | 3 +- src/avr/src/spindle.c | 79 +++------------------------------- src/avr/src/spindle.h | 5 +-- src/avr/src/stepper.c | 2 - src/py/bbctrl/__init__.py | 2 +- 12 files changed, 97 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ba1168..dc977b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/package-lock.json b/package-lock.json index 15e29b4..c42f3e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "bbctrl", - "version": "0.3.29", + "version": "0.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8eb06eb..c56b935 100644 --- a/package.json +++ b/package.json @@ -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+", diff --git a/src/avr/src/config.h b/src/avr/src/config.h index d8bb92d..b96a4d3 100644 --- a/src/avr/src/config.h +++ b/src/avr/src/config.h @@ -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) diff --git a/src/avr/src/line.c b/src/avr/src/line.c index 7722a24..b1f18e6 100644 --- a/src/avr/src/line.c +++ b/src/avr/src/line.c @@ -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); } diff --git a/src/avr/src/main.c b/src/avr/src/main.c index a6b3470..f93bcf5 100644 --- a/src/avr/src/main.c +++ b/src/avr/src/main.c @@ -42,7 +42,6 @@ #include "analog.h" #include "exec.h" #include "state.h" -#include "spindle.h" #include @@ -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 diff --git a/src/avr/src/pwm_spindle.c b/src/avr/src/pwm_spindle.c index a7c36f4..b905610 100644 --- a/src/avr/src/pwm_spindle.c +++ b/src/avr/src/pwm_spindle.c @@ -34,12 +34,27 @@ #include +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;} diff --git a/src/avr/src/pwm_spindle.h b/src/avr/src/pwm_spindle.h index 1d467a1..5ac5e54 100644 --- a/src/avr/src/pwm_spindle.h +++ b/src/avr/src/pwm_spindle.h @@ -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(); diff --git a/src/avr/src/spindle.c b/src/avr/src/spindle.c index ca733cd..1965cae 100644 --- a/src/avr/src/spindle.c +++ b/src/avr/src/spindle.c @@ -35,21 +35,6 @@ #include -#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;} diff --git a/src/avr/src/spindle.h b/src/avr/src/spindle.h index 1947aa6..7626f41 100644 --- a/src/avr/src/spindle.h +++ b/src/avr/src/spindle.h @@ -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); diff --git a/src/avr/src/stepper.c b/src/avr/src/stepper.c index 89397c1..6e6904a 100644 --- a/src/avr/src/stepper.c +++ b/src/avr/src/stepper.c @@ -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++) diff --git a/src/py/bbctrl/__init__.py b/src/py/bbctrl/__init__.py index 098a80f..d18c7fa 100644 --- a/src/py/bbctrl/__init__.py +++ b/src/py/bbctrl/__init__.py @@ -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') -- 2.27.0