Fixed a number of bugs caused by using abs() on floats and long ints. Added support for selectively inverting bits of the stepping port. Debugged, optimized and cleaned up timing code for the step-pulses.
This commit is contained in:
parent
6ac3b3f2e6
commit
a42c03601d
2
Makefile
2
Makefile
@ -35,7 +35,7 @@ FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
|
||||
|
||||
# Tune the lines below only if you know what you are doing:
|
||||
|
||||
AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) -B 10
|
||||
AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) -B 10 -F
|
||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -I.
|
||||
|
||||
# symbolic targets:
|
||||
|
50
config.h
50
config.h
@ -23,11 +23,13 @@
|
||||
|
||||
#define VERSION "0.0"
|
||||
|
||||
#define X_STEPS_PER_MM 128.0
|
||||
#define Y_STEPS_PER_MM 128.0
|
||||
#define Z_STEPS_PER_MM 128.0
|
||||
#define X_STEPS_PER_MM 94.488188976378
|
||||
#define Y_STEPS_PER_MM 94.488188976378
|
||||
#define Z_STEPS_PER_MM 94.488188976378
|
||||
|
||||
#define INCHES_PER_MM 25.4
|
||||
#define STEP_PULSE_MICROSECONDS 30
|
||||
|
||||
#define INCHES_PER_MM (1.0/25.4)
|
||||
#define X_STEPS_PER_INCH X_STEPS_PER_MM*INCHES_PER_MM
|
||||
#define Y_STEPS_PER_INCH Y_STEPS_PER_MM*INCHES_PER_MM
|
||||
#define Z_STEPS_PER_INCH Z_STEPS_PER_MM*INCHES_PER_MM
|
||||
@ -35,12 +37,12 @@
|
||||
#define RAPID_FEEDRATE 960.0 // in millimeters per minute
|
||||
#define DEFAULT_FEEDRATE 960.0
|
||||
|
||||
#define STEPPERS_ENABLE_DDR DDRB
|
||||
#define STEPPERS_ENABLE_PORT PORTB
|
||||
#define STEPPERS_ENABLE_BIT 6
|
||||
#define STEPPERS_ENABLE_DDR DDRD
|
||||
#define STEPPERS_ENABLE_PORT PORTD
|
||||
#define STEPPERS_ENABLE_BIT 2
|
||||
|
||||
#define STEPPING_DDR DDRB
|
||||
#define STEPPING_PORT PORTB
|
||||
#define STEPPING_DDR DDRC
|
||||
#define STEPPING_PORT PORTC
|
||||
#define X_STEP_BIT 0
|
||||
#define Y_STEP_BIT 1
|
||||
#define Z_STEP_BIT 2
|
||||
@ -48,19 +50,20 @@
|
||||
#define Y_DIRECTION_BIT 4
|
||||
#define Z_DIRECTION_BIT 5
|
||||
|
||||
#define LIMIT_DDR DDRC
|
||||
#define LIMIT_PORT PORTC
|
||||
#define X_LIMIT_BIT 0
|
||||
#define Y_LIMIT_BIT 1
|
||||
#define Z_LIMIT_BIT 2
|
||||
|
||||
#define SPINDLE_ENABLE_DDR DDRC
|
||||
#define SPINDLE_ENABLE_PORT PORTC
|
||||
#define SPINDLE_ENABLE_BIT 3
|
||||
#define LIMIT_DDR DDRD
|
||||
#define LIMIT_PORT PORTD
|
||||
#define X_LIMIT_BIT 3
|
||||
#define Y_LIMIT_BIT 4
|
||||
#define Z_LIMIT_BIT 5
|
||||
|
||||
#define SPINDLE_DIRECTION_DDR DDRC
|
||||
#define SPINDLE_DIRECTION_PORT PORTC
|
||||
#define SPINDLE_DIRECTION_BIT 4
|
||||
#define SPINDLE_ENABLE_DDR DDRD
|
||||
#define SPINDLE_ENABLE_PORT PORTD
|
||||
#define SPINDLE_ENABLE_BIT 6
|
||||
|
||||
#define SPINDLE_DIRECTION_DDR DDRD
|
||||
#define SPINDLE_DIRECTION_PORT PORTD
|
||||
#define SPINDLE_DIRECTION_BIT 7
|
||||
|
||||
#define BAUD_RATE 9600
|
||||
|
||||
@ -69,4 +72,11 @@
|
||||
#define STEPPING_MASK (STEP_MASK | DIRECTION_MASK)
|
||||
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT))
|
||||
|
||||
// Use this line for default operation (step-pulses high)
|
||||
#define STEPPING_INVERT_MASK 0
|
||||
// Uncomment this line for inverted stepping (step-pulses low, rest high)
|
||||
// #define STEPPING_INVERT_MASK (STEP_MASK)
|
||||
// Or bake your own like this adding any step-bits or directions you want to invert:
|
||||
// #define STEPPING_INVERT_MASK (STEP_MASK | (1<<Z_DIRECTION_BIT))
|
||||
|
||||
#endif
|
||||
|
2
gcode.c
2
gcode.c
@ -118,7 +118,7 @@ void gc_init() {
|
||||
}
|
||||
|
||||
inline float to_millimeters(double value) {
|
||||
return(gc.inches_mode ? value * INCHES_PER_MM : value);
|
||||
return(gc.inches_mode ? (value * INCHES_PER_MM) : value);
|
||||
}
|
||||
|
||||
|
||||
|
2670
gcode/braid_two_decimals.gcode
Normal file
2670
gcode/braid_two_decimals.gcode
Normal file
File diff suppressed because it is too large
Load Diff
1674
gcode/miller.gcode
Normal file
1674
gcode/miller.gcode
Normal file
File diff suppressed because it is too large
Load Diff
@ -54,7 +54,7 @@ double theta(double x, double y)
|
||||
|
||||
// Find the quadrant of the coordinate
|
||||
int quadrant_of_the_circle(int32_t x, int32_t y) {
|
||||
if (abs(x)<abs(y)){
|
||||
if (labs(x)<labs(y)){
|
||||
if (y>0) {
|
||||
return(0);
|
||||
} else {
|
||||
|
4
main.c
4
main.c
@ -33,12 +33,14 @@
|
||||
int main(void)
|
||||
{
|
||||
beginSerial(BAUD_RATE);
|
||||
st_init();
|
||||
st_init(); // initialize the stepper subsystem
|
||||
mc_init(); // initialize motion control subsystem
|
||||
spindle_init(); // initialize spindle controller
|
||||
gc_init(); // initialize gcode-parser
|
||||
sp_init(); // initialize the serial protocol
|
||||
|
||||
st_start(); // start the stepper subsystem
|
||||
|
||||
for(;;){
|
||||
sleep_mode();
|
||||
sp_process(); // process the serial protocol
|
||||
|
@ -96,7 +96,7 @@ void mc_line(double x, double y, double z, float feed_rate, int invert_feed_rate
|
||||
target[Z_AXIS] = round(z*Z_STEPS_PER_MM);
|
||||
// Determine direction and travel magnitude for each axis
|
||||
for(axis = X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
step_count[axis] = abs(target[axis] - position[axis]);
|
||||
step_count[axis] = labs(target[axis] - position[axis]);
|
||||
direction[axis] = signof(target[axis] - position[axis]);
|
||||
}
|
||||
// Find the magnitude of the axis with the longest travel
|
||||
@ -138,7 +138,9 @@ void mc_line(double x, double y, double z, float feed_rate, int invert_feed_rate
|
||||
}
|
||||
}
|
||||
}
|
||||
if(step_bits) { step_steppers(step_bits); }
|
||||
if(step_bits) {
|
||||
step_steppers(step_bits);
|
||||
}
|
||||
} while (step_bits);
|
||||
mode = MC_MODE_AT_REST;
|
||||
}
|
||||
@ -210,11 +212,11 @@ void mc_arc(double theta, double angular_travel, double radius, double linear_tr
|
||||
int target_quadrant = quadrant_of_the_circle(target_x, target_y);
|
||||
uint32_t arc_steps=0;
|
||||
// Will this whole arc take place within the same quadrant?
|
||||
if (start_quadrant == target_quadrant && (abs(angular_travel) <= (M_PI/2))) {
|
||||
if (start_quadrant == target_quadrant && (fabs(angular_travel) <= (M_PI/2))) {
|
||||
if(quadrant_horizontal(start_quadrant)) { // a horizontal quadrant where x will be the primary direction
|
||||
arc_steps = abs(target_x-start_x);
|
||||
arc_steps = labs(target_x-start_x);
|
||||
} else { // a vertical quadrant where y will be the primary direction
|
||||
arc_steps = abs(target_y-start_y);
|
||||
arc_steps = labs(target_y-start_y);
|
||||
}
|
||||
} else { // the start and target points are in different quadrants
|
||||
// Lets estimate the amount of steps along half a quadrant
|
||||
@ -234,7 +236,7 @@ void mc_arc(double theta, double angular_travel, double radius, double linear_tr
|
||||
|
||||
// Set up the linear interpolation of the "depth" axis -----------------------------------------------------
|
||||
|
||||
int32_t linear_steps = abs(st_millimeters_to_steps(linear_travel, axis_linear));
|
||||
int32_t linear_steps = labs(st_millimeters_to_steps(linear_travel, axis_linear));
|
||||
int linear_direction = signof(linear_travel);
|
||||
// The number of steppings needed to trace this motion is equal to the motion that require the maximum
|
||||
// amount of steps: the arc or the line:
|
||||
@ -247,7 +249,7 @@ void mc_arc(double theta, double angular_travel, double radius, double linear_tr
|
||||
// Calculate feed rate -------------------------------------------------------------------------------------
|
||||
|
||||
// We then calculate the millimeters of helical travel
|
||||
double millimeters_of_travel = hypot(angular_travel*radius, abs(linear_travel));
|
||||
double millimeters_of_travel = hypot(angular_travel*radius, labs(linear_travel));
|
||||
// Then we calculate the microseconds between each step as if we will trace the full circle.
|
||||
// It doesn't matter what fraction of the circle we are actually going to trace. The pace is the same.
|
||||
compute_and_set_step_pace(feed_rate, millimeters_of_travel, maximum_steps, invert_feed_rate);
|
||||
@ -288,12 +290,12 @@ void mc_arc(double theta, double angular_travel, double radius, double linear_tr
|
||||
direction[axis_1] = dx;
|
||||
direction[axis_2] = dy;
|
||||
// Check which axis will be "major" for this stepping
|
||||
if (abs(x)<abs(y)) {
|
||||
if (labs(x)<labs(y)) {
|
||||
// X is major: Step arc horizontally
|
||||
error += 1 + 2*x * dx;
|
||||
x+=dx;
|
||||
diagonal_error = error + 1 + 2*y*dy;
|
||||
if(abs(error) >= abs(diagonal_error)) {
|
||||
if(labs(error) >= labs(diagonal_error)) {
|
||||
y += dy;
|
||||
error = diagonal_error;
|
||||
step_bits |= diagonal_bits; // step diagonal
|
||||
@ -305,7 +307,7 @@ void mc_arc(double theta, double angular_travel, double radius, double linear_tr
|
||||
error += 1 + 2*y * dy;
|
||||
y+=dy;
|
||||
diagonal_error = error + 1 + 2*x * dx;
|
||||
if(abs(error) >= abs(diagonal_error)) {
|
||||
if(labs(error) >= labs(diagonal_error)) {
|
||||
x += dx;
|
||||
error = diagonal_error;
|
||||
step_bits |= diagonal_bits; // step diagonal
|
||||
@ -362,16 +364,7 @@ void set_stepper_directions(int8_t *direction)
|
||||
((direction[Z_AXIS]&0x80)>>(7-Z_DIRECTION_BIT)));
|
||||
}
|
||||
|
||||
// Step enabled steppers. Enabled should be an array of three bytes. Each byte represent one
|
||||
// stepper motor in the order X, Y, Z. Set the bytes of the steppers you want to step to
|
||||
// 1, and the rest to 0.
|
||||
inline void step_steppers(uint8_t bits)
|
||||
{
|
||||
st_buffer_step(direction_bits | bits);
|
||||
}
|
||||
|
||||
// Step only one motor
|
||||
inline void step_axis(uint8_t axis)
|
||||
{
|
||||
st_buffer_step(direction_bits | st_bit_for_stepper(axis));
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
socat -d -d READLINE /dev/tty.usbserial-A4001o6L,clocal=1,nonblock=1,cread=1,cs8,ixon=1,ixoff=1
|
||||
socat -d -d READLINE /dev/tty.usbserial-A9007QcR,clocal=1,nonblock=1,cread=1,cs8,ixon=1,ixoff=1
|
||||
|
||||
|
@ -24,18 +24,21 @@ if ARGV.empty?
|
||||
exit
|
||||
end
|
||||
|
||||
SerialPort.open('/dev/tty.usbserial-A4001o6L', 9600) do |sp|
|
||||
SerialPort.open('/dev/tty.usbserial-A9007QcR', 9600) do |sp|
|
||||
sp.write("\r\n\r\n");
|
||||
sleep 5
|
||||
ARGV.each do |file|
|
||||
puts "Processing file #{file}"
|
||||
prebuffer = $prebuffer ? 10 : 0
|
||||
prebuffer = $prebuffer ? 7 : 0
|
||||
File.readlines(file).each do |line|
|
||||
next if line.strip == ''
|
||||
puts line.strip
|
||||
sp.write("#{line.strip}\r\n");
|
||||
if prebuffer == 0
|
||||
sleep 0.1
|
||||
begin
|
||||
result = sp.gets.strip
|
||||
puts result unless result == '' or result == 'ok'
|
||||
puts "Grbl >> #{result}" unless result == '' or result == 'ok'
|
||||
end while result != 'ok'
|
||||
else
|
||||
prebuffer -= 1
|
||||
|
@ -26,9 +26,9 @@
|
||||
#include <math.h>
|
||||
#include "nuts_bolts.h"
|
||||
|
||||
#define BLOCK_BUFFER_SIZE 128
|
||||
#define LINE_BUFFER_SIZE 128
|
||||
|
||||
char line[BLOCK_BUFFER_SIZE];
|
||||
char line[LINE_BUFFER_SIZE];
|
||||
uint8_t line_counter;
|
||||
|
||||
void prompt() {
|
||||
@ -79,6 +79,9 @@ void sp_process()
|
||||
{
|
||||
if((c < 32)) { // Line is complete. Then execute!
|
||||
line[line_counter] = 0;
|
||||
// printString("->");
|
||||
// printString(line);
|
||||
// printString("<-\r\n");
|
||||
gc_execute_line(line);
|
||||
line_counter = 0;
|
||||
prompt();
|
||||
|
69
stepper.c
69
stepper.c
@ -25,6 +25,7 @@
|
||||
#include "stepper.h"
|
||||
#include "config.h"
|
||||
#include <math.h>
|
||||
#include <util/delay.h>
|
||||
#include "nuts_bolts.h"
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
@ -58,14 +59,13 @@ SIGNAL(SIG_OUTPUT_COMPARE1A)
|
||||
config_pace_timer(next_pace);
|
||||
next_pace = 0;
|
||||
} else {
|
||||
// Set the direction pins a nanosecond or two before you step the steppers
|
||||
popped ^= STEPPING_INVERT_MASK;
|
||||
// Set the direction pins a cuple of nanoseconds before we step the steppers
|
||||
STEPPING_PORT = (STEPPING_PORT & ~DIRECTION_MASK) | (popped & DIRECTION_MASK);
|
||||
// Then pulse the stepping pins
|
||||
STEPPING_PORT = (STEPPING_PORT & ~STEP_MASK) | popped;
|
||||
// Reset and start timer 2 which will reset the motor port after 5 microsecond
|
||||
TCNT2 = 0; // reset counter
|
||||
OCR2A = 5*TICKS_PER_MICROSECOND; // set the trigger time
|
||||
TIMSK2 |= (1<<OCIE2A); // enable interrupt
|
||||
// Reset step pulse reset timer
|
||||
TCNT2 = -(((STEP_PULSE_MICROSECONDS-4)*TICKS_PER_MICROSECOND)/8);
|
||||
}
|
||||
// move the step buffer tail to the next instruction
|
||||
step_buffer_tail = (step_buffer_tail + 1) % STEP_BUFFER_SIZE;
|
||||
@ -73,11 +73,11 @@ SIGNAL(SIG_OUTPUT_COMPARE1A)
|
||||
}
|
||||
|
||||
// This interrupt is set up by SIG_OUTPUT_COMPARE1A when it sets the motor port bits. It resets
|
||||
// the motor port after a short period (5us) completing one step cycle.
|
||||
SIGNAL(SIG_OUTPUT_COMPARE2A)
|
||||
// the motor port after a short period (STEP_PULSE_MICROSECONDS) completing one step cycle.
|
||||
SIGNAL(SIG_OVERFLOW2)
|
||||
{
|
||||
STEPPING_PORT = STEPPING_PORT & ~STEP_MASK; // reset stepping pins (leave the direction pins)
|
||||
TIMSK2 &= ~(1<<OCIE2A); // disable this timer interrupt until next time
|
||||
// reset stepping pins (leave the direction pins)
|
||||
STEPPING_PORT = (STEPPING_PORT & ~STEPPING_MASK) | (STEPPING_INVERT_MASK & STEPPING_MASK);
|
||||
}
|
||||
|
||||
// Initialize and start the stepper motor subsystem
|
||||
@ -85,7 +85,7 @@ void st_init()
|
||||
{
|
||||
// Configure directions of interface pins
|
||||
STEPPING_DDR |= STEPPING_MASK;
|
||||
printInteger(STEPPING_DDR);
|
||||
STEPPING_PORT = (STEPPING_PORT & ~STEPPING_MASK) | STEPPING_INVERT_MASK;
|
||||
LIMIT_DDR &= ~(LIMIT_MASK);
|
||||
STEPPERS_ENABLE_DDR |= 1<<STEPPERS_ENABLE_BIT;
|
||||
|
||||
@ -101,17 +101,16 @@ void st_init()
|
||||
|
||||
// Configure Timer 2
|
||||
TCCR2A = 0; // Normal operation
|
||||
TCCR2B = 1<<CS20; // Full speed, no prescaler
|
||||
TCCR2B = (1<<CS21); // Full speed, 1/8 prescaler
|
||||
TIMSK2 = 0; // All interrupts disabled
|
||||
|
||||
sei();
|
||||
|
||||
// start off with a mellow pace
|
||||
config_pace_timer(20000);
|
||||
st_start();
|
||||
}
|
||||
|
||||
void st_buffer_step(uint8_t motor_port_bits)
|
||||
inline void st_buffer_step(uint8_t motor_port_bits)
|
||||
{
|
||||
// Buffer nothing unless stepping subsystem is running
|
||||
if (stepper_mode != STEPPER_MODE_RUNNING) { return; }
|
||||
@ -146,8 +145,10 @@ void st_flush()
|
||||
// Start the stepper subsystem
|
||||
void st_start()
|
||||
{
|
||||
// Enable timer interrupt
|
||||
// Enable timer interrupts
|
||||
TIMSK1 |= (1<<OCIE1A);
|
||||
TIMSK2 |= (1<<TOIE2);
|
||||
// set enable pin
|
||||
STEPPERS_ENABLE_PORT |= 1<<STEPPERS_ENABLE_BIT;
|
||||
stepper_mode = STEPPER_MODE_RUNNING;
|
||||
}
|
||||
@ -155,8 +156,12 @@ void st_start()
|
||||
// Execute all buffered steps, then stop the stepper subsystem
|
||||
inline void st_stop()
|
||||
{
|
||||
// flush pending operations
|
||||
st_synchronize();
|
||||
// disable timer interrupts
|
||||
TIMSK1 &= ~(1<<OCIE1A);
|
||||
TIMSK2 &= ~(1<<TOIE2);
|
||||
// reset enable pin
|
||||
STEPPERS_ENABLE_PORT &= ~(1<<STEPPERS_ENABLE_BIT);
|
||||
stepper_mode = STEPPER_MODE_STOPPED;
|
||||
}
|
||||
@ -238,42 +243,6 @@ int check_limit_switch(int axis)
|
||||
return((LIMIT_PORT&mask) || (LIMIT_PORT&mask));
|
||||
}
|
||||
|
||||
// void perform_go_home()
|
||||
// {
|
||||
// int axis;
|
||||
// if(stepper_mode.home.phase == PHASE_HOME_RETURN) {
|
||||
// // We are running all axes in reverse until all limit switches are tripped
|
||||
// // Check all limit switches:
|
||||
// for(axis=X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
// stepper_mode.home.away[axis] |= check_limit_switch(axis);
|
||||
// }
|
||||
// // Step steppers. First retract along Z-axis. Then X and Y.
|
||||
// if(stepper_mode.home.away[Z_AXIS]) {
|
||||
// step_axis(Z_AXIS);
|
||||
// } else {
|
||||
// // Check if all axes are home
|
||||
// if(!(stepper_mode.home.away[X_AXIS] || stepper_mode.home.away[Y_AXIS])) {
|
||||
// // All axes are home, prepare next phase: to nudge the tool carefully out of the limit switches
|
||||
// memset(stepper_mode.home.direction, 1, sizeof(stepper_mode.home.direction)); // direction = [1,1,1]
|
||||
// set_direction_bits(stepper_mode.home.direction);
|
||||
// stepper_mode.home.phase == PHASE_HOME_NUDGE;
|
||||
// return;
|
||||
// }
|
||||
// step_steppers(stepper_mode.home.away);
|
||||
// }
|
||||
// } else {
|
||||
// for(axis=X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
// if(check_limit_switch(axis)) {
|
||||
// step_axis(axis);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// // When this code is reached it means all axes are free of their limit-switches. Complete the cycle and rest:
|
||||
// clear_vector(stepper_mode.position); // By definition this is location [0, 0, 0]
|
||||
// stepper_mode.mode = MODE_AT_REST;
|
||||
// }
|
||||
// }
|
||||
|
||||
void st_go_home()
|
||||
{
|
||||
// Todo: Perform the homing cycle
|
||||
|
@ -42,7 +42,7 @@ uint8_t st_bit_for_stepper(int axis);
|
||||
void st_buffer_pace(uint32_t microseconds);
|
||||
|
||||
// Buffer a new instruction for the steppers
|
||||
void st_buffer_step(uint8_t motor_port_bits);
|
||||
inline void st_buffer_step(uint8_t motor_port_bits);
|
||||
|
||||
// Block until all buffered steps are executed
|
||||
void st_synchronize();
|
||||
|
@ -28,7 +28,7 @@
|
||||
// using a ring buffer (I think), in which rx_buffer_head is the index of the
|
||||
// location to which to write the next incoming character and rx_buffer_tail
|
||||
// is the index of the location from which to read.
|
||||
#define RX_BUFFER_SIZE 128
|
||||
#define RX_BUFFER_SIZE 256
|
||||
|
||||
unsigned char rx_buffer[RX_BUFFER_SIZE];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user