version 0.1
This commit is contained in:
commit
9df29ad3b3
165
COPYING.txt
Normal file
165
COPYING.txt
Normal file
@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
89
Makefile
Normal file
89
Makefile
Normal file
@ -0,0 +1,89 @@
|
||||
# Part of Grbl
|
||||
#
|
||||
# Copyright (c) 2009 Simen Svale Skogsrud
|
||||
#
|
||||
# Grbl is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Grbl is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# This is a prototype Makefile. Modify it according to your needs.
|
||||
# You should at least check the settings for
|
||||
# DEVICE ....... The AVR device you compile for
|
||||
# CLOCK ........ Target AVR clock rate in Hertz
|
||||
# OBJECTS ...... The object files created from your source files. This list is
|
||||
# usually the same as the list of source files with suffix ".o".
|
||||
# PROGRAMMER ... Options to avrdude which define the hardware you use for
|
||||
# uploading to the AVR and the interface where this hardware
|
||||
# is connected.
|
||||
# FUSES ........ Parameters for avrdude to flash the fuses appropriately.
|
||||
|
||||
DEVICE = atmega168
|
||||
CLOCK = 20000000
|
||||
PROGRAMMER = -c avrisp2 -P usb
|
||||
OBJECTS = main.o motion_control.o gcode.o spindle_control.o wiring_serial.o serial_protocol.o
|
||||
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
|
||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -I.
|
||||
|
||||
# symbolic targets:
|
||||
all: main.hex
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $< -o $@
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -x assembler-with-cpp -c $< -o $@
|
||||
# "-x assembler-with-cpp" should not be necessary since this is the default
|
||||
# file type for the .S (with capital S) extension. However, upper case
|
||||
# characters are not always preserved on Windows. To ensure WinAVR
|
||||
# compatibility define the file type manually.
|
||||
|
||||
.c.s:
|
||||
$(COMPILE) -S $< -o $@
|
||||
|
||||
flash: all
|
||||
$(AVRDUDE) -U flash:w:main.hex:i
|
||||
|
||||
fuse:
|
||||
$(AVRDUDE) $(FUSES)
|
||||
|
||||
# Xcode uses the Makefile targets "", "clean" and "install"
|
||||
install: flash fuse
|
||||
|
||||
# if you use a bootloader, change the command below appropriately:
|
||||
load: all
|
||||
bootloadHID main.hex
|
||||
|
||||
clean:
|
||||
rm -f main.hex main.elf $(OBJECTS)
|
||||
|
||||
# file targets:
|
||||
main.elf: $(OBJECTS)
|
||||
$(COMPILE) -o main.elf $(OBJECTS) -lm
|
||||
|
||||
main.hex: main.elf
|
||||
rm -f main.hex
|
||||
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
|
||||
avr-size main.hex *.o
|
||||
# If you have an EEPROM section, you must also create a hex file for the
|
||||
# EEPROM and add it to the "flash" target.
|
||||
|
||||
# Targets for code debugging and analysis:
|
||||
disasm: main.elf
|
||||
avr-objdump -d main.elf
|
||||
|
||||
cpp:
|
||||
$(COMPILE) -E main.c
|
73
config.h
Normal file
73
config.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
config.h - configuration data for Grbl
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef config_h
|
||||
#define config_h
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
#define X_STEPS_PER_MM 100.0
|
||||
#define Y_STEPS_PER_MM 100.0
|
||||
#define Z_STEPS_PER_MM 100.0
|
||||
|
||||
#define INCHES_PER_MM 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
|
||||
|
||||
#define RAPID_FEEDRATE 1270.0 // in millimeters per minute
|
||||
#define DEFAULT_FEEDRATE 635.0
|
||||
|
||||
#define STEPPERS_ENABLE_DDR DDRB
|
||||
#define STEPPERS_ENABLE_PORT PORTB
|
||||
#define STEPPERS_ENABLE_BIT 6
|
||||
|
||||
#define STEP_DDR DDRB
|
||||
#define STEP_PORT PORTB
|
||||
#define X_STEP_BIT 0
|
||||
#define Y_STEP_BIT 2
|
||||
#define Z_STEP_BIT 4
|
||||
#define STEP_MASK (1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)
|
||||
|
||||
#define DIRECTION_DDR DDRB
|
||||
#define DIRECTION_PORT PORTB
|
||||
#define X_DIRECTION_BIT 1
|
||||
#define Y_DIRECTION_BIT 3
|
||||
#define Z_DIRECTION_BIT 5
|
||||
#define DIRECTION_MASK (1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)
|
||||
|
||||
#define LIMIT_DDR DDRC
|
||||
#define LIMIT_PORT PORTC
|
||||
#define X_LIMIT_BIT 0
|
||||
#define Y_LIMIT_BIT 1
|
||||
#define Z_LIMIT_BIT 2
|
||||
#define LIMIT_MASK (1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)
|
||||
|
||||
#define SPINDLE_ENABLE_DDR DDRC
|
||||
#define SPINDLE_ENABLE_PORT PORTC
|
||||
#define SPINDLE_ENABLE_BIT 3
|
||||
|
||||
#define SPINDLE_DIRECTION_DDR DDRC
|
||||
#define SPINDLE_DIRECTION_PORT PORTC
|
||||
#define SPINDLE_DIRECTION_BIT 4
|
||||
|
||||
#define BAUD_RATE 14400
|
||||
|
||||
#endif
|
308
gcode.c
Normal file
308
gcode.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
gcode.c - rs274/ngc parser.
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This code is inspired by the Arduino GCode Interpreter by Mike Ellery and the NIST RS274/NGC Interpreter
|
||||
by Kramer, Proctor and Messina. */
|
||||
|
||||
/* Intentionally not supported:
|
||||
- Canned cycles
|
||||
- Tool radius compensatino
|
||||
- A,B,C-axes
|
||||
- Multiple coordinate systems
|
||||
- Evaluation of expressions
|
||||
- Variables
|
||||
- Multiple home locations
|
||||
- Probing
|
||||
- Spindle direction
|
||||
- Override control
|
||||
*/
|
||||
|
||||
/*
|
||||
Omitted for the time being:
|
||||
|
||||
group 0 = {G10, G28, G30, G53, G92, G92.1, G92.2, G92.3} (Non modal G-codes)
|
||||
group 5 = {G93, G94} feed rate mode
|
||||
group 12 = {G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3} coordinate system selection
|
||||
group 13 = {G61, G61.1, G64} path control mode
|
||||
group 4 = {M0, M1, M2, M30, M60} stopping
|
||||
group 8 = {M7, M8, M9} coolant (special case: M7 and M8 may be active at the same time)
|
||||
group 9 = {M48, M49} enable/disable feed and speed override switches
|
||||
*/
|
||||
|
||||
#include "gcode.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "nuts_bolts.h"
|
||||
#include <math.h>
|
||||
#include "config.h"
|
||||
#include "motion_control.h"
|
||||
#include "spindle_control.h"
|
||||
|
||||
#define NEXT_ACTION_DEFAULT 0
|
||||
#define NEXT_ACTION_DWELL 1
|
||||
#define NEXT_ACTION_GO_HOME 2
|
||||
|
||||
#define MOTION_MODE_RAPID_LINEAR 0 // G0
|
||||
#define MOTION_MODE_LINEAR 1 // G1
|
||||
#define MOTION_MODE_CW_ARC 2 // G2
|
||||
#define MOTION_MODE_CCW_ARC 3 // G3
|
||||
#define MOTION_MODE_CANCEL 4 // G80
|
||||
|
||||
#define PLANE_XY 0; // G17
|
||||
#define PLANE_XZ 1; // G18
|
||||
#define PLANE_YZ 2; // G19
|
||||
|
||||
#define PATH_CONTROL_MODE_EXACT_PATH 0
|
||||
#define PATH_CONTROL_MODE_EXACT_STOP 1
|
||||
#define PATH_CONTROL_MODE_CONTINOUS 2
|
||||
|
||||
#define PROGRAM_FLOW_RUNNING 0
|
||||
#define PROGRAM_FLOW_PAUSED 1
|
||||
#define PROGRAM_FLOW_COMPLETED 2
|
||||
|
||||
#define SPINDLE_DIRECTION_CW 0
|
||||
#define SPINDLE_DIRECTION_CCW 1
|
||||
|
||||
// Using packed bit fields saves a "lot" of invaluable SRAM, but bumps the compiled size of this unit
|
||||
// by 100 bytes. If we get tight on code space, consider using byte aligned values again.
|
||||
struct ParserState {
|
||||
uint32_t line_number;
|
||||
uint8_t status_code:5;
|
||||
|
||||
uint8_t motion_mode:3; /* {G0, G1, G2, G3, G38.2, G80, G81, G82, G83, G84, G85, G86, G87, G88, G89} */
|
||||
uint8_t inverse_feed_rate_mode:1; /* G93, G94 */
|
||||
uint8_t plane:2; /* {G17, G18, G19} */
|
||||
uint8_t inches_mode:1; /* 0 = millimeter mode, 1 = inches mode {G20, G21} */
|
||||
uint8_t program_flow:2;
|
||||
int spindle_direction:2;
|
||||
double feed_rate; /* Millimeters/second */
|
||||
double logical_position[3]; /* Where the interpreter considers the tool to be at this point in the code */
|
||||
uint8_t tool;
|
||||
int16_t spindle_speed; /* RPM/100 */
|
||||
};
|
||||
struct ParserState state;
|
||||
|
||||
#define FAIL(status) state.status_code = status;
|
||||
|
||||
int read_double(char *line, //!< string: line of RS274/NGC code being processed
|
||||
int *counter, //!< pointer to a counter for logical_position on the line
|
||||
double *double_ptr); //!< pointer to double to be read
|
||||
|
||||
int next_statement(char *letter, double *double_ptr, char *line, int *counter);
|
||||
|
||||
|
||||
void gc_init() {
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.feed_rate = DEFAULT_FEEDRATE;
|
||||
}
|
||||
|
||||
inline float to_millimeters(double value) {
|
||||
return(state.inches_mode ? value * INCHES_PER_MM : value);
|
||||
}
|
||||
|
||||
// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase
|
||||
// characters and signed floats (no whitespace).
|
||||
uint8_t gc_execute_line(char *line) {
|
||||
int counter;
|
||||
char letter;
|
||||
double value;
|
||||
double unit_converted_value;
|
||||
double inverse_feed_rate;
|
||||
|
||||
uint8_t absolute_mode = 0; /* 0 = relative motion, 1 = absolute motion {G90, G91} */
|
||||
uint8_t next_action = NEXT_ACTION_DEFAULT; /* One of the NEXT_ACTION_-constants */
|
||||
|
||||
double target[3], offset[3];
|
||||
|
||||
double p, r;
|
||||
int int_value, axis;
|
||||
|
||||
state.line_number++;
|
||||
state.status_code = GCSTATUS_OK;
|
||||
|
||||
/* First: parse all statements */
|
||||
|
||||
if (line[0] == '(') { return(state.status_code); }
|
||||
if (line[0] == '/') { counter++; } // ignore block delete
|
||||
|
||||
// Pass 1: Commands
|
||||
while(next_statement(&letter, &value, line, &counter)) {
|
||||
int_value = trunc(value);
|
||||
switch(letter) {
|
||||
case 'G':
|
||||
switch(int_value) {
|
||||
case 0: state.motion_mode = MOTION_MODE_RAPID_LINEAR; break;
|
||||
case 1: state.motion_mode = MOTION_MODE_LINEAR; break;
|
||||
case 2: state.motion_mode = MOTION_MODE_CW_ARC; break;
|
||||
case 3: state.motion_mode = MOTION_MODE_CCW_ARC; break;
|
||||
case 4: next_action = NEXT_ACTION_DWELL; break;
|
||||
case 17: state.plane = PLANE_XY; break;
|
||||
case 18: state.plane = PLANE_XZ; break;
|
||||
case 19: state.plane = PLANE_YZ; break;
|
||||
case 20: state.inches_mode = true; break;
|
||||
case 21: state.inches_mode = false; break;
|
||||
case 28: case 30: next_action = NEXT_ACTION_GO_HOME; break;
|
||||
case 53: absolute_mode = 1; break;
|
||||
case 80: state.motion_mode = MOTION_MODE_CANCEL; break;
|
||||
case 93: state.inverse_feed_rate_mode = true; break;
|
||||
case 94: state.inverse_feed_rate_mode = false; break;
|
||||
default: FAIL(GCSTATUS_UNSUPPORTED_STATEMENT);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
switch(int_value) {
|
||||
case 0: case 1: state.program_flow = PROGRAM_FLOW_PAUSED; break;
|
||||
case 2: state.program_flow = PROGRAM_FLOW_COMPLETED; break;
|
||||
case 3: state.spindle_direction = 1; break;
|
||||
case 4: state.spindle_direction = -1; break;
|
||||
case 5: state.spindle_direction = 0; break;
|
||||
default: FAIL(GCSTATUS_UNSUPPORTED_STATEMENT);
|
||||
}
|
||||
break;
|
||||
case 'T': state.tool = trunc(value); break;
|
||||
}
|
||||
if(state.status_code) { break; }
|
||||
}
|
||||
|
||||
// If there were any errors parsing this line, we will return right away with the bad news
|
||||
if (state.status_code) { return(state.status_code); }
|
||||
|
||||
// Pass 2: Parameters
|
||||
counter = 0;
|
||||
clear_vector(offset);
|
||||
while(next_statement(&letter, &value, line, &counter)) {
|
||||
int_value = trunc(value);
|
||||
unit_converted_value = to_millimeters(value);
|
||||
switch(letter) {
|
||||
case 'F':
|
||||
if (state.inverse_feed_rate_mode) {
|
||||
inverse_feed_rate = unit_converted_value; // seconds per motion for this motion only
|
||||
} else {
|
||||
state.feed_rate = unit_converted_value; // millimeters pr second
|
||||
}
|
||||
break;
|
||||
case 'I': case 'J': case 'K': offset[letter-'I'] = unit_converted_value; break;
|
||||
case 'P': p = value; break;
|
||||
case 'R': r = unit_converted_value; break;
|
||||
case 'S': state.spindle_speed = value; break;
|
||||
case 'X': case 'Y': case 'Z':
|
||||
axis = letter - 'X';
|
||||
if (absolute_mode) {
|
||||
target[axis] = unit_converted_value;
|
||||
} else {
|
||||
target[axis] = state.logical_position[axis]+unit_converted_value;
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update spindle state
|
||||
if (state.spindle_direction) {
|
||||
spindle_run(state.spindle_direction, state.spindle_speed);
|
||||
} else {
|
||||
spindle_stop();
|
||||
}
|
||||
|
||||
// Perform any physical actions
|
||||
switch (next_action) {
|
||||
case NEXT_ACTION_GO_HOME: mc_go_home(); break;
|
||||
case NEXT_ACTION_DWELL: mc_dwell(trunc(p*1000)); break;
|
||||
case NEXT_ACTION_DEFAULT:
|
||||
switch (state.motion_mode) {
|
||||
case MOTION_MODE_CANCEL: break;
|
||||
case MOTION_MODE_RAPID_LINEAR: case MOTION_MODE_LINEAR:
|
||||
if (inverse_feed_rate) {
|
||||
mc_linear_motion(target[X_AXIS], target[Y_AXIS], target[Z_AXIS],
|
||||
inverse_feed_rate, true);
|
||||
} else {
|
||||
mc_linear_motion(target[X_AXIS], target[Y_AXIS], target[Z_AXIS],
|
||||
(state.motion_mode == MOTION_MODE_LINEAR) ? state.feed_rate : RAPID_FEEDRATE,
|
||||
false);
|
||||
}
|
||||
break;
|
||||
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
|
||||
// to be implemented
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mc_execute();
|
||||
|
||||
// As far as the parser is concerned, the logical_position is now == target. In reality the
|
||||
// motion control system might still be processing the action and the real tool position
|
||||
// in any intermediate location.
|
||||
memcpy(state.logical_position, target, sizeof(state.logical_position));
|
||||
|
||||
return(state.status_code);
|
||||
}
|
||||
|
||||
void gc_get_status(double *position, uint8_t *status_code, int *inches_mode, uint32_t *line_number)
|
||||
{
|
||||
int axis;
|
||||
if (state.inches_mode) {
|
||||
for(axis = X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
position[axis] = state.logical_position[axis]*INCHES_PER_MM;
|
||||
}
|
||||
} else {
|
||||
memcpy(position, state.logical_position, sizeof(position));
|
||||
}
|
||||
*status_code = state.status_code;
|
||||
*inches_mode = state.inches_mode;
|
||||
*line_number = state.line_number;
|
||||
}
|
||||
|
||||
// Parses the next statement and leaves the counter on the first character following
|
||||
// the statement. Returns 1 if there was a statements, 0 if end of string was reached
|
||||
// or there was an error (check state.status_code).
|
||||
int next_statement(char *letter, double *double_ptr, char *line, int *counter) {
|
||||
if (*line == 0) {
|
||||
return(0); // No more statements
|
||||
}
|
||||
|
||||
*letter = *line;
|
||||
if((*letter < 'A') || (*letter > 'Z')) {
|
||||
FAIL(GCSTATUS_EXPECTED_COMMAND_LETTER);
|
||||
return(0);
|
||||
}
|
||||
*counter++;
|
||||
if (!read_double(line, counter, double_ptr)) {
|
||||
return(0);
|
||||
};
|
||||
return(1);
|
||||
}
|
||||
|
||||
int read_double(char *line, //!< string: line of RS274/NGC code being processed
|
||||
int *counter, //!< pointer to a counter for position on the line
|
||||
double *double_ptr) //!< pointer to double to be read
|
||||
{
|
||||
char *start = line + *counter;
|
||||
char *end;
|
||||
|
||||
*double_ptr = strtod(start, &end);
|
||||
if(end == start) {
|
||||
FAIL(GCSTATUS_BAD_NUMBER_FORMAT);
|
||||
return(0);
|
||||
};
|
||||
|
||||
*counter = end - line;
|
||||
return(1);
|
||||
}
|
||||
|
41
gcode.h
Normal file
41
gcode.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
gcode.c - rs274/ngc parser.
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef gcode_h
|
||||
#define gcode_h
|
||||
#include <avr/io.h>
|
||||
|
||||
#define GCSTATUS_OK 0
|
||||
#define GCSTATUS_BAD_NUMBER_FORMAT 1
|
||||
#define GCSTATUS_EXPECTED_COMMAND_LETTER 2
|
||||
#define GCSTATUS_UNSUPPORTED_STATEMENT 3
|
||||
#define GCSTATUS_MOTION_CONTROL_ERROR 4
|
||||
|
||||
// Initialize the parser
|
||||
void gc_init();
|
||||
|
||||
// Execute one block of rs275/ngc/g-code
|
||||
uint8_t gc_execute_line(char *line);
|
||||
|
||||
// get the current logical position (in current units), the current status code and the unit mode
|
||||
void gc_get_status(double *position, uint8_t *status_code, int *inches_mode, uint32_t *line_number);
|
||||
|
||||
#endif
|
41
main.c
Normal file
41
main.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
main.c - An embedded CNC Controller with rs274/ngc (g-code) support
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/sleep.h>
|
||||
#include "motion_control.h"
|
||||
#include "gcode.h"
|
||||
#include "spindle_control.h"
|
||||
#include "serial_protocol.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
mc_init(); // initialize motion control subsystem
|
||||
gc_init(); // initialize gcode-parser
|
||||
spindle_init(); // initialize spindle controller
|
||||
sp_init(); // initialize the serial protocol
|
||||
|
||||
gc_execute_line("123.1");
|
||||
for(;;){
|
||||
sleep_mode();
|
||||
sp_process(); // process the serial protocol
|
||||
}
|
||||
return 0; /* never reached */
|
||||
}
|
338
motion_control.c
Normal file
338
motion_control.c
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
motion_control.c - cartesian robot controller.
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This code was inspired by the Arduino GCode_Interpreter by Mike Ellery. */
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "config.h"
|
||||
#include "motion_control.h"
|
||||
#include <util/delay.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "nuts_bolts.h"
|
||||
|
||||
// position represents the current position of the head measured in steps
|
||||
// target is the target for the current linear motion
|
||||
// step_count contains the absolute values of the steps to travel along each axis
|
||||
// direction is the sign of the motion for each axis (-1: reverse, 0: standby, 1: forward)
|
||||
|
||||
#define MODE_AT_REST 0
|
||||
#define MODE_LINEAR 1
|
||||
#define MODE_ARC 2
|
||||
#define MODE_DWELL 3
|
||||
#define MODE_HOME 4
|
||||
#define MODE_LIMIT_OVERRUN -1
|
||||
|
||||
#define PHASE_HOME_RETURN 0
|
||||
#define PHASE_HOME_NUDGE 1
|
||||
|
||||
#define ONE_MINUTE_OF_MICROSECONDS 60000000
|
||||
|
||||
// Parameters when mode is MODE_ARC
|
||||
struct LinearMotionParameters {
|
||||
int8_t direction[3]; // The direction of travel along each axis (-1, 0 or 1)
|
||||
uint16_t feed_rate;
|
||||
int32_t target[3], // The target position in absolute steps
|
||||
step_count[3], // Absolute steps of travel along each axis
|
||||
counter[3], // A counter used in the bresenham algorithm for line plotting
|
||||
maximum_steps; // The larges absolute step-count of any axis
|
||||
};
|
||||
|
||||
// Parameters when mode is MODE_LINEAR
|
||||
struct ArcMotionParameters {
|
||||
uint32_t radius;
|
||||
int16_t degrees;
|
||||
int ccw;
|
||||
};
|
||||
|
||||
struct HomeCycleParameters {
|
||||
int8_t direction[3]; // The direction of travel along each axis (-1, 0 or 1)
|
||||
int8_t phase; // current phase of the home cycle.
|
||||
int8_t away[3]; // a vector of booleans. True for each axis that is still away.
|
||||
};
|
||||
|
||||
/* The whole state of the motion-control-system in one struct. Makes the code a little bit hard to
|
||||
read, but lets us initialize the state of the system by just clearing a single, contigous block of memory.
|
||||
By overlaying the variables of the different modes in a union we save a few bytes of precious SRAM.
|
||||
*/
|
||||
struct MotionControlState {
|
||||
int8_t mode; // The current operation mode
|
||||
int32_t position[3]; // The current position of the tool in absolute steps
|
||||
int32_t update_delay_us; // Microseconds between each update in the current mode
|
||||
union {
|
||||
struct LinearMotionParameters linear; // variables used in MODE_LINEAR
|
||||
struct ArcMotionParameters arc; // variables used in MODE_ARC
|
||||
struct HomeCycleParameters home; // variables used in MODE_HOME
|
||||
uint32_t dwell_milliseconds; // variable used in MODE_DWELL
|
||||
int8_t limit_overrun_direction[3]; // variable used in MODE_LIMIT_OVERRUN
|
||||
};
|
||||
};
|
||||
struct MotionControlState state;
|
||||
|
||||
int check_limit_switches();
|
||||
void enable_steppers();
|
||||
void disable_steppers();
|
||||
void set_direction_pins(int8_t *direction);
|
||||
inline void step_steppers(uint8_t *enabled);
|
||||
void limit_overrun(uint8_t *direction);
|
||||
int check_limit_switch(int axis);
|
||||
inline void step_axis(uint8_t axis);
|
||||
|
||||
void mc_init()
|
||||
{
|
||||
// Initialize state variables
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
||||
// Configure directions of interface pins
|
||||
STEP_DDR |= STEP_MASK;
|
||||
DIRECTION_DDR |= DIRECTION_MASK;
|
||||
LIMIT_DDR &= ~(LIMIT_MASK);
|
||||
STEPPERS_ENABLE_DDR |= 1<<STEPPERS_ENABLE_BIT;
|
||||
|
||||
disable_steppers();
|
||||
}
|
||||
|
||||
void limit_overrun(uint8_t *direction)
|
||||
{
|
||||
state.mode = MODE_LIMIT_OVERRUN;
|
||||
memcpy(state.limit_overrun_direction, direction, sizeof(state.limit_overrun_direction));
|
||||
}
|
||||
|
||||
void mc_dwell(uint32_t milliseconds)
|
||||
{
|
||||
mc_wait();
|
||||
state.mode = MODE_DWELL;
|
||||
state.dwell_milliseconds = milliseconds;
|
||||
state.update_delay_us = 1000;
|
||||
}
|
||||
|
||||
void mc_linear_motion(double x, double y, double z, float feed_rate, int invert_feed_rate)
|
||||
{
|
||||
mc_wait();
|
||||
state.mode = MODE_LINEAR;
|
||||
|
||||
state.linear.target[X_AXIS] = trunc(x*X_STEPS_PER_MM);
|
||||
state.linear.target[Y_AXIS] = trunc(y*Y_STEPS_PER_MM);
|
||||
state.linear.target[Z_AXIS] = trunc(z*Z_STEPS_PER_MM);
|
||||
|
||||
uint8_t axis; // loop variable
|
||||
|
||||
// Determine direction and travel magnitude for each axis
|
||||
for(axis = X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
state.linear.step_count[axis] = abs(state.linear.target[axis] - state.position[axis]);
|
||||
state.linear.direction[axis] = sign(state.linear.step_count[axis]);
|
||||
}
|
||||
// Find the magnitude of the axis with the longest travel
|
||||
state.linear.maximum_steps = max(state.linear.step_count[Z_AXIS],
|
||||
max(state.linear.step_count[X_AXIS], state.linear.step_count[Y_AXIS]));
|
||||
|
||||
// Set up a neat counter for each axis
|
||||
for(axis = X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
state.linear.counter[axis] = -state.linear.maximum_steps/2;
|
||||
}
|
||||
|
||||
// Set our direction pins
|
||||
set_direction_pins(state.linear.direction);
|
||||
|
||||
// Calculate the microseconds we need to wait between each step to achieve the desired feed rate
|
||||
if (invert_feed_rate) {
|
||||
state.update_delay_us =
|
||||
(feed_rate*1000000.0)/state.linear.maximum_steps;
|
||||
} else {
|
||||
// Ask old Phytagoras how many millimeters our next move is going to take us:
|
||||
float millimeters_of_travel =
|
||||
sqrt(pow((X_STEPS_PER_MM*state.linear.step_count[X_AXIS]),2) +
|
||||
pow((Y_STEPS_PER_MM*state.linear.step_count[Y_AXIS]),2) +
|
||||
pow((Z_STEPS_PER_MM*state.linear.step_count[Z_AXIS]),2));
|
||||
state.update_delay_us =
|
||||
((millimeters_of_travel * ONE_MINUTE_OF_MICROSECONDS) / feed_rate) / state.linear.maximum_steps;
|
||||
}
|
||||
}
|
||||
|
||||
void perform_linear_motion()
|
||||
{
|
||||
// Flags to keep track of which axes to step
|
||||
uint8_t step[3];
|
||||
uint8_t axis; // loop variable
|
||||
|
||||
// Trace the line
|
||||
clear_vector(step);
|
||||
for(axis = X_AXIS; axis <= Z_AXIS; axis++) {
|
||||
if (state.linear.target[axis] != state.position[axis])
|
||||
{
|
||||
state.linear.counter[axis] += state.linear.step_count[axis];
|
||||
if (state.linear.counter[axis] > 0)
|
||||
{
|
||||
step[axis] = true;
|
||||
state.linear.counter[axis] -= state.linear.maximum_steps;
|
||||
state.position[axis] += state.linear.direction[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (step[X_AXIS] | step[Y_AXIS] | step[Z_AXIS]) {
|
||||
step_steppers(step);
|
||||
|
||||
// If we trip any limit switch while moving: Abort, abort!
|
||||
if (check_limit_switches()) {
|
||||
limit_overrun(state.linear.direction);
|
||||
}
|
||||
|
||||
_delay_us(state.update_delay_us);
|
||||
} else {
|
||||
state.mode = MODE_AT_REST;
|
||||
}
|
||||
}
|
||||
|
||||
void mc_go_home()
|
||||
{
|
||||
state.mode = MODE_HOME;
|
||||
memset(state.home.direction, -1, sizeof(state.home.direction)); // direction = [-1,-1,-1]
|
||||
set_direction_pins(state.home.direction);
|
||||
clear_vector(state.home.away);
|
||||
}
|
||||
|
||||
void perform_go_home()
|
||||
{
|
||||
int axis;
|
||||
if(state.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++) {
|
||||
state.home.away[axis] |= check_limit_switch(axis);
|
||||
}
|
||||
// Step steppers. First retract along Z-axis. Then X and Y.
|
||||
if(state.home.away[Z_AXIS]) {
|
||||
step_axis(Z_AXIS);
|
||||
} else {
|
||||
// Check if all axes are home
|
||||
if(!(state.home.away[X_AXIS] || state.home.away[Y_AXIS])) {
|
||||
// All axes are home, prepare next phase: to nudge the tool carefully out of the limit switches
|
||||
memset(state.home.direction, 1, sizeof(state.home.direction)); // direction = [1,1,1]
|
||||
set_direction_pins(state.home.direction);
|
||||
state.home.phase == PHASE_HOME_NUDGE;
|
||||
return;
|
||||
}
|
||||
step_steppers(state.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(state.position); // By definition this is location [0, 0, 0]
|
||||
state.mode = MODE_AT_REST;
|
||||
}
|
||||
}
|
||||
|
||||
void mc_execute() {
|
||||
enable_steppers();
|
||||
while(state.mode) {
|
||||
switch(state.mode) {
|
||||
case MODE_AT_REST: break;
|
||||
case MODE_DWELL: _delay_ms(state.dwell_milliseconds); state.mode = MODE_AT_REST; break;
|
||||
case MODE_LINEAR: perform_linear_motion();
|
||||
case MODE_HOME: perform_go_home();
|
||||
}
|
||||
_delay_us(state.update_delay_us);
|
||||
}
|
||||
disable_steppers();
|
||||
}
|
||||
|
||||
void mc_wait() {
|
||||
return; // No concurrency support yet. So waiting for all to pass is moot.
|
||||
}
|
||||
|
||||
int mc_status()
|
||||
{
|
||||
return(state.mode);
|
||||
}
|
||||
|
||||
int check_limit_switches()
|
||||
{
|
||||
// Dual read as crude debounce
|
||||
return((LIMIT_PORT & LIMIT_MASK) | (LIMIT_PORT & LIMIT_MASK));
|
||||
}
|
||||
|
||||
int check_limit_switch(int axis)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
switch (axis) {
|
||||
case X_AXIS: mask = 1<<X_LIMIT_BIT; break;
|
||||
case Y_AXIS: mask = 1<<Y_LIMIT_BIT; break;
|
||||
case Z_AXIS: mask = 1<<Z_LIMIT_BIT; break;
|
||||
}
|
||||
return((LIMIT_PORT&mask) || (LIMIT_PORT&mask));
|
||||
}
|
||||
|
||||
void enable_steppers()
|
||||
{
|
||||
STEPPERS_ENABLE_PORT |= 1<<STEPPERS_ENABLE_BIT;
|
||||
}
|
||||
|
||||
void disable_steppers()
|
||||
{
|
||||
STEPPERS_ENABLE_PORT &= ~(1<<STEPPERS_ENABLE_BIT);
|
||||
}
|
||||
|
||||
// Set the direction pins for the stepper motors according to the provided vector.
|
||||
// direction is an array of three 8 bit integers representing the direction of
|
||||
// each motor. The values should be -1 (reverse), 0 or 1 (forward).
|
||||
void set_direction_pins(int8_t *direction)
|
||||
{
|
||||
/* Sorry about this convoluted code! It uses the fact that bit 7 of each direction
|
||||
int is set when the direction == -1, but is 0 when direction is forward. This
|
||||
way we can generate the whole direction bit-mask without doing any comparisions
|
||||
or branching. Fast and compact, yet practically unreadable. Sorry sorry sorry.
|
||||
*/
|
||||
uint8_t forward_bits = ~(
|
||||
((direction[X_AXIS]&128)>>(7-X_DIRECTION_BIT)) |
|
||||
((direction[Y_AXIS]&128)>>(7-Y_DIRECTION_BIT)) |
|
||||
((direction[Z_AXIS]&128)>>(7-Z_DIRECTION_BIT))
|
||||
);
|
||||
DIRECTION_PORT = DIRECTION_PORT & ~(DIRECTION_MASK) | forward_bits;
|
||||
}
|
||||
|
||||
// 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 *enabled)
|
||||
{
|
||||
STEP_PORT |= enabled[X_AXIS]<<X_STEP_BIT | enabled[Y_AXIS]<<Y_STEP_BIT | enabled[Z_AXIS]<<Z_STEP_BIT;
|
||||
_delay_us(5);
|
||||
STEP_PORT &= ~STEP_MASK;
|
||||
}
|
||||
|
||||
// Step only one motor
|
||||
inline void step_axis(uint8_t axis)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
switch (axis) {
|
||||
case X_AXIS: mask = 1<<X_STEP_BIT; break;
|
||||
case Y_AXIS: mask = 1<<Y_STEP_BIT; break;
|
||||
case Z_AXIS: mask = 1<<Z_STEP_BIT; break;
|
||||
}
|
||||
STEP_PORT &= mask;
|
||||
_delay_us(5);
|
||||
STEP_PORT &= ~STEP_MASK;
|
||||
}
|
49
motion_control.h
Normal file
49
motion_control.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
motion_control.h - cartesian robot controller.
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef motion_control_h
|
||||
#define motion_control_h
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
/* All coordinates are in step-counts. */
|
||||
|
||||
// Initializes the motion_control subsystem resources
|
||||
void mc_init();
|
||||
|
||||
// Prepare for linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
|
||||
// unless invert_feed_rate is true. Then the feed_rate states the number of seconds for the whole movement.
|
||||
void mc_linear_motion(double x, double y, double z, float feed_rate, int invert_feed_rate);
|
||||
// Prepare linear motion relative to the current position.
|
||||
void mc_dwell(uint32_t milliseconds);
|
||||
// Prepare to send the tool position home
|
||||
void mc_go_home();
|
||||
// Start the prepared operation.
|
||||
void mc_execute();
|
||||
|
||||
// Block until the motion control system is idle
|
||||
void mc_wait();
|
||||
|
||||
|
||||
// Check motion control status. result == 0: the system is idle. result > 0: the system is busy,
|
||||
// result < 0: the system is in an error state.
|
||||
int mc_status();
|
||||
|
||||
#endif
|
41
nuts_bolts.h
Normal file
41
nuts_bolts.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
motion_control.h - cartesian robot controller.
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef nuts_bolts_h
|
||||
#define nuts_bolts_h
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
// Decide the sign of a value
|
||||
#define sign(a) (a>0 ? 1 : ((a<0) ? -1 : 0))
|
||||
|
||||
#define clear_vector(a) memset(a, 0, sizeof(a))
|
||||
|
||||
#define X_AXIS 0
|
||||
#define Y_AXIS 1
|
||||
#define Z_AXIS 2
|
||||
|
||||
#endif
|
15
readme.txt
Normal file
15
readme.txt
Normal file
@ -0,0 +1,15 @@
|
||||
Grbl - An embedded rs274/ngc (g-code) interpreter, cartesian bot controller, readout and exerciser
|
||||
Inspired by the Arduino GCode Interpreter by Mike Ellery
|
||||
|
||||
Goals:
|
||||
* Suitable for both milling and deposition fabrication
|
||||
* Support GCode from common free and cheap CAM-packages right out of the box
|
||||
* Optional support for a alphanumeric LCD readout, a joystick and a few buttons for program control
|
||||
* Optional support for automated cutter length calibration when milling
|
||||
* Support "headless" fabrication by buffering all code to SD-card or similar
|
||||
|
||||
Limitations:
|
||||
* No support for Arduino software (but will run fine on an Arduino board if you program it with an ISP)
|
||||
* Limited GCode-support. Focus on the kind of GCode produced by automated CAM tools. Leave human GCoders frustrated.
|
||||
|
||||
|
89
serial_protocol.c
Normal file
89
serial_protocol.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
serial_protocol.c - the serial protocol master control unit
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "serial_protocol.h"
|
||||
#include "gcode.h"
|
||||
#include "wiring_serial.h"
|
||||
#include "config.h"
|
||||
#include <math.h>
|
||||
#include "nuts_bolts.h"
|
||||
|
||||
#define BLOCK_BUFFER_SIZE 128
|
||||
|
||||
char line[BLOCK_BUFFER_SIZE];
|
||||
uint8_t line_counter;
|
||||
|
||||
void prompt() {
|
||||
printString(PROMPT);
|
||||
}
|
||||
|
||||
void print_result() {
|
||||
double position[3];
|
||||
int inches_mode;
|
||||
uint8_t status_code;
|
||||
uint32_t line_number;
|
||||
gc_get_status(position, &status_code, &inches_mode, &line_number);
|
||||
printByte('[');
|
||||
printInteger(trunc(position[X_AXIS]*100));
|
||||
printByte(',');
|
||||
printInteger(trunc(position[Y_AXIS]*100));
|
||||
printByte(',');
|
||||
printInteger(trunc(position[Z_AXIS]*100));
|
||||
printByte(']');
|
||||
printByte(' ');
|
||||
printByte('@');
|
||||
printInteger(line_number);
|
||||
printByte(':');
|
||||
switch(status_code) {
|
||||
case GCSTATUS_OK: printString("0 OK\n"); break;
|
||||
case GCSTATUS_BAD_NUMBER_FORMAT: printString("1 Bad number format\n");
|
||||
case GCSTATUS_EXPECTED_COMMAND_LETTER: printString("2 Expected command letter\n"); break;
|
||||
case GCSTATUS_UNSUPPORTED_STATEMENT: printString("3 Unsupported statement\n"); break;
|
||||
case GCSTATUS_MOTION_CONTROL_ERROR: printString("4 Motion control error\n"); break;
|
||||
}
|
||||
}
|
||||
|
||||
void sp_init()
|
||||
{
|
||||
beginSerial(BAUD_RATE);
|
||||
|
||||
printString("Grbl ");
|
||||
printString(VERSION);
|
||||
printByte('\n');
|
||||
prompt();
|
||||
}
|
||||
|
||||
void sp_process()
|
||||
{
|
||||
char c;
|
||||
while((c = serialRead()) != -1)
|
||||
{
|
||||
if(c == '\n') {
|
||||
line[line_counter] = 0;
|
||||
gc_execute_line(line);
|
||||
line_counter = 0;
|
||||
print_result();
|
||||
prompt();
|
||||
} else {
|
||||
line[line_counter] = c;
|
||||
}
|
||||
}
|
||||
}
|
28
serial_protocol.h
Normal file
28
serial_protocol.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
serial_protocol.h - the serial protocol master control unit
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef serial_h
|
||||
#define serial_h
|
||||
|
||||
#define PROMPT ">>>"
|
||||
|
||||
void sp_init();
|
||||
void sp_process();
|
||||
|
||||
#endif
|
44
spindle_control.c
Normal file
44
spindle_control.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
spindle_control.c - spindle control methods
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "spindle_control.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
void spindle_init()
|
||||
{
|
||||
SPINDLE_ENABLE_DDR |= 1<<SPINDLE_ENABLE_BIT;
|
||||
}
|
||||
|
||||
void spindle_run(int direction, uint32_t rpm)
|
||||
{
|
||||
if(direction >= 0) {
|
||||
SPINDLE_DIRECTION_PORT &= ~(1<<SPINDLE_DIRECTION_BIT);
|
||||
} else {
|
||||
SPINDLE_DIRECTION_PORT |= 1<<SPINDLE_DIRECTION_BIT;
|
||||
}
|
||||
SPINDLE_ENABLE_PORT |= 1<<SPINDLE_ENABLE_BIT;
|
||||
}
|
||||
|
||||
void spindle_stop()
|
||||
{
|
||||
SPINDLE_ENABLE_PORT &= ~(1<<SPINDLE_ENABLE_BIT);
|
||||
}
|
30
spindle_control.h
Normal file
30
spindle_control.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
spindle_control.h - spindle control methods
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009 Simen Svale Skogsrud
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef spindle_control_h
|
||||
#define spindle_control_h
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
void spindle_init();
|
||||
void spindle_run(int direction, uint32_t rpm);
|
||||
void spindle_stop();
|
||||
|
||||
#endif
|
7
todo.txt
Normal file
7
todo.txt
Normal file
@ -0,0 +1,7 @@
|
||||
* Use timer interrupts to drive steppers
|
||||
* Tool table
|
||||
* Tool length offsets
|
||||
* Tool change M6
|
||||
* Coolant control
|
||||
* Path Control Modes
|
||||
* Spindle speed support
|
56
wiring_private.h
Normal file
56
wiring_private.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
wiring_private.h - Internal header file.
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2005-2006 David A. Mellis
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
|
||||
*/
|
||||
|
||||
#ifndef WiringPrivate_h
|
||||
#define WiringPrivate_h
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif
|
||||
#ifndef sbi
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
#define EXTERNAL_INT_0 0
|
||||
#define EXTERNAL_INT_1 1
|
||||
|
||||
#define EXTERNAL_NUM_INTERRUPTS 2
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
212
wiring_serial.c
Normal file
212
wiring_serial.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
wiring_serial.c - serial functions.
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2005-2006 David A. Mellis
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||
*/
|
||||
|
||||
#include "wiring_private.h"
|
||||
|
||||
// Define constants and variables for buffering incoming serial data. We're
|
||||
// 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
|
||||
|
||||
unsigned char rx_buffer[RX_BUFFER_SIZE];
|
||||
|
||||
int rx_buffer_head = 0;
|
||||
int rx_buffer_tail = 0;
|
||||
|
||||
void beginSerial(long baud)
|
||||
{
|
||||
#if defined(__AVR_ATmega168__)
|
||||
UBRR0H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8;
|
||||
UBRR0L = ((F_CPU / 16 + baud / 2) / baud - 1);
|
||||
|
||||
// enable rx and tx
|
||||
sbi(UCSR0B, RXEN0);
|
||||
sbi(UCSR0B, TXEN0);
|
||||
|
||||
// enable interrupt on complete reception of a byte
|
||||
sbi(UCSR0B, RXCIE0);
|
||||
#else
|
||||
UBRRH = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8;
|
||||
UBRRL = ((F_CPU / 16 + baud / 2) / baud - 1);
|
||||
|
||||
// enable rx and tx
|
||||
sbi(UCSRB, RXEN);
|
||||
sbi(UCSRB, TXEN);
|
||||
|
||||
// enable interrupt on complete reception of a byte
|
||||
sbi(UCSRB, RXCIE);
|
||||
#endif
|
||||
|
||||
// defaults to 8-bit, no parity, 1 stop bit
|
||||
}
|
||||
|
||||
void serialWrite(unsigned char c)
|
||||
{
|
||||
#if defined(__AVR_ATmega168__)
|
||||
while (!(UCSR0A & (1 << UDRE0)))
|
||||
;
|
||||
|
||||
UDR0 = c;
|
||||
#else
|
||||
while (!(UCSRA & (1 << UDRE)))
|
||||
;
|
||||
|
||||
UDR = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
int serialAvailable()
|
||||
{
|
||||
return (RX_BUFFER_SIZE + rx_buffer_head - rx_buffer_tail) % RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
int serialRead()
|
||||
{
|
||||
// if the head isn't ahead of the tail, we don't have any characters
|
||||
if (rx_buffer_head == rx_buffer_tail) {
|
||||
return -1;
|
||||
} else {
|
||||
unsigned char c = rx_buffer[rx_buffer_tail];
|
||||
rx_buffer_tail = (rx_buffer_tail + 1) % RX_BUFFER_SIZE;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
void serialFlush()
|
||||
{
|
||||
// don't reverse this or there may be problems if the RX interrupt
|
||||
// occurs after reading the value of rx_buffer_head but before writing
|
||||
// the value to rx_buffer_tail; the previous value of rx_buffer_head
|
||||
// may be written to rx_buffer_tail, making it appear as if the buffer
|
||||
// were full, not empty.
|
||||
rx_buffer_head = rx_buffer_tail;
|
||||
}
|
||||
|
||||
#if defined(__AVR_ATmega168__)
|
||||
SIGNAL(SIG_USART_RECV)
|
||||
#else
|
||||
SIGNAL(SIG_UART_RECV)
|
||||
#endif
|
||||
{
|
||||
#if defined(__AVR_ATmega168__)
|
||||
unsigned char c = UDR0;
|
||||
#else
|
||||
unsigned char c = UDR;
|
||||
#endif
|
||||
|
||||
int i = (rx_buffer_head + 1) % RX_BUFFER_SIZE;
|
||||
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
if (i != rx_buffer_tail) {
|
||||
rx_buffer[rx_buffer_head] = c;
|
||||
rx_buffer_head = i;
|
||||
}
|
||||
}
|
||||
|
||||
void printMode(int mode)
|
||||
{
|
||||
// do nothing, we only support serial printing, not lcd.
|
||||
}
|
||||
|
||||
void printByte(unsigned char c)
|
||||
{
|
||||
serialWrite(c);
|
||||
}
|
||||
|
||||
void printNewline()
|
||||
{
|
||||
printByte('\n');
|
||||
}
|
||||
|
||||
void printString(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
printByte(*s++);
|
||||
}
|
||||
|
||||
void printIntegerInBase(unsigned long n, unsigned long base)
|
||||
{
|
||||
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||
unsigned long i = 0;
|
||||
|
||||
if (n == 0) {
|
||||
printByte('0');
|
||||
return;
|
||||
}
|
||||
|
||||
while (n > 0) {
|
||||
buf[i++] = n % base;
|
||||
n /= base;
|
||||
}
|
||||
|
||||
for (; i > 0; i--)
|
||||
printByte(buf[i - 1] < 10 ?
|
||||
'0' + buf[i - 1] :
|
||||
'A' + buf[i - 1] - 10);
|
||||
}
|
||||
|
||||
void printInteger(long n)
|
||||
{
|
||||
if (n < 0) {
|
||||
printByte('-');
|
||||
n = -n;
|
||||
}
|
||||
|
||||
printIntegerInBase(n, 10);
|
||||
}
|
||||
|
||||
void printHex(unsigned long n)
|
||||
{
|
||||
printIntegerInBase(n, 16);
|
||||
}
|
||||
|
||||
void printOctal(unsigned long n)
|
||||
{
|
||||
printIntegerInBase(n, 8);
|
||||
}
|
||||
|
||||
void printBinary(unsigned long n)
|
||||
{
|
||||
printIntegerInBase(n, 2);
|
||||
}
|
||||
|
||||
/* Including print() adds approximately 1500 bytes to the binary size,
|
||||
* so we replace it with the smaller and less-confusing printString(),
|
||||
* printInteger(), etc.
|
||||
void print(const char *format, ...)
|
||||
{
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buf, 256, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
printString(buf);
|
||||
}
|
||||
*/
|
43
wiring_serial.h
Normal file
43
wiring_serial.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Based on wiring.h - Partial implementation of the Wiring API for the ATmega8.
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2005-2006 David A. Mellis
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: wiring.h 387 2008-03-08 21:30:00Z mellis $
|
||||
*/
|
||||
|
||||
#ifndef wiring_h
|
||||
#define wiring_h
|
||||
|
||||
void beginSerial(long);
|
||||
void serialWrite(unsigned char);
|
||||
int serialAvailable(void);
|
||||
int serialRead(void);
|
||||
void serialFlush(void);
|
||||
void printMode(int);
|
||||
void printByte(unsigned char c);
|
||||
void printNewline(void);
|
||||
void printString(const char *s);
|
||||
void printInteger(long n);
|
||||
void printHex(unsigned long n);
|
||||
void printOctal(unsigned long n);
|
||||
void printBinary(unsigned long n);
|
||||
void printIntegerInBase(unsigned long n, unsigned long base);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user