Skip to content

Commit

Permalink
Merge pull request #347 from bdring/Devt
Browse files Browse the repository at this point in the history
Devt
  • Loading branch information
bdring authored Mar 22, 2022
2 parents 911c52e + e8cf687 commit adfc015
Show file tree
Hide file tree
Showing 36 changed files with 537 additions and 112 deletions.
22 changes: 1 addition & 21 deletions FluidNC/src/Configuration/ParseException.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,15 @@
namespace Configuration {
class ParseException {
int line_;
int column_;
const char* keyStart_;
const char* keyEnd_;
const char* description_;
const char* current_;

public:
ParseException() = default;
ParseException(const ParseException&) = default;

ParseException(const char* start, const char* current, const char* description) :
keyStart_(start), keyEnd_(current), description_(description), current_(current) {
line_ = 1;
column_ = 1;
while (start != current) {
if (*start == '\n') {
++line_;
column_ = 1;
}
++column_;
++start;
}
}
ParseException(int line, const char* description) : line_(line), description_(description) {}

inline int LineNumber() const { return line_; }
inline int ColumnNumber() const { return column_; }
inline const char* Near() const { return current_; }
inline const char* What() const { return description_; }
inline const char* KeyStart() const { return keyStart_; }
inline const char* KeyEnd() const { return keyEnd_; }
};
}
2 changes: 1 addition & 1 deletion FluidNC/src/Configuration/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Configuration {
void Parser::parseError(const char* description) const {
// Attempt to use the correct position in the parser:
if (token_.keyEnd_) {
throw ParseException(token_.keyStart_, token_.keyEnd_, description);
throw ParseException(line_, description);
} else {
Tokenizer::ParseError(description);
}
Expand Down
4 changes: 2 additions & 2 deletions FluidNC/src/Configuration/ParserHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ namespace Configuration {
void item(const char* name, int32_t& value, int32_t minValue, int32_t maxValue) override {
if (_parser.is(name)) {
value = _parser.intValue();
constrain_with_message(value, minValue, maxValue);
constrain_with_message(value, minValue, maxValue, name);
}
}

Expand All @@ -121,7 +121,7 @@ namespace Configuration {
void item(const char* name, float& value, float minValue, float maxValue) override {
if (_parser.is(name)) {
value = _parser.floatValue();
constrain_with_message(value, minValue, maxValue);
constrain_with_message(value, minValue, maxValue, name);
}
}

Expand Down
20 changes: 7 additions & 13 deletions FluidNC/src/Configuration/Tokenizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,12 @@ namespace Configuration {
while (!IsEndLine()) {
Inc();
}
Inc();
}

Tokenizer::Tokenizer(const char* start, const char* end) : current_(start), end_(end), start_(start), token_() {
// If start is a yaml document start ('---' [newline]), skip that first.
if (EqualsCaseInsensitive("---")) {
for (int i = 0; i < 3; ++i) {
Inc();
}
skipToEol();
start_ = current_;
}
}
Tokenizer::Tokenizer(const char* start, const char* end) : current_(start), end_(end), start_(start), line_(0), token_() {}

void Tokenizer::ParseError(const char* description) const { throw ParseException(start_, current_, description); }
void Tokenizer::ParseError(const char* description) const { throw ParseException(line_, description); }

void Tokenizer::Tokenize() {
// Release a held token
Expand All @@ -44,6 +36,8 @@ namespace Configuration {
// is at the start of the line.

parseAgain:
++line_;

int indent = 0;

while (!Eof() && IsSpace()) {
Expand All @@ -60,7 +54,7 @@ namespace Configuration {
}
switch (Current()) {
case '\t':
ParseError("Tabs are not allowed. Use spaces for indentation.");
ParseError("Use spaces, not tabs, for indentation");
break;

case '#': // Comment till end of line
Expand All @@ -83,7 +77,7 @@ namespace Configuration {

default:
if (!IsIdentifierChar()) {
ParseError("Expected identifier.");
ParseError("Invalid character");
}

token_.keyStart_ = current_;
Expand Down
1 change: 1 addition & 0 deletions FluidNC/src/Configuration/Tokenizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ namespace Configuration {

public:
const char* start_;
int line_;

// Results:
struct TokenData {
Expand Down
2 changes: 1 addition & 1 deletion FluidNC/src/CoolantControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,5 @@ void CoolantControl::off() {
void CoolantControl::group(Configuration::HandlerBase& handler) {
handler.item("flood_pin", _flood);
handler.item("mist_pin", _mist);
handler.item("delay_ms", _delay_ms);
handler.item("delay_ms", _delay_ms, 0, 10000);
}
4 changes: 2 additions & 2 deletions FluidNC/src/FileStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ FileStream::FileStream(const char* filename, const char* mode, const char* defau
}
if (_path.startsWith(sdPrefix)) {
if (config->_sdCard->begin(SDCard::State::BusyWriting) != SDCard::State::Idle) {
log_info("FS busy ");
log_info("FS busy");
throw Error::FsFailedMount;
}
_isSD = true;
}
if (_path.startsWith(actualLocalFs) && _path.length() > (30 + strlen(actualLocalFs))) {
log_info("Filename too long");
log_info("Filename too long: " << _path);
}
_fd = fopen(_path.c_str(), mode);
if (!_fd) {
Expand Down
11 changes: 10 additions & 1 deletion FluidNC/src/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,15 @@ Error gc_execute_line(char* line, Channel& channel) {
// is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning
// an error, it issues an alarm to prevent further motion to the probe. It's also done there to
// allow the planner buffer to empty and move off the probe trigger before another probing cycle.
if (bitnum_is_true(value_words, GCodeWord::P)) {
if (multiple_bits_set(axis_words)) { // There should only be one axis word given
FAIL(Error::GcodeUnusedWords); // we have more axis words than allowed.
}
} else {
gc_block.values.p = __FLT_MAX__; // This is a hack to signal the probe cycle that not to auto offset.
}
clear_bitnum(value_words, GCodeWord::P); // allow P to be used

if (!axis_words) {
FAIL(Error::GcodeNoAxisWords); // [No axis words]
}
Expand Down Expand Up @@ -1575,7 +1584,7 @@ Error gc_execute_line(char* line, Channel& channel) {
if (!ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES) {
pl_data->motion.noFeedOverride = 1;
}
gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags);
gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags, axis_words, gc_block.values.p);
}
// As far as the parser is concerned, the position is now == target. In reality the
// motion control system might still be processing the action and the real tool position
Expand Down
8 changes: 4 additions & 4 deletions FluidNC/src/Machine/Axis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

namespace Machine {
void Axis::group(Configuration::HandlerBase& handler) {
handler.item("steps_per_mm", _stepsPerMm);
handler.item("max_rate_mm_per_min", _maxRate);
handler.item("acceleration_mm_per_sec2", _acceleration);
handler.item("max_travel_mm", _maxTravel);
handler.item("steps_per_mm", _stepsPerMm, 0.001, 100000.0);
handler.item("max_rate_mm_per_min", _maxRate, 0.001, 100000.0);
handler.item("acceleration_mm_per_sec2", _acceleration, 0.001, 100000.0);
handler.item("max_travel_mm", _maxTravel, 0.1, 10000000.0);
handler.item("soft_limits", _softLimits);
handler.section("homing", _homing);

Expand Down
12 changes: 6 additions & 6 deletions FluidNC/src/Machine/Homing.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ namespace Machine {
void validate() const override { Assert(_cycle >= 0, "Homing cycle must be defined"); }

void group(Configuration::HandlerBase& handler) override {
handler.item("cycle", _cycle);
handler.item("cycle", _cycle, -1, 6);
handler.item("allow_single_axis", _allow_single_axis);
handler.item("positive_direction", _positiveDirection);
handler.item("mpos_mm", _mpos);
handler.item("feed_mm_per_min", _feedRate);
handler.item("seek_mm_per_min", _seekRate);
handler.item("settle_ms", _settle_ms);
handler.item("seek_scaler", _seek_scaler);
handler.item("feed_scaler", _feed_scaler);
handler.item("feed_mm_per_min", _feedRate, 1.0, 100000.0);
handler.item("seek_mm_per_min", _seekRate, 1.0, 100000.0);
handler.item("settle_ms", _settle_ms, 0, 1000);
handler.item("seek_scaler", _seek_scaler, 1.0, 100.0);
handler.item("feed_scaler", _feed_scaler, 1.0, 100.0);
}

void init() {}
Expand Down
3 changes: 2 additions & 1 deletion FluidNC/src/Machine/MachineConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace Machine {
handler.item("report_inches", _reportInches);
handler.item("enable_parking_override_control", _enableParkingOverrideControl);
handler.item("use_line_numbers", _useLineNumbers);
handler.item("planner_blocks", _planner_blocks, 10, 120);

Spindles::SpindleFactory::factory(handler, _spindles);
}
Expand Down Expand Up @@ -219,7 +220,7 @@ namespace Machine {

} catch (const Configuration::ParseException& ex) {
sys.state = State::ConfigAlarm;
log_error("Configuration parse error: " << ex.What() << " Line " << ex.LineNumber() << " column " << ex.ColumnNumber());
log_error("Configuration parse error on line " << ex.LineNumber() << ": " << ex.What());
} catch (const AssertionFailed& ex) {
sys.state = State::ConfigAlarm;
// Get rid of buffer and return
Expand Down
2 changes: 2 additions & 0 deletions FluidNC/src/Machine/MachineConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ namespace Machine {
bool _verboseErrors = false;
bool _reportInches = false;

size_t _planner_blocks = 16;

// Enables a special set of M-code commands that enables and disables the parking motion.
// These are controlled by `M56`, `M56 P1`, or `M56 Px` to enable and `M56 P0` to disable.
// The command is modal and will be set after a planner sync. Since it is GCode, it is
Expand Down
2 changes: 1 addition & 1 deletion FluidNC/src/Machine/Motor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Machine {
handler.item("limit_pos_pin", _posPin);
handler.item("limit_all_pin", _allPin);
handler.item("hard_limits", _hardLimits);
handler.item("pulloff_mm", _pulloff);
handler.item("pulloff_mm", _pulloff, 0.1, 100000.0);
MotorDrivers::MotorFactory::factory(handler, _driver);
}

Expand Down
8 changes: 4 additions & 4 deletions FluidNC/src/Machine/UserOutputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ namespace Machine {
handler.item("analog1_pin", _analogOutput[1]);
handler.item("analog2_pin", _analogOutput[2]);
handler.item("analog3_pin", _analogOutput[3]);
handler.item("analog0_hz", _analogFrequency[0]);
handler.item("analog1_hz", _analogFrequency[1]);
handler.item("analog2_hz", _analogFrequency[2]);
handler.item("analog3_hz", _analogFrequency[3]);
handler.item("analog0_hz", _analogFrequency[0], 1, 20000000);
handler.item("analog1_hz", _analogFrequency[1], 1, 20000000);
handler.item("analog2_hz", _analogFrequency[2], 1, 20000000);
handler.item("analog3_hz", _analogFrequency[3], 1, 20000000);
handler.item("digital0_pin", _digitalOutput[0]);
handler.item("digital1_pin", _digitalOutput[1]);
handler.item("digital2_pin", _digitalOutput[2]);
Expand Down
2 changes: 2 additions & 0 deletions FluidNC/src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ void setup() {

config->_stepping->init(); // Configure stepper interrupt timers

plan_init();

config->_userOutputs->init();

config->_axes->init();
Expand Down
24 changes: 22 additions & 2 deletions FluidNC/src/MotionControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "I2SOut.h" // i2s_out_reset
#include "InputFile.h" // infile
#include "Platform.h" // WEAK_LINK
#include "Settings.h" // coords

#include <cmath>

Expand Down Expand Up @@ -290,7 +291,7 @@ bool probe_succeeded = false;

// Perform tool length probe cycle. Requires probe switch.
// NOTE: Upon probe failure, the program will be stopped and placed into ALARM state.
GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t parser_flags) {
GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t parser_flags, uint8_t offsetAxis, float offset) {
if (!config->_probe->exists()) {
log_error("Probe pin is not configured");
return GCUpdatePos::None;
Expand Down Expand Up @@ -321,7 +322,6 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
return GCUpdatePos::None; // Nothing else to do but bail.
}
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
log_info("Found");
mc_linear(target, pl_data, gc_state.position);
// Activate the probing state monitor in the stepper module.
probeState = ProbeState::Active;
Expand Down Expand Up @@ -360,6 +360,26 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
report_probe_parameters(allChannels);
}
if (probe_succeeded) {
if (offset != __FLT_MAX__) {
float coord_data[MAX_N_AXIS];
float probe_contact[MAX_N_AXIS];

motor_steps_to_mpos(probe_contact, probe_steps);
coords[gc_state.modal.coord_select]->get(coord_data); // get a copy of the current coordinate offsets
auto n_axis = config->_axes->_numberAxis;
for (int axis = 0; axis < n_axis; axis++) { // find the axis specified. There should only be one.
if (offsetAxis & (1 << axis)) {
coord_data[axis] = probe_contact[axis] + offset;
log_info("Offset:" << coord_data[axis]);
break;
}
}
log_info("Probe offset applied:");
coords[gc_state.modal.coord_select]->set(coord_data); // save it
memcpy(gc_state.coord_system, coord_data, sizeof(gc_state.coord_system));
report_wco_counter = 0;
}

return GCUpdatePos::System; // Successful probe cycle.
} else {
return GCUpdatePos::Target; // Failed to trigger probe within travel. With or without error.
Expand Down
2 changes: 1 addition & 1 deletion FluidNC/src/MotionControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ bool mc_dwell(int32_t milliseconds);
void mc_homing_cycle(AxisMask cycle_mask);

// Perform tool length probe cycle. Requires probe switch.
GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t parser_flags);
GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t parser_flags, uint8_t offsetAxis = 0, float offset = 0.0);

// Handles updating the override control state.
void mc_override_ctrl_update(Override override_state);
Expand Down
16 changes: 8 additions & 8 deletions FluidNC/src/Motors/TrinamicBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ namespace MotorDrivers {
TrinamicBase(uint16_t partNumber) : StandardStepper(), _driver_part_number(partNumber) {}

void group(Configuration::HandlerBase& handler) override {
handler.item("r_sense_ohms", _r_sense);
handler.item("run_amps", _run_current);
handler.item("hold_amps", _hold_current);
handler.item("microsteps", _microsteps);
handler.item("stallguard", _stallguard);
handler.item("r_sense_ohms", _r_sense, 0.01, 1.00);
handler.item("run_amps", _run_current, 0.05, 10.0);
handler.item("hold_amps", _hold_current, 0.05, 10.0);
handler.item("microsteps", _microsteps, 1, 256);
handler.item("stallguard", _stallguard, -64, 63);
handler.item("stallguard_debug", _stallguardDebugMode);
handler.item("toff_disable", _toff_disable);
handler.item("toff_stealthchop", _toff_stealthchop);
handler.item("toff_coolstep", _toff_coolstep);
handler.item("toff_disable", _toff_disable, 0, 15);
handler.item("toff_stealthchop", _toff_stealthchop, 2, 15);
handler.item("toff_coolstep", _toff_coolstep, 2, 15);
handler.item("run_mode", _run_mode, trinamicModes);
handler.item("homing_mode", _homing_mode, trinamicModes);
handler.item("use_enable", _use_enable);
Expand Down
2 changes: 1 addition & 1 deletion FluidNC/src/Motors/TrinamicSpiDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace MotorDrivers {

void group(Configuration::HandlerBase& handler) override {
handler.item("cs_pin", _cs_pin);
handler.item("spi_index", _spi_index);
handler.item("spi_index", _spi_index, -1, 127);
TrinamicBase::group(handler);
}

Expand Down
8 changes: 8 additions & 0 deletions FluidNC/src/NutsBolts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ char* trim(char* str) {
return str;
}

bool multiple_bits_set(uint32_t val) {
// Takes advantage of a quirk of twos-complement math. If a number has
// only one bit set, for example 0b1000, then subtracting 1 will clear that
// bit and set only other bits giving e.g. 0b0111, and anding the two gives 0.
// If multiple bits are set, subtracting 1 will not clear the high bit.
return val & (val - 1);
}

String formatBytes(uint64_t bytes) {
if (bytes < 1024) {
return String((uint16_t)bytes) + " B";
Expand Down
6 changes: 4 additions & 2 deletions FluidNC/src/NutsBolts.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,15 @@ T mapConstrain(T x, T in_min, T in_max, T out_min, T out_max) {

// constrain a value and issue a message. Returns true is the value was OK
template <typename T>
bool constrain_with_message(T& value, T min, T max) {
bool constrain_with_message(T& value, T min, T max, const char* name = "") {
if (value < min || value > max) {
log_warn("Value " << value << " constrained to range (" << min << "," << max << ")");
log_warn(name << " value " << value << " constrained to range (" << min << "," << max << ")");
value = myConstrain(value, min, max);
return false;
}
return true;
}

bool multiple_bits_set(uint32_t val);

String formatBytes(uint64_t bytes);
Loading

0 comments on commit adfc015

Please sign in to comment.