1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-01 02:21:46 +02:00

Merge remote-tracking branch 'bdring/master'

This commit is contained in:
Unknown
2019-06-26 10:16:22 +02:00
70 changed files with 8845 additions and 3276 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.pioenvs/

View File

@@ -18,7 +18,6 @@ before_script:
- cd esp32/tools
- python get.py
- cd ..
- echo 'build.flash_freq=40m' >> platform.txt
- mv $TRAVIS_BUILD_DIR/libraries/ESP32SSDP $HOME/arduino_ide/libraries/
- mv $TRAVIS_BUILD_DIR/libraries/arduinoWebSockets $HOME/arduino_ide/libraries/
@@ -26,7 +25,7 @@ script:
- cd $TRAVIS_BUILD_DIR
- source command.sh
- export PATH="$HOME/arduino_ide:$PATH"
- arduino --board esp32:esp32:esp32 --save-prefs
- arduino --board esp32:esp32:esp32:PartitionScheme=min_spiffs,FlashFreq=40 --pref compiler.warning_level=all --save-prefs
- sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- sed -i "s/\/\/#define ENABLE_BLUETOOTH/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- sed -i "s/#define ENABLE_BLUETOOTH/\/\/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
@@ -37,6 +36,11 @@ script:
- sed -i "s/#define ENABLE_WIFI/\/\/#define ENABLE_WIFI/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- build_sketch $TRAVIS_BUILD_DIR/Grbl_Esp32/Grbl_Esp32.ino
- sed -i "s/\/\/#define ENABLE_BLUETOOTH/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- sed -i "s/\/\/#define ENABLE_WIFI/#define ENABLE_WIFI/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h
- build_sketch $TRAVIS_BUILD_DIR/Grbl_Esp32/Grbl_Esp32.ino
notifications:
email:

198
Grbl_Esp32/BTconfig.cpp Normal file
View File

@@ -0,0 +1,198 @@
/*
BTconfig.cpp - Bluetooth functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ARDUINO_ARCH_ESP32
#include "config.h"
#ifdef ENABLE_BLUETOOTH
#include <Preferences.h>
#include "BluetoothSerial.h"
#include "BTconfig.h"
#include "commands.h"
#include "report.h"
BTConfig bt_config;
BluetoothSerial SerialBT;
#ifdef __cplusplus
extern "C" {
#endif
const uint8_t *esp_bt_dev_get_address(void);
#ifdef __cplusplus
}
#endif
String BTConfig::_btname = "";
String BTConfig::_btclient = "";
BTConfig::BTConfig(){
}
BTConfig::~BTConfig(){
end();
}
static void my_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
switch (event)
{
case ESP_SPP_SRV_OPEN_EVT://Server connection open
{
char str[18];
str[17]='\0';
uint8_t * addr = param->srv_open.rem_bda;
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
BTConfig::_btclient = str;
grbl_sendf(CLIENT_ALL,"[MSG:BT Connected with %s]\r\n", str);
}
break;
case ESP_SPP_CLOSE_EVT://Client connection closed
grbl_send(CLIENT_ALL,"[MSG:BT Disconnected]\r\n");
BTConfig::_btclient="";
break;
default:
break;
}
}
const char *BTConfig::info(){
static String result;
String tmp;
result = "[MSG:";
if(Is_BT_on()) {
result += "Mode=BT:Name=";
result += _btname;
result += "(";
result += device_address();
result += "):Status=";
if (SerialBT.hasClient()){
result += "Connected with " + _btclient;
} else result += "Not connected";
}
else result+="No BT";
result+= "]\r\n";
return result.c_str();
}
/**
* Check if BlueTooth string is valid
*/
bool BTConfig::isBTnameValid (const char * hostname){
//limited size
char c;
if (strlen (hostname) > MAX_BTNAME_LENGTH || strlen (hostname) < MIN_BTNAME_LENGTH) {
return false;
}
//only letter and digit
for (int i = 0; i < strlen (hostname); i++) {
c = hostname[i];
if (! (isdigit (c) || isalpha (c) || c == '_') ) {
return false;
}
}
return true;
}
const char* BTConfig::device_address(){
const uint8_t* point = esp_bt_dev_get_address();
static char str[18];
str[17]='\0';
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", (int)point[0], (int)point[1], (int)point[2], (int)point[3], (int)point[4], (int)point[5]);
return str;
}
/**
* begin WiFi setup
*/
void BTConfig::begin() {
Preferences prefs;
//stop active services
end();
prefs.begin(NAMESPACE, true);
//Get hostname
String defV = DEFAULT_BT_NAME;
_btname = prefs.getString(BT_NAME_ENTRY, defV);
int8_t wifiMode = prefs.getChar(ESP_RADIO_MODE, DEFAULT_RADIO_MODE);
prefs.end();
if (wifiMode == ESP_BT) {
if (!SerialBT.begin(_btname))
{
report_status_message(STATUS_BT_FAIL_BEGIN, CLIENT_ALL);
} else {
SerialBT.register_callback(&my_spp_cb);
grbl_sendf(CLIENT_ALL,"[MSG:BT Started with %s]\r\n", _btname.c_str());
}
}else end();
}
/**
* End WiFi
*/
void BTConfig::end() {
SerialBT.end();
}
/**
* Reset ESP
*/
void BTConfig::reset_settings(){
Preferences prefs;
prefs.begin(NAMESPACE, false);
String sval;
int8_t bbuf;
bool error = false;
sval = DEFAULT_BT_NAME;
if (prefs.putString(BT_NAME_ENTRY, sval) == 0){
error = true;
}
bbuf = DEFAULT_RADIO_MODE;
if (prefs.putChar(ESP_RADIO_MODE, bbuf) ==0 ) {
error = true;
}
prefs.end();
if (error) {
grbl_send(CLIENT_ALL,"[MSG:BT reset error]\r\n");
} else {
grbl_send(CLIENT_ALL,"[MSG:BT reset done]\r\n");
}
}
/**
* Check if BT is on and working
*/
bool BTConfig::Is_BT_on(){
return btStarted();
}
/**
* Handle not critical actions that must be done in sync environement
*/
void BTConfig::handle() {
//If needed
COMMANDS::wait(0);
}
#endif // ENABLE_BLUETOOTH
#endif // ARDUINO_ARCH_ESP32

65
Grbl_Esp32/BTconfig.h Normal file
View File

@@ -0,0 +1,65 @@
/*
BTconfig.h - Bluetooth functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//Preferences entries
#define BT_NAME_ENTRY "BT_NAME"
//defaults values
#define DEFAULT_BT_NAME "btgrblesp"
//boundaries
#define MAX_BTNAME_LENGTH 32
#define MIN_BTNAME_LENGTH 1
#define BT_EVENT_DISCONNECTED 0
#define BT_EVENT_CONNECTED 1
#ifndef _BT_CONFIG_H
#define _BT_CONFIG_H
#include "BluetoothSerial.h"
extern BluetoothSerial SerialBT;
class BTConfig {
public:
BTConfig();
~BTConfig();
static const char *info();
static void BTEvent(uint8_t event);
static bool isBTnameValid (const char * hostname);
static String BTname(){return _btname;}
static const char* device_address();
static void begin();
static void end();
static void handle();
static void reset_settings();
static bool Is_BT_on();
static String _btclient;
private :
static String _btname;
};
extern BTConfig bt_config;
#endif

View File

@@ -46,24 +46,30 @@ void setup() {
system_ini(); // Configure pinout pins and pin-change interrupt (Renamed due to conflict with esp32 files)
#ifdef ENABLE_BLUETOOTH
//#ifdef ENABLE_BLUETOOTH
// if $I has some text, that is the bluetooth name
// This is a temporary convenience until a new setting is defined
char line[LINE_BUFFER_SIZE];
settings_read_build_info(line);
if (line[0] != '\0') {
// just send to serial because it is the only interface available
Serial.printf("Starting Bluetooth:%s", line);
bluetooth_init(line);
}
#endif
//char line[LINE_BUFFER_SIZE];
//settings_read_build_info(line);
//if (line[0] != '\0') {
// // just send to serial because it is the only interface available
// Serial.printf("Starting Bluetooth:%s", line);
// bluetooth_init(line);
//}
//#endif
memset(sys_position,0,sizeof(sys_position)); // Clear machine position.
#ifdef USE_PEN_SERVO
servo_init();
#endif
#ifdef USE_SERVO_AXES
init_servos();
#endif
#ifdef USE_PEN_SOLENOID
solenoid_init();
#endif
@@ -89,6 +95,9 @@ void setup() {
#ifdef ENABLE_WIFI
wifi_config.begin();
#endif
#ifdef ENABLE_BLUETOOTH
bt_config.begin();
#endif
}
void loop() {

58
Grbl_Esp32/TMC2130.cpp Normal file
View File

@@ -0,0 +1,58 @@
/*
TMC2130.cpp - Support for TMC2130 Stepper Drivers SPI Mode
Part of Grbl_ESP32
Copyright (c) 2019 Barton Dring for Buildlog.net LLC
GrblESP32 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 "grbl.h"
#ifdef X_CS_PIN
TMC2130Stepper TMC2130_X = TMC2130Stepper(X_CS_PIN);
#endif
#ifdef Y_CS_PIN
TMC2130Stepper TMC2130_Y = TMC2130Stepper(Y_CS_PIN);
#endif
#ifdef Z_CS_PIN
TMC2130Stepper TMC2130_Z = TMC2130Stepper(Z_CS_PIN);
#endif
void TMC2130_Init()
{
#ifdef X_CS_PIN
TMC2130_X.begin(); // Initiate pins and registries
TMC2130_X.microsteps(32);
TMC2130_X.setCurrent(200, 0.11, 0.5);
TMC2130_X.stealthChop(1); // Enable extremely quiet stepping
#endif
#ifdef Y_CS_PIN
TMC2130_Y.begin(); // Initiate pins and registries
TMC2130_Y.microsteps(32);
TMC2130_Y.setCurrent(200, 0.11, 0.5);
TMC2130_Y.stealthChop(1); // Enable extremely quiet stepping
#endif
#ifdef Z_CS_PIN
TMC2130_Z.begin(); // Initiate pins and registries
TMC2130_Z.microsteps(32);
TMC2130_Z.setCurrent(200, 0.11, 0.5);
TMC2130_Z.stealthChop(1); // Enable extremely quiet stepping
#endif
}

31
Grbl_Esp32/TMC2130.h Normal file
View File

@@ -0,0 +1,31 @@
/*
TMC2130.h - Support for TMC2130 Stepper Drivers SPI Mode
Part of Grbl_ESP32
Copyright (c) 2019 Barton Dring for Buildlog.net LLC
GrblESP32 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 TMC2130_h
#define TMC2130_h
#include "grbl.h"
#include <TMC2130Stepper.h>
#ifdef USE_TMC2130
void TMC2130_Init();
#endif
#endif

2147
Grbl_Esp32/commands.cpp Normal file

File diff suppressed because it is too large Load Diff

58
Grbl_Esp32/commands.h Normal file
View File

@@ -0,0 +1,58 @@
/*
commands.h - ESP3D configuration class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef COMMANDS_h
#define COMMANDS_h
#include "config.h"
//Authentication level
typedef enum {
LEVEL_GUEST = 0,
LEVEL_USER = 1,
LEVEL_ADMIN = 2
} level_authenticate_type;
// Define line flags. Includes comment type tracking and line overflow detection.
#define LINE_FLAG_OVERFLOW bit(0)
#define LINE_FLAG_COMMENT_PARENTHESES bit(1)
#define LINE_FLAG_COMMENT_SEMICOLON bit(2)
class ESPResponseStream;
class COMMANDS
{
public:
static bool check_command (const char *, int * cmd, String & cmd_params);
static String get_param (String & cmd_params, const char * id, bool withspace);
static bool execute_internal_command (int cmd, String cmd_params, level_authenticate_type auth_level = LEVEL_GUEST , ESPResponseStream *espresponse= NULL);
static void wait(uint32_t milliseconds);
static void handle();
static void restart_ESP();
#ifdef ENABLE_AUTHENTICATION
static bool isadmin (String & cmd_params);
static bool isuser (String & cmd_params);
static bool isLocalPasswordValid (const char * password);
#endif
private :
static bool restart_ESP_module;
};
#endif

View File

@@ -5,7 +5,7 @@
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
2018 - Bart Dring This file was modified for use on the ESP32
2018 - Bart Dring This file was modifed for use on the ESP32
CPU. Do not use this with Grbl for atMega328P
Grbl is free software: you can redistribute it and/or modify
@@ -46,12 +46,14 @@ Some features should not be changed. See notes below.
// one configuration file by placing their specific defaults and pin map at the bottom of this file.
// If doing so, simply comment out these two defines and see instructions below.
#define DEFAULTS_GENERIC
#define CPU_MAP_ESP32
#define CPU_MAP_ESP32 // these are defined in cpu_map.h
#define VERBOSE_HELP // adds addition help info, but could confuse some senders
// Serial baud rate
#define BAUD_RATE 115200
//#define ENABLE_BLUETOOTH // enable bluetooth ... turns of if $I= something
#define ENABLE_BLUETOOTH // enable bluetooth ... turns of if $I= something
#define ENABLE_SD_CARD // enable use of SD Card to run jobs
@@ -60,14 +62,49 @@ Some features should not be changed. See notes below.
#define ENABLE_HTTP //enable HTTP and all related services
#define ENABLE_OTA //enable OTA
#define ENABLE_TELNET //enable telnet
#define ENABLE_TELNET_WELCOME_MSG //display welcome string when connect to telnet
#define ENABLE_MDNS //enable mDNS discovery
#define ENABLE_SSDP //enable UPNP discovery
#define ENABLE_NOTIFICATIONS //enable notifications
#define ENABLE_SERIAL2SOCKET_IN
#define ENABLE_SERIAL2SOCKET_OUT
#define ENABLE_CAPTIVE_PORTAL
#define ENABLE_AUTHENTICATION
//#define ENABLE_AUTHENTICATION
#define NAMESPACE "GRBL"
#define ESP_RADIO_MODE "RADIO_MODE"
#ifdef ENABLE_AUTHENTICATION
#define DEFAULT_ADMIN_PWD "admin"
#define DEFAULT_USER_PWD "user";
#define DEFAULT_ADMIN_LOGIN "admin"
#define DEFAULT_USER_LOGIN "user"
#define ADMIN_PWD_ENTRY "ADMIN_PWD"
#define USER_PWD_ENTRY "USER_PWD"
#define AUTH_ENTRY_NB 20
#define MAX_LOCAL_PASSWORD_LENGTH 16
#define MIN_LOCAL_PASSWORD_LENGTH 1
#endif
//Radio Mode
#define ESP_RADIO_OFF 0
#define ESP_WIFI_STA 1
#define ESP_WIFI_AP 2
#define ESP_BT 3
//Default mode
#ifdef ENABLE_WIFI
#define DEFAULT_RADIO_MODE ESP_WIFI_AP
#else
#undef ENABLE_NOTIFICATIONS
#ifdef ENABLE_BLUETOOTH
#define DEFAULT_RADIO_MODE ESP_BT
#else
#define DEFAULT_RADIO_MODE ESP_RADIO_OFF
#endif
#endif
// Define realtime command special characters. These characters are 'picked-off' directly from the
// serial read data stream and are not passed to the grbl line execution parser. Select characters
@@ -171,6 +208,7 @@ Some features should not be changed. See notes below.
// values cannot be less than 0.001mm or 0.0001in, because machines can not be physically more
// precise this. So, there is likely no need to change these, but you can if you need to here.
// NOTE: Must be an integer value from 0 to ~4. More than 4 may exhibit round-off errors.
// ESP32 Note: These are mostly hard coded, so these values will not change anything
#define N_DECIMAL_COORDVALUE_INCH 4 // Coordinate or position value in inches
#define N_DECIMAL_COORDVALUE_MM 3 // Coordinate or position value in mm
#define N_DECIMAL_RATEVALUE_INCH 1 // Rate or velocity value in in/min
@@ -206,7 +244,7 @@ Some features should not be changed. See notes below.
// immediately forces a feed hold and then safely de-energizes the machine. Resuming is blocked until
// the safety door is re-engaged. When it is, Grbl will re-energize the machine and then resume on the
// previous tool path, as if nothing happened.
//#define ENABLE_SAFETY_DOOR_INPUT_PIN // ESP32 Leave this enabled for now .. code for undefined not ready
#define ENABLE_SAFETY_DOOR_INPUT_PIN // ESP32 Leave this enabled for now .. code for undefined not ready
// After the safety door switch has been toggled and restored, this setting sets the power-up delay
// between restoring the spindle and coolant and resuming the cycle.
@@ -225,23 +263,24 @@ Some features should not be changed. See notes below.
// Enable using a servo for the Z axis on a pen type machine.
// You typically should not define a pin for the Z axis in cpu_map.h
// You should configure your settings in servo_pen.h
//#define USE_PEN_SERVO
// #define USE_PEN_SERVO // this method will be deprecated soon
// #define USE_SERVO_AXES // the new method
// define your servo pin here or in cpu_map.h
//#define SERVO_PEN_PIN GPIO_NUM_27
// Enable using a solenoid for the Z axis on a pen type machine
//#define USE_PEN_SOLENOID
// #define USE_PEN_SOLENOID
// Inverts pin logic of the control command pins based on a mask. This essentially means you can use
// normally-closed switches on the specified pins, rather than the default normally-open switches.
// NOTE: The top option will mask and invert all control pins. The bottom option is an example of
// inverting only two control pins, the safety door and reset. See cpu_map.h for other bit definitions.
//#define INVERT_CONTROL_PIN_MASK CONTROL_MASK // Default disabled. Uncomment to disable.
// The mask order is Cycle Start | Feed Hold | Reset | Safety Door
// For example B1101 will invert the function of the Reset pin.
#define INVERT_CONTROL_PIN_MASK B1111
// This allows control pins to be ignored.
// Since these are typically used on the pins that don't have pullups, they will float and cause
// problems if not externally pulled up. Ignoring will always return not activated when read.
//#define IGNORE_CONTROL_PINS
#define IGNORE_CONTROL_PINS
@@ -463,6 +502,15 @@ Some features should not be changed. See notes below.
// time step. Also, keep in mind that the Arduino delay timer is not very accurate for long delays.
#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds)
// For test use only. This uses the ESP32's RMT perifieral to generate step pulses
// It allows the use of the STEP_PULSE_DELAY (see below) and it automatically ends the
// pulse in one operation.
// Dir Pin ____|--------------------
// Step Pin _______|--|____________
// While this is experimental, it is intended to be the future default method after testing
//#define USE_RMT_STEPS
// Creates a delay between the direction pin setting and corresponding step pulse by creating
// another interrupt (Timer2 compare) to manage it. The main Grbl interrupt (Timer1 compare)
// sets the direction pins, and does not immediately set the stepper pins, as it would in
@@ -472,8 +520,8 @@ Some features should not be changed. See notes below.
// NOTE: Uncomment to enable. The recommended delay must be > 3us, and, when added with the
// user-supplied step pulse time, the total time must not exceed 127us. Reported successful
// values for certain setups have ranged from 5 to 20us.
// !!!!! ESP32 Not currently implemented
// #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.
// must use #define USE_RMT_STEPS for this to work
//#define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.
// The number of linear motions in the planner buffer to be planned at any give time. The vast
// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra
@@ -513,14 +561,11 @@ Some features should not be changed. See notes below.
// #define RX_BUFFER_SIZE 128 // (1-254) Uncomment to override defaults in serial.h
// #define TX_BUFFER_SIZE 100 // (1-254)
// A simple software debouncing feature for hard limit switches. When enabled, the interrupt
// monitoring the hard limit switch pins will enable the Arduino's watchdog timer to re-check
// the limit pin state after a delay of about 32msec. This can help with CNC machines with
// problematic false triggering of their hard limit switches, but it WILL NOT fix issues with
// electrical interference on the signal cables from external sources. It's recommended to first
// use shielded signal cables with their shielding connected to ground (old USB/computer cables
// work well and are cheap to find) and wire in a low-pass circuit into each limit pin.
// #define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable.
// A simple software debouncing feature for hard limit switches. When enabled, the limit
// switch interrupt unblock a waiting task which will recheck the limit switch pins after
// a short delay. Default disabled
//#define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable.
#define DEBOUNCE_PERIOD 32 // in milliseconds default 32 microseconds
// Configures the position after a probing cycle during Grbl's check mode. Disabled sets
// the position to the probe target, when enabled sets the position to the start position.

View File

@@ -35,7 +35,9 @@
with AVR grbl
*/
#ifdef CPU_MAP_ESP32
// This is the CPU Map for the ESP32 CNC Controller R2
@@ -43,13 +45,19 @@
// won't affect operation except that there will be no output
// form the pins. Grbl will virtually move the axis. This could
// be handy if you are using a servo, etc. for another axis.
#define X_STEP_PIN GPIO_NUM_12
#define Y_STEP_PIN GPIO_NUM_14
#define Z_STEP_PIN GPIO_NUM_27
#define CPU_MAP_NAME "CPU_MAP_ESP32"
#define X_DIRECTION_PIN GPIO_NUM_26
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Z_DIRECTION_PIN GPIO_NUM_33
#define X_STEP_PIN GPIO_NUM_12
#define X_DIRECTION_PIN GPIO_NUM_26
#define X_RMT_CHANNEL 0
#define Y_STEP_PIN GPIO_NUM_14
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Y_RMT_CHANNEL 1
#define Z_STEP_PIN GPIO_NUM_27
#define Z_DIRECTION_PIN GPIO_NUM_33
#define Z_RMT_CHANNEL 2
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
@@ -77,6 +85,8 @@
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_ENABLE_PIN GPIO_NUM_22
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
// if these spindle function pins are defined, they will be activated in the code
@@ -97,9 +107,95 @@
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
#endif
#ifdef CPU_MAP_ESP32_ESC_SPINDLE
// This is the CPU Map for the ESP32 CNC Controller R2
// It is OK to comment out any step and direction pins. This
// won't affect operation except that there will be no output
// form the pins. Grbl will virtually move the axis. This could
// be handy if you are using a servo, etc. for another axis.
#define CPU_MAP_NAME "CPU_MAP_ESP32_ESC_SPINDLE"
#define X_STEP_PIN GPIO_NUM_12
#define X_DIRECTION_PIN GPIO_NUM_26
#define X_RMT_CHANNEL 0
#define Y_STEP_PIN GPIO_NUM_14
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Y_RMT_CHANNEL 1
#define Z_STEP_PIN GPIO_NUM_27
#define Z_DIRECTION_PIN GPIO_NUM_33
#define Z_RMT_CHANNEL 2
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
// *** the flood coolant feature code is activated by defining this pins
// *** Comment it out to use the pin for other features
#define COOLANT_FLOOD_PIN GPIO_NUM_16
//#define COOLANT_MIST_PIN GPIO_NUM_21
// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still
// use a virtual spindle. Do not comment out the other parameters for the spindle.
#define SPINDLE_PWM_PIN GPIO_NUM_17
#define SPINDLE_PWM_CHANNEL 0
// RC ESC Based Spindle
// An ESC works like a hobby servo with 50Hz PWM 1ms to 2 ms pulse range
#define SPINDLE_PWM_BASE_FREQ 50 // Hz for ESC
#define SPINDLE_PWM_BIT_PRECISION 16 // 16 bit required for ESC
#define SPINDLE_PULSE_RES_COUNT 65535
#define ESC_MIN_PULSE_SEC 0.001 // min pulse in seconds (OK to tune this one)
#define ESC_MAX_PULSE_SEC 0.002 // max pulse in seconds (OK to tune this one)
#define ESC_TIME_PER_BIT ((1.0 / (float)SPINDLE_PWM_BASE_FREQ) / ((float)SPINDLE_PULSE_RES_COUNT) ) // seconds
#define SPINDLE_PWM_OFF_VALUE (uint16_t)(ESC_MIN_PULSE_SEC / ESC_TIME_PER_BIT) // in timer counts
#define SPINDLE_PWM_MAX_VALUE (uint16_t)(ESC_MAX_PULSE_SEC / ESC_TIME_PER_BIT) // in timer counts
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE SPINDLE_PWM_OFF_VALUE // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define SPINDLE_ENABLE_PIN GPIO_NUM_22
// if these spindle function pins are defined, they will be activated in the code
// comment them out to use the pins for other functions
//#define SPINDLE_ENABLE_PIN GPIO_NUM_16
//#define SPINDLE_DIR_PIN GPIO_NUM_16
#define X_LIMIT_PIN GPIO_NUM_2
#define Y_LIMIT_PIN GPIO_NUM_4
#define Z_LIMIT_PIN GPIO_NUM_15
#define LIMIT_MASK B111
#define PROBE_PIN GPIO_NUM_32
#define CONTROL_SAFETY_DOOR_PIN GPIO_NUM_35 // needs external pullup
#define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
#endif
#ifdef CPU_MAP_PEN_LASER // The Buildlog.net pen laser controller V1
// For pen mode be sure to uncomment #define USE_PEN_SERVO in config.h
// For solenoid mode be sure to uncomment #define USE_PEN_SERVO in config.h
// For laser mode, you do not need to change anything
// Note: You can use all 3 modes at the same time if you want
#define CPU_MAP_NAME "CPU_MAP_PEN_LASER"
// Pick a board version
//#define PEN_LASER_V1
#define PEN_LASER_V2
#define X_STEP_PIN GPIO_NUM_12
#define Y_STEP_PIN GPIO_NUM_14
#define X_DIRECTION_PIN GPIO_NUM_26
@@ -107,16 +203,14 @@
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
#define X_LIMIT_PIN GPIO_NUM_2
#ifdef PEN_LASER_V1
#define X_LIMIT_PIN GPIO_NUM_2
#endif
#ifdef PEN_LASER_V2
#define X_LIMIT_PIN GPIO_NUM_15
#endif
#define Y_LIMIT_PIN GPIO_NUM_4
#define LIMIT_MASK B11
// ignored via config.h
#define CONTROL_SAFETY_DOOR_PIN GPIO_NUM_35 // needs external pullup
#define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
#define LIMIT_MASK B11
// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still
// use a virtual spindle. Do not comment out the other parameters for the spindle.
@@ -136,14 +230,68 @@
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define SERVO_PEN_PIN GPIO_NUM_27
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#endif
// defaults
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // stay on
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 0 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir Z, negative X,Y
#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 1000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 3.0 // mm
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 80
#define DEFAULT_Y_STEPS_PER_MM 80
#define DEFAULT_Z_STEPS_PER_MM 100.0 // This is percent in servo mode...used for calibration
#define DEFAULT_X_MAX_RATE 5000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 5000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 5000.0 // mm/min
#define DEFAULT_X_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (50.0*60*60)
#define DEFAULT_X_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 100.0 // This is percent in servo mode...used for calibration
#endif
#ifdef CPU_MAP_MIDTBOT // Buildlog.net midtbot
#define CPU_MAP_NAME "CPU_MAP_MIDTBOT"
#define X_STEP_PIN GPIO_NUM_12
#define Y_STEP_PIN GPIO_NUM_14
#define X_DIRECTION_PIN GPIO_NUM_26
@@ -190,8 +338,8 @@
#endif
// redefine some stuff from config.h
#define HOMING_CYCLE_0 (1<<X_AXIS)
#define HOMING_CYCLE_1 (1<<Y_AXIS)
#define HOMING_CYCLE_0 (1<<Y_AXIS)
#define HOMING_CYCLE_1 (1<<X_AXIS)
#ifdef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#endif
@@ -204,9 +352,715 @@
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define SERVO_PEN_PIN GPIO_NUM_27
#define SERVO_PEN_PIN GPIO_NUM_27
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#endif
// defaults
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // stay on
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 2 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 1
#define DEFAULT_HOMING_DIR_MASK 1
#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 1000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 3.0 // mm
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 100.0
#define DEFAULT_Y_STEPS_PER_MM 100.0
#define DEFAULT_Z_STEPS_PER_MM 100.0 // This is percent in servo mode
#define DEFAULT_X_MAX_RATE 8000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 8000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 5000.0 // mm/min
#define DEFAULT_X_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (100.0*60*60)
#define DEFAULT_X_MAX_TRAVEL 50.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 100.0 // This is percent in servo mode
#endif
#ifdef CPU_MAP_POLAR_COASTER // The Buildlog.net pen polar coaster controller V1
#define CPU_MAP_NAME "CPU_MAP_POLAR_COASTER"
#define X_STEP_PIN GPIO_NUM_15
#define Y_STEP_PIN GPIO_NUM_2
#define X_DIRECTION_PIN GPIO_NUM_25
#define Y_DIRECTION_PIN GPIO_NUM_26
#define STEPPERS_DISABLE_PIN GPIO_NUM_17
#define X_LIMIT_PIN GPIO_NUM_4
#define LIMIT_MASK B1
#define CONTROL_RESET_PIN GPIO_NUM_13
// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still
// use a virtual spindle. Do not comment out the other parameters for the spindle.
//#define SPINDLE_PWM_PIN GPIO_NUM_17
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define USE_PEN_SERVO
#define SERVO_PEN_PIN GPIO_NUM_16
// redefine some stuff from config.h
#define HOMING_CYCLE_0 (1<<X_AXIS) // this 'bot only homes the X axis
#ifdef HOMING_CYCLE_1
#undef HOMING_CYCLE_1
#endif
#ifdef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#endif
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#endif
// defaults
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // stay on
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 2 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 1
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir Z, negative X,Y
#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 1000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 3.0 // mm
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 200.0
#define DEFAULT_Y_STEPS_PER_MM 71.111
#define DEFAULT_Z_STEPS_PER_MM 100.0 // This is percent in servo mode
#define DEFAULT_X_MAX_RATE 5000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 15000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 3000.0 // mm/min
#define DEFAULT_X_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (50.0*60*60)
#define DEFAULT_X_MAX_TRAVEL 50.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 100.0 // This is percent in servo mode
#endif
#ifdef CPU_MAP_SERVO_AXIS // The Buildlog.net pen laser controller V1
// For pen mode be sure to uncomment #define USE_PEN_SERVO in config.h
// For solenoid mode be sure to uncomment #define USE_PEN_SERVO in config.h
// For laser mode, you do not need to change anything
// Note: You can use all 3 modes at the same time if you want
#define CPU_MAP_NAME "CPU_MAP_SERVO_AXIS"
// Pick a board version
//#define PEN_LASER_V1
#define PEN_LASER_V2
#define X_STEP_PIN GPIO_NUM_12
//#define Y_STEP_PIN GPIO_NUM_14
#define X_DIRECTION_PIN GPIO_NUM_26
//#define Y_DIRECTION_PIN GPIO_NUM_25
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
#ifdef PEN_LASER_V1
#define X_LIMIT_PIN GPIO_NUM_2
#endif
#ifdef PEN_LASER_V2
#define X_LIMIT_PIN GPIO_NUM_15
#endif
#define Y_LIMIT_PIN GPIO_NUM_4
#define LIMIT_MASK B11
// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still
// use a virtual spindle. Do not comment out the other parameters for the spindle.
#define SPINDLE_PWM_PIN GPIO_NUM_17 // Laser PWM
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define SERVO_Y_PIN GPIO_NUM_14
#define SERVO_Y_CHANNEL_NUM 6
#define SERVO_Y_RANGE_MIN 0.0
#define SERVO_Y_RANGE_MAX 30.0
#define SERVO_Z_PIN GPIO_NUM_27
#define SERVO_Z_CHANNEL_NUM 5
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 20.0
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#endif
// defaults
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // stay on
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 0 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir Z, negative X,Y
#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 1000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 3.0 // mm
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 40 // half turn on a stepper
#define DEFAULT_Y_STEPS_PER_MM 100.0 // default calibration value
#define DEFAULT_Z_STEPS_PER_MM 100.0 // default calibration value
#define DEFAULT_X_MAX_RATE 2000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 2000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 2000.0 // mm/min
#define DEFAULT_X_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (50.0*60*60)
#define DEFAULT_X_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 100.0 // default calibration value
#define DEFAULT_Z_MAX_TRAVEL 100.0 // default calibration value
#endif
#ifdef CPU_MAP_SM // String art machine definition
#define X_STEP_PIN GPIO_NUM_12
#define X_DIRECTION_PIN GPIO_NUM_26
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
#define X_LIMIT_PIN GPIO_NUM_15
#define LIMIT_MASK B1
// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still
// use a virtual spindle. Do not comment out the other parameters for the spindle.
#define SPINDLE_PWM_PIN GPIO_NUM_17 // Laser PWM
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
// define Y and Z as servos
#define USE_SERVO_AXES
#define SERVO_Y_PIN GPIO_NUM_27
#define SERVO_Y_CHANNEL_NUM 6
#define SERVO_Y_RANGE_MIN 0.0
#define SERVO_Y_RANGE_MAX 20.0
#define SERVO_Z_PIN GPIO_NUM_14
#define SERVO_Z_CHANNEL_NUM 5
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 28.0
// define the control pins
//#define CONTROL_RESET_PIN GPIO_NUM_36 // needs external pullup
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_34 // needs external pullup
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
// change some things that may have been defined in config.h
#ifndef IGNORE_CONTROL_PINS
#define IGNORE_CONTROL_PINS
#endif
#ifdef INVERT_CONTROL_PIN_MASK
#undef INVERT_CONTROL_PIN_MASK
#endif
#define INVERT_CONTROL_PIN_MASK B1100
// clear any default homings and set X as the only one
#ifdef HOMING_CYCLE_0
#undef HOMING_CYCLE_0
#endif
#define HOMING_CYCLE_0 (1<<X_AXIS)
#ifdef HOMING_CYCLE_1
#undef HOMING_CYCLE_1
#endif
#ifdef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#endif
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#endif
// defaults
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // stay on
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 6 // Y and Z need to be inverted
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 1
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir Z, negative X,Y
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 600.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 300.0
#define DEFAULT_Y_STEPS_PER_MM 100.0 // This is percent in servo mode...used for calibration
#define DEFAULT_Z_STEPS_PER_MM 100.0 // This is percent in servo mode...used for calibration
#define DEFAULT_X_MAX_RATE 8000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 4000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 4000.0 // mm/min
#define DEFAULT_X_ACCELERATION (150.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (200.0*60*60)
#define DEFAULT_X_MAX_TRAVEL 100000.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 100.0 // This is percent in servo mode...used for calibration
#define DEFAULT_Z_MAX_TRAVEL 100.0 // This is percent in servo mode...used for calibration
#endif
#ifdef CPU_MAP_MPCNC_V1P2
// This is the CPU Map for the Buildlog.net MPCNC controller
#define CPU_MAP_NAME "CPU_MAP_MPCNC_V1P2"
// switch to the correct default settings
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC
#endif
#define DEFAULTS_MPCNC
#define USE_GANGED_AXES // allow two motors on an axis
#define X_STEP_PIN GPIO_NUM_12
#define X_STEP_B_PIN GPIO_NUM_22 // ganged motor
#define X_AXIS_SQUARING
#define Y_STEP_PIN GPIO_NUM_14
#define Y_STEP_B_PIN GPIO_NUM_21 // ganged motor
#define Y_AXIS_SQUARING
#define Z_STEP_PIN GPIO_NUM_27
#define X_DIRECTION_PIN GPIO_NUM_26
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Z_DIRECTION_PIN GPIO_NUM_33
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
// Note: if you use PWM rather than relay, you could map GPIO_NUM_2 to mist or flood
//#define USE_SPINDLE_RELAY
#ifdef USE_SPINDLE_RELAY
#define SPINDLE_PWM_PIN GPIO_NUM_2
#else
#define SPINDLE_PWM_PIN GPIO_NUM_16
#define SPINDLE_ENABLE_PIN GPIO_NUM_32
#endif
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
// Note: Only uncomment this if USE_SPINDLE_RELAY is commented out.
// Relay can be used for Spindle or Coolant
//#define COOLANT_FLOOD_PIN GPIO_NUM_2
#define X_LIMIT_PIN GPIO_NUM_17
#define Y_LIMIT_PIN GPIO_NUM_4
#define Z_LIMIT_PIN GPIO_NUM_15
#define LIMIT_MASK B111
#ifndef ENABLE_SOFTWARE_DEBOUNCE // V1P2 does not have R/C filters
#define ENABLE_SOFTWARE_DEBOUNCE
#endif
#define PROBE_PIN GPIO_NUM_35
// The default value in config.h is wrong for this controller
#ifdef INVERT_CONTROL_PIN_MASK
#undef INVERT_CONTROL_PIN_MASK
#endif
#define INVERT_CONTROL_PIN_MASK B1110
// Note: defualt is #define IGNORE_CONTROL_PINS in config.h
// uncomment to these lines to use them
#ifdef IGNORE_CONTROL_PINS
#undef IGNORE_CONTROL_PINS
#endif
#define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
#endif
#ifdef CPU_MAP_MPCNC_V1P1
// This is the CPU Map for the Buildlog.net MPCNC controller
#define CPU_MAP_NAME "CPU_MAP_MPCNC_V1P1"
// switch to the correct default settings
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC
#endif
#define DEFAULTS_MPCNC
#define USE_GANGED_AXES // allow two motors on an axis
#define X_STEP_PIN GPIO_NUM_12
#define X_STEP_B_PIN GPIO_NUM_22 // ganged motor
#define X_AXIS_SQUARING
#define Y_STEP_PIN GPIO_NUM_14
#define Y_STEP_B_PIN GPIO_NUM_21 // ganged motor
#define Y_AXIS_SQUARING
#define Z_STEP_PIN GPIO_NUM_27
#define X_DIRECTION_PIN GPIO_NUM_26
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Z_DIRECTION_PIN GPIO_NUM_33
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
// Note: if you use PWM rather than relay, you could map GPIO_NUM_17 to mist or flood
#define USE_SPINDLE_RELAY
#ifdef USE_SPINDLE_RELAY
#define SPINDLE_PWM_PIN GPIO_NUM_17
#else
#define SPINDLE_PWM_PIN GPIO_NUM_16
#define SPINDLE_ENABLE_PIN GPIO_NUM_32
#endif
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
// Note: Only uncomment this if USE_SPINDLE_RELAY is commented out.
// Relay can be used for Spindle or Coolant
//#define COOLANT_FLOOD_PIN GPIO_NUM_17
#define X_LIMIT_PIN GPIO_NUM_34
#define Y_LIMIT_PIN GPIO_NUM_4
#define Z_LIMIT_PIN GPIO_NUM_15
#define LIMIT_MASK B111
#define PROBE_PIN GPIO_NUM_35
// The default value in config.h is wrong for this controller
#ifdef INVERT_CONTROL_PIN_MASK
#undef INVERT_CONTROL_PIN_MASK
#endif
#define INVERT_CONTROL_PIN_MASK B1100
// Note: check the #define IGNORE_CONTROL_PINS is the way you want in config.h
//#define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
#endif
#ifdef CPU_MAP_LOWRIDER // !!!!!!!!!!!!!!!!! Warning: Untested !!!!!!!!!!!!!!!!! //
// This is the CPU Map for the Buildlog.net MPCNC controller
// used in lowrider mode. Low rider has (2) Y and Z and one X motor
// These will not match the silkscreen or schematic descriptions
#define CPU_MAP_NAME "CPU_MAP_LOWRIDER"
#define USE_GANGED_AXES // allow two motors on an axis
#define X_STEP_PIN GPIO_NUM_27 // use Z labeled connector
#define X_DIRECTION_PIN GPIO_NUM_33 // use Z labeled connector
#define Y_STEP_PIN GPIO_NUM_14
#define Y_STEP_B_PIN GPIO_NUM_21 // ganged motor
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Y_AXIS_SQUARING
#define Z_STEP_PIN GPIO_NUM_12 // use X labeled connector
#define Z_STEP_B_PIN GPIO_NUM_22 // use X labeled connector
#define Z_DIRECTION_PIN GPIO_NUM_26 // use X labeled connector
#define Z_AXIS_SQUARING
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
// Note: if you use PWM rather than relay, you could map GPIO_NUM_17 to mist or flood
#define USE_SPINDLE_RELAY
#ifdef USE_SPINDLE_RELAY
#define SPINDLE_PWM_PIN GPIO_NUM_17
#else
#define SPINDLE_PWM_PIN GPIO_NUM_16
#define SPINDLE_ENABLE_PIN GPIO_NUM_32
#endif
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
// Note: Only uncomment this if USE_SPINDLE_RELAY is commented out.
// Relay can be used for Spindle or Coolant
//#define COOLANT_FLOOD_PIN GPIO_NUM_17
#define X_LIMIT_PIN GPIO_NUM_15
#define Y_LIMIT_PIN GPIO_NUM_4
#define Z_LIMIT_PIN GPIO_NUM_2
#define LIMIT_MASK B111
#define PROBE_PIN GPIO_NUM_35
// The default value in config.h is wrong for this controller
#ifdef INVERT_CONTROL_PIN_MASK
#undef INVERT_CONTROL_PIN_MASK
#endif
#define INVERT_CONTROL_PIN_MASK B1110
// Note: check the #define IGNORE_CONTROL_PINS is the way you want in config.h
#define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup
#define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup
#endif
#ifdef CPU_MAP_TMC2130_PEN
#define CPU_MAP_NAME "ESP32_TMC2130_PEN"
#define USE_RMT_STEPS
#define USE_TMC2130 // make sure you assign chip select pins to each axis
#define X_STEP_PIN GPIO_NUM_12
#define X_DIRECTION_PIN GPIO_NUM_26
#define X_CS_PIN GPIO_NUM_17 //chip select
#define X_RMT_CHANNEL 0
#define Y_STEP_PIN GPIO_NUM_14
#define Y_DIRECTION_PIN GPIO_NUM_25
#define Y_CS_PIN GPIO_NUM_16 //chip select
#define Y_RMT_CHANNEL 1
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
// *** the flood coolant feature code is activated by defining this pins
// *** Comment it out to use the pin for other features
//#define COOLANT_FLOOD_PIN GPIO_NUM_16
//#define COOLANT_MIST_PIN GPIO_NUM_21
// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still
// use a virtual spindle. Do not comment out the other parameters for the spindle.
//#define SPINDLE_PWM_PIN GPIO_NUM_17
#define SPINDLE_PWM_CHANNEL 0
// PWM Generator is based on 80,000,000 Hz counter
// Therefor the freq determines the resolution
// 80,000,000 / freq = max resolution
// For 5000 that is 80,000,000 / 5000 = 16000
// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE = 13bits (8192)
#define SPINDLE_PWM_BASE_FREQ 5000 // Hz
#define SPINDLE_PWM_BIT_PRECISION 8 // be sure to match this with SPINDLE_PWM_MAX_VALUE
#define SPINDLE_PWM_OFF_VALUE 0
#define SPINDLE_PWM_MAX_VALUE 255 // (2^SPINDLE_PWM_BIT_PRECISION)
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)
#define X_LIMIT_PIN GPIO_NUM_2
#define Y_LIMIT_PIN GPIO_NUM_4
#define LIMIT_MASK B11
#endif
// ================= common to all machines ================================
// These are some ESP32 CPU Settings that the program needs, but are generally not changed
@@ -238,7 +1092,6 @@
#define PROBE_MASK 1 // don't change
#define CONTROL_MASK B1111 // don't change
#define INVERT_CONTROL_PIN_MASK B1110 // don't change
// =======================================================================

Binary file not shown.

View File

@@ -42,7 +42,7 @@
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 2 // MPos enabled
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
@@ -82,102 +82,63 @@
#endif
#ifdef DEFAULTS_PEN_LASER
#ifdef DEFAULTS_MPCNC
// Grbl generic default settings. Should work across different machines.
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // msec (0-254, 255 keeps steppers enabled)
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 0 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 0 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 2 // MPos enabled
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_DIR_MASK 3 // move positive dir Z, negative X,Y
#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 2000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // 255 = Keep steppers on
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 0 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 1
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 1 // false
#define DEFAULT_HOMING_DIR_MASK 3 // move positive dir Z,negative X,Y
#define DEFAULT_HOMING_FEED_RATE 600.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 2000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.5 // mm
#ifdef USE_SPINDLE_RELAY
#define DEFAULT_SPINDLE_RPM_MAX 1.0 // must be 1 so PWM duty is alway 100% to prevent relay damage
#else
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // can be change to your spindle max
#endif
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 200.0
#define DEFAULT_Y_STEPS_PER_MM 200.0
#define DEFAULT_Z_STEPS_PER_MM 800.0
#define DEFAULT_X_MAX_RATE 8000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 8000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 3000.0 // mm/min
#define DEFAULT_X_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (100.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_X_MAX_TRAVEL 500.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 500.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 80.0 // mm NOTE: Must be a positive value.
#endif
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 80.0
#define DEFAULT_Y_STEPS_PER_MM 80.0
#define DEFAULT_Z_STEPS_PER_MM 80.0
#define DEFAULT_X_MAX_RATE 12000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 12000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 5000.0 // mm/min
#define DEFAULT_X_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (200.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_X_MAX_TRAVEL 100.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 100.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 10.0 // mm NOTE: Must be a positive value.
#endif
#ifdef DEFAULTS_MIDTBOT
// Grbl generic default settings. Should work across different machines.
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // msec (0-254, 255 keeps steppers enabled)
#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t
#define DEFAULT_DIRECTION_INVERT_MASK 0 // uint8_t
#define DEFAULT_INVERT_ST_ENABLE 0 // boolean
#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean
#define DEFAULT_INVERT_PROBE_PIN 0 // boolean
#define DEFAULT_STATUS_REPORT_MASK 2 // MPos enabled
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 1 // false
#define DEFAULT_HOMING_DIR_MASK 1 // move neg in X, pos in Y
#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 3000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_X_STEPS_PER_MM 400.0
#define DEFAULT_Y_STEPS_PER_MM 200.0
#define DEFAULT_Z_STEPS_PER_MM 100.0 // DEFAULT CAL VALUE !!
#define DEFAULT_X_MAX_RATE 10000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 10000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 10000.0 // mm/min
#define DEFAULT_X_ACCELERATION (400.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (400.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (400.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_X_MAX_TRAVEL 90.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 90.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 100.0 // DEFAULT CAL VALUE !!
#endif
#endif

100
Grbl_Esp32/espresponse.cpp Normal file
View File

@@ -0,0 +1,100 @@
/*
espresponse.cpp - GRBL_ESP response class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "espresponse.h"
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
#include "web_server.h"
#include <WebServer.h>
#endif
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
ESPResponseStream::ESPResponseStream(WebServer * webserver){
_header_sent=false;
_webserver = webserver;
_client = CLIENT_WEBUI;
}
#endif
ESPResponseStream::ESPResponseStream(uint8_t client){
_client = client;
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
_header_sent=false;
_webserver = NULL;
#endif
}
void ESPResponseStream::println(const char *data){
print(data);
if (_client == CLIENT_TELNET) print("\r\n");
else print("\n");
}
//helper to format size to readable string
String ESPResponseStream::formatBytes (uint64_t bytes)
{
if (bytes < 1024) {
return String ((uint16_t)bytes) + " B";
} else if (bytes < (1024 * 1024) ) {
return String ((float)(bytes / 1024.0),2) + " KB";
} else if (bytes < (1024 * 1024 * 1024) ) {
return String ((float)(bytes / 1024.0 / 1024.0),2) + " MB";
} else {
return String ((float)(bytes / 1024.0 / 1024.0 / 1024.0),2) + " GB";
}
}
void ESPResponseStream::print(const char *data){
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
if (_webserver) {
if (!_header_sent) {
_webserver->setContentLength(CONTENT_LENGTH_UNKNOWN);
_webserver->sendHeader("Content-Type","text/html");
_webserver->sendHeader("Cache-Control","no-cache");
_webserver->send(200);
_header_sent = true;
}
_buffer+=data;
if (_buffer.length() > 1200) {
//send data
_webserver->sendContent(_buffer);
//reset buffer
_buffer = "";
}
return;
}
#endif
if (_client == CLIENT_WEBUI) return; //this is sanity check
grbl_send(_client, data);
}
void ESPResponseStream::flush(){
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
if (_webserver) {
if(_header_sent) {
//send data
if(_buffer.length() > 0)_webserver->sendContent(_buffer);
//close connection
_webserver->sendContent("");
}
_header_sent = false;
_buffer = "";
}
#endif
}

49
Grbl_Esp32/espresponse.h Normal file
View File

@@ -0,0 +1,49 @@
/*
espresponse.h - GRBL_ESP response class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ESPRESPONSE_h
#define ESPRESPONSE_h
#include "config.h"
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
class WebServer;
#endif
class ESPResponseStream{
public:
void print(const char *data);
void println(const char *data);
void flush();
static String formatBytes (uint64_t bytes);
uint8_t client() {return _client;}
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
ESPResponseStream(WebServer * webserver);
#endif
ESPResponseStream(uint8_t client);
private:
uint8_t _client;
#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI)
bool _header_sent;
WebServer * _webserver;
String _buffer;
#endif
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
// Grbl versioning system
#define GRBL_VERSION "1.1f"
#define GRBL_VERSION_BUILD "20180917"
#define GRBL_VERSION_BUILD "20190622"
//#include <sdkconfig.h>
#include <Arduino.h>
@@ -43,7 +43,7 @@
#include "planner.h"
#include "coolant_control.h"
#include "eeprom.h"
#include "grbl_eeprom.h"
#include "gcode.h"
#include "grbl_limits.h"
#include "motion_control.h"
@@ -57,7 +57,7 @@
#include "jog.h"
#ifdef ENABLE_BLUETOOTH
#include "grbl_bluetooth.h"
#include "BTconfig.h"
#endif
#ifdef ENABLE_SD_CARD
@@ -72,7 +72,19 @@
#ifdef ENABLE_TELNET
#include "telnet_server.h"
#endif
#ifdef ENABLE_NOTIFICATIONS
#include "notifications_service.h"
#endif
#endif
#include "servo_pen.h"
#include "solenoid_pen.h"
#ifdef USE_SERVO_AXES
#include "servo_axis.h"
#endif
#ifdef USE_TMC2130
#include "TMC2130.h" // https://github.com/teemuatlut/TMC2130Stepper
#endif

View File

@@ -1,15 +0,0 @@
#include "grbl.h"
#ifdef ENABLE_BLUETOOTH
BluetoothSerial SerialBT;
void bluetooth_init(char *name)
{
if (!SerialBT.begin(name))
{
report_status_message(STATUS_BT_FAIL_BEGIN, CLIENT_SERIAL);
}
}
#endif

View File

@@ -1,14 +0,0 @@
#ifndef grbl_bluetooth_h
#define grbl_bluetooth_h
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
#include "grbl.h"
#include "BluetoothSerial.h"
extern BluetoothSerial SerialBT;
void bluetooth_init(char *name);
#endif

View File

@@ -18,8 +18,8 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef eeprom_h
#define eeprom_h
#ifndef eeprom_memcpy_h
#define eeprom_memcpy_h
#include "grbl.h"

View File

@@ -27,6 +27,7 @@
#include "grbl.h"
xQueueHandle limit_sw_queue; // used by limit switch debouncing
// Homing axis search distance multiplier. Computed by this value times the cycle travel.
#ifndef HOMING_AXIS_SEARCH_SCALAR
@@ -38,25 +39,32 @@
void IRAM_ATTR isr_limit_switches()
{
// Ignore limit switches if already in an alarm state or in-process of executing an alarm.
// Ignore limit switches if already in an alarm state or in-process of executing an alarm.
// When in the alarm state, Grbl should have been reset or will force a reset, so any pending
// moves in the planner and serial buffers are all cleared and newly sent blocks will be
// locked out until a homing cycle or a kill lock command. Allows the user to disable the hard
// limit setting if their limits are constantly triggering after a reset and move their axes.
if ( ( sys.state != STATE_ALARM) & (bit_isfalse(sys.state, STATE_HOMING)) ) {
if (!(sys_rt_exec_alarm)) {
#ifdef HARD_LIMIT_FORCE_STATE_CHECK
// Check limit pin state.
if (limits_get_state()) {
mc_reset(); // Initiate system kill.
system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event
}
#else
mc_reset(); // Initiate system kill.
system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event
#endif
}
if ( ( sys.state != STATE_ALARM) & (bit_isfalse(sys.state, STATE_HOMING)) ) {
if (!(sys_rt_exec_alarm)) {
#ifdef ENABLE_SOFTWARE_DEBOUNCE
// we will start a task that will recheck the switches after a small delay
int evt;
xQueueSendFromISR(limit_sw_queue, &evt, NULL);
#else
#ifdef HARD_LIMIT_FORCE_STATE_CHECK
// Check limit pin state.
if (limits_get_state()) {
mc_reset(); // Initiate system kill.
system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event
}
#else
mc_reset(); // Initiate system kill.
system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event
#endif
#endif
}
}
}
@@ -299,15 +307,17 @@ void limits_init()
limits_disable();
}
// TODO Debounce
/*
#ifdef ENABLE_SOFTWARE_DEBOUNCE
MCUSR &= ~(1<<WDRF);
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDP0); // Set time-out at ~32msec.
#endif
*/
// setup task used for debouncing
limit_sw_queue = xQueueCreate(10, sizeof( int ));
xTaskCreate(limitCheckTask,
"limitCheckTask",
2048,
NULL,
5, // priority
NULL);
}
@@ -325,66 +335,104 @@ void limits_disable()
// number in bit position, i.e. Z_AXIS is (1<<2) or bit 2, and Y_AXIS is (1<<1) or bit 1.
uint8_t limits_get_state()
{
uint8_t limit_state = 0;
uint8_t pin = 0;
uint8_t limit_state = 0;
uint8_t pin = 0;
#ifdef X_LIMIT_PIN
pin += digitalRead(X_LIMIT_PIN);
#endif
#ifdef Y_LIMIT_PIN
pin += (digitalRead(Y_LIMIT_PIN) << Y_AXIS);
#endif
#ifdef Z_LIMIT_PIN
pin += (digitalRead(Z_LIMIT_PIN) << Z_AXIS);
#endif
#ifdef INVERT_LIMIT_PIN_MASK // not normally used..unless you have both normal and inverted switches
pin ^= INVERT_LIMIT_PIN_MASK;
#endif
pin ^= INVERT_LIMIT_PIN_MASK;
#endif
if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS))
{
if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) {
pin ^= LIMIT_MASK;
}
if (pin) {
uint8_t idx;
for (idx=0; idx<N_AXIS; idx++) {
if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }
}
}
return(limit_state);
if (pin) {
uint8_t idx;
for (idx=0; idx<N_AXIS; idx++) {
if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }
}
}
return(limit_state);
}
// Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed,
// the workspace volume is in all negative space, and the system is in normal operation.
// NOTE: Used by jogging to limit travel within soft-limit volume.
void limits_soft_check(float *target)
{
if (system_check_travel_limits(target)) {
sys.soft_limit = true;
// Force feed hold if cycle is active. All buffered blocks are guaranteed to be within
// workspace volume so just come to a controlled stop so position is not lost. When complete
// enter alarm mode.
if (sys.state == STATE_CYCLE) {
system_set_exec_state_flag(EXEC_FEED_HOLD);
do {
protocol_execute_realtime();
if (sys.abort) { return; }
} while ( sys.state != STATE_IDLE );
if (system_check_travel_limits(target)) {
sys.soft_limit = true;
// Force feed hold if cycle is active. All buffered blocks are guaranteed to be within
// workspace volume so just come to a controlled stop so position is not lost. When complete
// enter alarm mode.
if (sys.state == STATE_CYCLE) {
system_set_exec_state_flag(EXEC_FEED_HOLD);
do {
protocol_execute_realtime();
if (sys.abort) { return; }
} while ( sys.state != STATE_IDLE );
}
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
system_set_exec_alarm(EXEC_ALARM_SOFT_LIMIT); // Indicate soft limit critical event
protocol_execute_realtime(); // Execute to enter critical event loop and system abort
return;
}
}
// this is the task
void limitCheckTask(void *pvParameters)
{
while(true) {
int evt;
xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue
vTaskDelay( DEBOUNCE_PERIOD / portTICK_PERIOD_MS ); // delay a while
if (limits_get_state()) {
mc_reset(); // Initiate system kill.
system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event
}
}
}
// return true if the axis is defined as a squared axis
// Squaring: is used on gantry type axes that have two motors
// Each motor with touch off its own switch to square the axis
bool axis_is_squared(uint8_t axis_mask)
{
// Note: multi-axis homing returns false because it will not match any of the following
if (axis_mask == (1<<X_AXIS)) {
#ifdef X_AXIS_SQUARING
return true;
#endif
}
if (axis_mask == (1<<Y_AXIS)) {
#ifdef Y_AXIS_SQUARING
return true;
#endif
}
if (axis_mask == (1<<Z_AXIS)) {
#ifdef Z_AXIS_SQUARING
return true;
#endif
}
return false;
}

View File

@@ -28,6 +28,9 @@
#ifndef grbl_limits_h
#define grbl_limits_h
#define SQUARING_MODE_DUAL 0 // both motors run
#define SQUARING_MODE_A 1 // A motor runs
#define SQUARING_MODE_B 2 // B motor runs
// Initialize the limits module
void limits_init();
@@ -46,4 +49,9 @@ void limits_soft_check(float *target);
void isr_limit_switches();
#endif
bool axis_is_squared(uint8_t axis_mask);
// A task that runs after a limit switch interrupt.
void limitCheckTask(void *pvParameters);
#endif

View File

@@ -27,29 +27,30 @@
File myFile;
bool SD_ready_next = false; // Grbl has processed a line and is waiting for another
uint8_t SD_client = CLIENT_SERIAL;
uint32_t sd_current_line_number; // stores the most recent line number read from the SD
// attempt to mount the SD card
bool sd_mount()
/*bool sd_mount()
{
if(!SD.begin()) {
report_status_message(STATUS_SD_FAILED_MOUNT, CLIENT_SERIAL);
return false;
}
return true;
}
}*/
void listDir(fs::FS &fs, const char * dirname, uint8_t levels)
void listDir(fs::FS &fs, const char * dirname, uint8_t levels, uint8_t client)
{
char temp_filename[128]; // to help filter by extension TODO: 128 needs a definition based on something
//char temp_filename[128]; // to help filter by extension TODO: 128 needs a definition based on something
File root = fs.open(dirname);
if(!root) {
report_status_message(STATUS_SD_FAILED_OPEN_DIR, CLIENT_SERIAL);
report_status_message(STATUS_SD_FAILED_OPEN_DIR, client);
return;
}
if(!root.isDirectory()) {
report_status_message(STATUS_SD_DIR_NOT_FOUND, CLIENT_SERIAL);
report_status_message(STATUS_SD_DIR_NOT_FOUND, client);
return;
}
@@ -57,7 +58,7 @@ void listDir(fs::FS &fs, const char * dirname, uint8_t levels)
while(file) {
if(file.isDirectory()) {
if(levels) {
listDir(fs, file.name(), levels -1);
listDir(fs, file.name(), levels -1, client);
}
} else {
grbl_sendf(CLIENT_ALL, "[FILE:%s|SIZE:%d]\r\n", file.name(), file.size());
@@ -71,7 +72,7 @@ boolean openFile(fs::FS &fs, const char * path)
myFile = fs.open(path);
if(!myFile) {
report_status_message(STATUS_SD_FAILED_READ, CLIENT_SERIAL);
//report_status_message(STATUS_SD_FAILED_READ, CLIENT_SERIAL);
return false;
}
@@ -108,7 +109,7 @@ boolean readFileLine(char *line)
uint8_t line_flags = 0;
if (!myFile) {
report_status_message(STATUS_SD_FAILED_READ, CLIENT_SERIAL);
report_status_message(STATUS_SD_FAILED_READ, SD_client);
return false;
}
@@ -131,7 +132,9 @@ boolean readFileLine(char *line)
if (!(line_flags & LINE_FLAG_COMMENT_PARENTHESES)) { // semi colon inside parentheses do not mean anything
line_flags |= LINE_FLAG_COMMENT_SEMICOLON;
}
} else if (c == '\n') { // found the newline, so mark the end and return true
} else if (c == '%') {
// discard this character
} else if (c == '\n') { // found the newline, so mark the end and return true
line[index] = '\0';
return true;
} else { // add characters to the line
@@ -144,7 +147,7 @@ boolean readFileLine(char *line)
if (index == 255) { // name is too long so return false
line[index] = '\0';
report_status_message(STATUS_OVERFLOW, CLIENT_SERIAL);
report_status_message(STATUS_OVERFLOW, SD_client);
return false;
}
}
@@ -193,18 +196,13 @@ uint8_t get_sd_state(bool refresh)
}
//SD is idle or not detected, let see if still the case
if (sd_state == SDCARD_IDLE) {
SD.end();
sd_state = SDCARD_NOT_PRESENT;
//using default value for speed ? should be parameter
//refresh content if card was removed
if (!SD.begin()) {
sd_state = SDCARD_NOT_PRESENT;
} else {
if ( !(SD.cardSize() > 0 )) {
sd_state = SDCARD_NOT_PRESENT;
}
if (SD.begin()) {
if ( SD.cardSize() > 0 )sd_state = SDCARD_IDLE;
}
}
return sd_state;
}
@@ -217,7 +215,7 @@ uint8_t set_sd_state(uint8_t flag)
void sd_get_current_filename(char* name)
{
if (myFile != NULL) {
if (myFile) {
strcpy(name, myFile.name());
} else {
name[0] = 0;

View File

@@ -36,11 +36,12 @@
extern bool SD_ready_next; // Grbl has processed a line and is waiting for another
extern uint8_t SD_client;
bool sd_mount();
//bool sd_mount();
uint8_t get_sd_state(bool refresh);
uint8_t set_sd_state(uint8_t flag);
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void listDir(fs::FS &fs, const char * dirname, uint8_t levels, uint8_t client);
boolean openFile(fs::FS &fs, const char * path);
boolean closeFile();
boolean readFileLine(char *line);

View File

@@ -24,6 +24,7 @@
#include "grbl.h"
uint8_t ganged_mode = SQUARING_MODE_DUAL;
// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
@@ -223,12 +224,44 @@ void mc_homing_cycle(uint8_t cycle_mask)
#endif
{
// Search to engage all axes limit switches at faster homing seek rate.
limits_go_home(HOMING_CYCLE_0); // Homing cycle 0
if (! axis_is_squared(HOMING_CYCLE_0))
limits_go_home(HOMING_CYCLE_0); // Homing cycle 0
else {
ganged_mode = SQUARING_MODE_DUAL;
limits_go_home(HOMING_CYCLE_0);
ganged_mode = SQUARING_MODE_A;
limits_go_home(HOMING_CYCLE_0);
ganged_mode = SQUARING_MODE_B;
limits_go_home(HOMING_CYCLE_0);
ganged_mode = SQUARING_MODE_DUAL; // always return to dual
}
#ifdef HOMING_CYCLE_1
limits_go_home(HOMING_CYCLE_1); // Homing cycle 1
if (! axis_is_squared(HOMING_CYCLE_1))
limits_go_home(HOMING_CYCLE_1);
else {
ganged_mode = SQUARING_MODE_DUAL;
limits_go_home(HOMING_CYCLE_1);
ganged_mode = SQUARING_MODE_A;
limits_go_home(HOMING_CYCLE_1);
ganged_mode = SQUARING_MODE_B;
limits_go_home(HOMING_CYCLE_1);
ganged_mode = SQUARING_MODE_DUAL; // always return to dual
}
#endif
#ifdef HOMING_CYCLE_2
limits_go_home(HOMING_CYCLE_2); // Homing cycle 2
if (! axis_is_squared(HOMING_CYCLE_2))
limits_go_home(HOMING_CYCLE_2);
else {
ganged_mode = SQUARING_MODE_DUAL;
limits_go_home(HOMING_CYCLE_2);
ganged_mode = SQUARING_MODE_A;
limits_go_home(HOMING_CYCLE_2);
ganged_mode = SQUARING_MODE_B;
limits_go_home(HOMING_CYCLE_2);
ganged_mode = SQUARING_MODE_DUAL; // always return to dual
}
#endif
#ifdef HOMING_CYCLE_3
@@ -371,6 +404,7 @@ void mc_reset()
#ifdef ENABLE_SD_CARD
// do we need to stop a running SD job?
if (get_sd_state(false) == SDCARD_BUSY_PRINTING) {
//Report print stopped
report_feedback_message(MESSAGE_SD_FILE_QUIT);
closeFile();
}
@@ -388,5 +422,11 @@ void mc_reset()
st_go_idle(); // Force kill steppers. Position has likely been lost.
}
#ifdef USE_GANGED_AXES
ganged_mode = SQUARING_MODE_DUAL; // in case an error occurred during squaring
#endif
}
}

View File

@@ -0,0 +1,411 @@
/*
notifications_service.cpp - notifications service functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//Inspired by following sources
//* Line :
// - https://github.com/TridentTD/TridentTD_LineNotify
// - https://notify-bot.line.me/doc/en/
//* Pushover:
// - https://github.com/ArduinoHannover/Pushover
// - https://pushover.net/api
//* Email:
// - https://github.com/CosmicBoris/ESP8266SMTP
// - https://www.electronicshub.org/send-an-email-using-esp8266/
#include "config.h"
#ifdef ENABLE_NOTIFICATIONS
#include "grbl.h"
#include "commands.h"
#include "notifications_service.h"
#include <WiFiClientSecure.h>
#include <Preferences.h>
#include <base64.h>
#include "wificonfig.h"
#define PUSHOVERTIMEOUT 5000
#define PUSHOVERSERVER "api.pushover.net"
#define PUSHOVERPORT 443
#define LINETIMEOUT 5000
#define LINESERVER "notify-api.line.me"
#define LINEPORT 443
#define EMAILTIMEOUT 5000
NotificationsService notificationsservice;
bool Wait4Answer(WiFiClientSecure & client, const char * linetrigger, const char * expected_answer, uint32_t timeout)
{
if(client.connected()) {
String answer;
uint32_t starttimeout = millis();
while (client.connected() && ((millis() -starttimeout) < timeout)) {
answer = client.readStringUntil('\n');
log_d("Answer: %s", answer.c_str());
if ((answer.indexOf(linetrigger) != -1) || (strlen(linetrigger) == 0)) {
break;
}
COMMANDS::wait(10);
}
if (strlen(expected_answer) == 0) {
log_d("Answer ignored as requested");
return true;
}
if(answer.indexOf(expected_answer) == -1) {
log_d("Did not got answer!");
return false;
} else {
log_d("Got expected answer");
return true;
}
}
log_d("Failed to send message");
return false;
}
NotificationsService::NotificationsService()
{
_started = false;
_notificationType = 0;
_token1 = "";
_token1 = "";
_settings = "";
}
NotificationsService::~NotificationsService()
{
end();
}
bool NotificationsService::started()
{
return _started;
}
const char * NotificationsService::getTypeString()
{
switch(_notificationType) {
case ESP_PUSHOVER_NOTIFICATION:
return "Pushover";
case ESP_EMAIL_NOTIFICATION:
return "Email";
case ESP_LINE_NOTIFICATION:
return "Line";
default:
break;
}
return "None";
}
bool NotificationsService::sendMSG(const char * title, const char * message)
{
if (!_started) return false;
if (!((strlen(title) == 0) && (strlen(message) == 0))) {
switch(_notificationType) {
case ESP_PUSHOVER_NOTIFICATION:
return sendPushoverMSG(title,message);
break;
case ESP_EMAIL_NOTIFICATION:
return sendEmailMSG(title,message);
break;
case ESP_LINE_NOTIFICATION :
return sendLineMSG(title,message);
break;
default:
break;
}
}
return false;
}
//Messages are currently limited to 1024 4-byte UTF-8 characters
//but we do not do any check
bool NotificationsService::sendPushoverMSG(const char * title, const char * message)
{
String data;
String postcmd;
bool res;
WiFiClientSecure Notificationclient;
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {
log_d("Error connecting server %s:%d", _serveraddress.c_str(), _port);
return false;
}
//build data for post
data = "user=";
data += _token1;
data += "&token=";
data += _token2;;
data +="&title=";
data += title;
data += "&message=";
data += message;
data += "&device=";
data += wifi_config.Hostname();
//build post query
postcmd = "POST /1/messages.json HTTP/1.1\r\nHost: api.pushover.net\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Length: ";
postcmd += data.length();
postcmd +="\r\n\r\n";
postcmd +=data;
log_d("Query: %s", postcmd.c_str());
//send query
Notificationclient.print(postcmd);
res = Wait4Answer(Notificationclient, "{", "\"status\":1", PUSHOVERTIMEOUT);
Notificationclient.stop();
return res;
}
bool NotificationsService::sendEmailMSG(const char * title, const char * message)
{
WiFiClientSecure Notificationclient;
log_d("Connect to server");
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {
log_d("Error connecting server %s:%d", _serveraddress.c_str(), _port);
return false;
}
//Check answer of connection
if(!Wait4Answer(Notificationclient, "220", "220", EMAILTIMEOUT)) {
log_d("Connection failed!");
return false;
}
//Do HELO
log_d("HELO");
Notificationclient.print("HELO friend\r\n");
if(!Wait4Answer(Notificationclient, "250", "250", EMAILTIMEOUT)) {
log_d("HELO failed!");
return false;
}
log_d("AUTH LOGIN");
//Request AUthentication
Notificationclient.print("AUTH LOGIN\r\n");
if(!Wait4Answer(Notificationclient, "334", "334", EMAILTIMEOUT)) {
log_d("AUTH LOGIN failed!");
return false;
}
log_d("Send LOGIN");
//sent Login
Notificationclient.printf("%s\r\n",_token1.c_str());
if(!Wait4Answer(Notificationclient, "334", "334", EMAILTIMEOUT)) {
log_d("Sent login failed!");
return false;
}
log_d("Send PASSWORD");
//Send password
Notificationclient.printf("%s\r\n",_token2.c_str());
if(!Wait4Answer(Notificationclient, "235", "235", EMAILTIMEOUT)) {
log_d("Sent password failed!");
return false;
}
log_d("MAIL FROM");
//Send From
Notificationclient.printf("MAIL FROM: <%s>\r\n",_settings.c_str());
if(!Wait4Answer(Notificationclient, "250", "250", EMAILTIMEOUT)) {
log_d("MAIL FROM failed!");
return false;
}
log_d("RCPT TO");
//Send To
Notificationclient.printf("RCPT TO: <%s>\r\n",_settings.c_str());
if(!Wait4Answer(Notificationclient, "250", "250", EMAILTIMEOUT)) {
log_d("RCPT TO failed!");
return false;
}
log_d("DATA");
//Send Data
Notificationclient.print("DATA\r\n");
if(!Wait4Answer(Notificationclient, "354", "354", EMAILTIMEOUT)) {
log_d("Preparing DATA failed!");
return false;
}
log_d("Send message");
//Send message
Notificationclient.printf("From:ESP3D<%s>\r\n",_settings.c_str());
Notificationclient.printf("To: <%s>\r\n",_settings.c_str());
Notificationclient.printf("Subject: %s\r\n\r\n",title);
Notificationclient.println(message);
log_d("Send final dot");
//Send Final dot
Notificationclient.print(".\r\n");
if(!Wait4Answer(Notificationclient, "250", "250", EMAILTIMEOUT)) {
log_d("Sending final dot failed!");
return false;
}
log_d("QUIT");
//Quit
Notificationclient.print("QUIT\r\n");
if(!Wait4Answer(Notificationclient, "221", "221", EMAILTIMEOUT)) {
log_d("QUIT failed!");
return false;
}
Notificationclient.stop();
return true;
}
bool NotificationsService::sendLineMSG(const char * title, const char * message)
{
String data;
String postcmd;
bool res;
WiFiClientSecure Notificationclient;
(void)title;
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {
log_d("Error connecting server %s:%d", _serveraddress.c_str(), _port);
return false;
}
//build data for post
data = "message=";
data += message;
//build post query
postcmd = "POST /api/notify HTTP/1.1\r\nHost: notify-api.line.me\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\n";
postcmd +="Authorization: Bearer ";
postcmd += _token1 + "\r\n";
postcmd += "Content-Length: ";
postcmd += data.length();
postcmd +="\r\n\r\n";
postcmd +=data;
log_d("Query: %s", postcmd.c_str());
//send query
Notificationclient.print(postcmd);
res = Wait4Answer(Notificationclient, "{", "\"status\":200", LINETIMEOUT);
Notificationclient.stop();
return res;
}
//Email#serveraddress:port
bool NotificationsService::getPortFromSettings()
{
Preferences prefs;
String defV = DEFAULT_TOKEN;
prefs.begin(NAMESPACE, true);
String tmp = prefs.getString(NOTIFICATION_TS, defV);
prefs.end();
int pos = tmp.lastIndexOf(':');
if (pos == -1) {
return false;
}
_port= tmp.substring(pos+1).toInt();
log_d("port : %d", _port);
if (_port > 0) {
return true;
} else {
return false;
}
}
//Email#serveraddress:port
bool NotificationsService::getServerAddressFromSettings()
{
Preferences prefs;
String defV = DEFAULT_TOKEN;
prefs.begin(NAMESPACE, true);
String tmp = prefs.getString(NOTIFICATION_TS, defV);
prefs.end();
int pos1 = tmp.indexOf('#');
int pos2 = tmp.lastIndexOf(':');
if ((pos1 == -1) || (pos2 == -1)) {
return false;
}
//TODO add a check for valid email ?
_serveraddress = tmp.substring(pos1+1, pos2);
log_d("server : %s", _serveraddress.c_str());
return true;
}
//Email#serveraddress:port
bool NotificationsService::getEmailFromSettings()
{
Preferences prefs;
String defV = DEFAULT_TOKEN;
prefs.begin(NAMESPACE, true);
String tmp = prefs.getString(NOTIFICATION_TS, defV);
prefs.end();
int pos = tmp.indexOf('#');
if (pos == -1) {
return false;
}
_settings = tmp.substring(0, pos);
log_d("email : %s", _settings.c_str());
//TODO add a check for valid email ?
return true;
}
bool NotificationsService::begin()
{
bool res = true;
end();
Preferences prefs;
String defV = DEFAULT_TOKEN;
prefs.begin(NAMESPACE, true);
_notificationType = prefs.getChar(NOTIFICATION_TYPE, DEFAULT_NOTIFICATION_TYPE);
switch(_notificationType) {
case 0: //no notification = no error but no start
return true;
case ESP_PUSHOVER_NOTIFICATION:
_token1 = prefs.getString(NOTIFICATION_T1, defV);
_token2 = prefs.getString(NOTIFICATION_T2, defV);
_port = PUSHOVERPORT;
_serveraddress = PUSHOVERSERVER;
break;
case ESP_LINE_NOTIFICATION:
_token1 = prefs.getString(NOTIFICATION_T1, defV);
_port = LINEPORT;
_serveraddress = LINESERVER;
break;
case ESP_EMAIL_NOTIFICATION:
_token1 = base64::encode(prefs.getString(NOTIFICATION_T1, defV));
_token2 = base64::encode(prefs.getString(NOTIFICATION_T2, defV));
//log_d("%s",Settings_ESP3D::read_string(ESP_NOTIFICATION_TOKEN1));
//log_d("%s",Settings_ESP3D::read_string(ESP_NOTIFICATION_TOKEN2));
if(!getEmailFromSettings() || !getPortFromSettings()|| !getServerAddressFromSettings()) {
prefs.end();
return false;
}
break;
default:
prefs.end();
return false;
break;
}
prefs.end();
if(WiFi.getMode() != WIFI_STA){
res = false;
}
if (!res) {
end();
}
_started = res;
return _started;
}
void NotificationsService::end()
{
if(!_started) {
return;
}
_started = false;
_notificationType = 0;
_token1 = "";
_token1 = "";
_settings = "";
_serveraddress = "";
_port = 0;
}
void NotificationsService::handle()
{
if (_started) {
}
}
#endif //ENABLE_NOTIFICATIONS

View File

@@ -0,0 +1,57 @@
/*
notifications_service.h - notifications service functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _NOTIFICATIONS_SERVICE_H
#define _NOTIFICATIONS_SERVICE_H
class NotificationsService
{
public:
NotificationsService();
~NotificationsService();
bool begin();
void end();
void handle();
bool sendMSG(const char * title, const char * message);
const char * getTypeString();
bool started();
private:
bool _started;
uint8_t _notificationType;
String _token1;
String _token2;
String _settings;
String _serveraddress;
uint16_t _port;
bool sendPushoverMSG(const char * title, const char * message);
bool sendEmailMSG(const char * title, const char * message);
bool sendLineMSG(const char * title, const char * message);
bool getPortFromSettings();
bool getServerAddressFromSettings();
bool getEmailFromSettings();
};
extern NotificationsService notificationsservice;
#endif //_NOTIFICATIONS_SERVICE_H

View File

@@ -57,7 +57,8 @@
#define isequal_position_vector(a,b) !(memcmp(a, b, sizeof(float)*N_AXIS))
// Bit field and masking macros
#define bit(n) (1 << n)
//Arduino.h:104:0: note: this is the location of the previous definition
//#define bit(n) (1 << n)
#define bit_true(x,mask) (x) |= (mask)
#define bit_false(x,mask) (x) &= ~(mask)
#define bit_istrue(x,mask) ((x & mask) != 0)

View File

@@ -137,14 +137,6 @@ void printFloat_CoordValue(float n) {
}
}
void printFloat_RateValue(float n) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
printFloat(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH);
} else {
printFloat(n,N_DECIMAL_RATEVALUE_MM);
}
}
// Debug tool to print free memory in bytes at the called point.
// NOTE: Keep commented unless using. Part of this function always gets compiled in.
// void printFreeMemory()

View File

@@ -24,11 +24,14 @@
#include "grbl.h"
#include "config.h"
#include "commands.h"
#include "espresponse.h"
// Define line flags. Includes comment type tracking and line overflow detection.
#define LINE_FLAG_OVERFLOW bit(0)
#define LINE_FLAG_COMMENT_PARENTHESES bit(1)
#define LINE_FLAG_COMMENT_SEMICOLON bit(2)
#define LINE_FLAG_BRACKET bit(3) // square bracket for WebUI commands
static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
@@ -87,11 +90,13 @@ void protocol_main_loop()
char fileLine[255];
if (readFileLine(fileLine)) {
SD_ready_next = false;
report_status_message(gc_execute_line(fileLine, CLIENT_SERIAL), CLIENT_SERIAL);
report_status_message(gc_execute_line(fileLine, SD_client), SD_client);
}
else {
closeFile(); // close file and clear SD ready/running flags
// TODO some type of alert
char temp[50];
sd_get_current_filename(temp);
grbl_notifyf("SD print done", "%s print is successful", temp);
closeFile(); // close file and clear SD ready/running flags
}
}
#endif
@@ -124,6 +129,13 @@ void protocol_main_loop()
} else if (line[0] == '$') {
// Grbl '$' system command
report_status_message(system_execute_line(line, client), client);
} else if (line[0] == '[') {
int cmd = 0;
String cmd_params;
if (COMMANDS::check_command (line, &cmd, cmd_params)) {
ESPResponseStream espresponse(client);
COMMANDS::execute_internal_command (cmd, cmd_params, LEVEL_GUEST, &espresponse);
} else grbl_sendf(client, "[MSG: Unknow Command...%s]\r\n", line);
} else if (sys.state & (STATE_ALARM | STATE_JOG)) {
// Everything else is gcode. Block if in alarm or jog mode.
report_status_message(STATUS_SYSTEM_GC_LOCK, client);
@@ -139,6 +151,9 @@ void protocol_main_loop()
} else {
if (line_flags) {
if (line_flags & LINE_FLAG_BRACKET) { // in bracket mode all characters are accepted
line[char_counter++] = c;
}
// Throw away all (except EOL) comment characters and overflow characters.
if (c == ')') {
// End of '()' comment. Resume line allowed.
@@ -163,8 +178,14 @@ void protocol_main_loop()
} else if (c == ';') {
// NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST.
line_flags |= LINE_FLAG_COMMENT_SEMICOLON;
} else if (c == '[') {
// For ESP3D bracket commands like [ESP100]<SSID>pwd=<admin password>
// prevents spaces being striped and converting to uppercase
line_flags |= LINE_FLAG_BRACKET;
line[char_counter++] = c; // capture this character
// TODO: Install '%' feature
// } else if (c == '%') {
} else if (c == '%') {
// Program start-end percent sign NOT SUPPORTED.
// NOTE: This maybe installed to tell Grbl when a program is running vs manual input,
// where, during a program, the system auto-cycle start will continue to execute

View File

@@ -48,9 +48,10 @@
#include "grbl.h"
#define DEFAULTBUFFERSIZE 64
// this is a generic send function that everything should use, so interfaces could be added (Bluetooth, etc)
void grbl_send(uint8_t client, char *text)
void grbl_send(uint8_t client, const char *text)
{
#ifdef ENABLE_BLUETOOTH
if (SerialBT.hasClient() && ( client == CLIENT_BT || client == CLIENT_ALL ) )
@@ -101,15 +102,54 @@ void grbl_sendf(uint8_t client, const char *format, ...)
}
}
//function to notify
void grbl_notify(const char *title, const char *msg){
#ifdef ENABLE_NOTIFICATIONS
notificationsservice.sendMSG(title, msg);
#endif
}
void grbl_notifyf(const char *title, const char *format, ...){
char loc_buf[64];
char * temp = loc_buf;
va_list arg;
va_list copy;
va_start(arg, format);
va_copy(copy, arg);
size_t len = vsnprintf(NULL, 0, format, arg);
va_end(copy);
if(len >= sizeof(loc_buf)){
temp = new char[len+1];
if(temp == NULL) {
return;
}
}
len = vsnprintf(temp, len+1, format, arg);
grbl_notify(title, temp);
va_end(arg);
if(len > 64){
delete[] temp;
}
}
// formats axis values into a string and returns that string in rpt
static void report_util_axis_values(float *axis_value, char *rpt) {
uint8_t idx;
char axisVal[10];
float unit_conv = 1.0; // unit conversion multiplier..default is mm
rpt[0] = '\0';
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES))
unit_conv = 1.0 / MM_PER_INCH;
for (idx=0; idx<N_AXIS; idx++) {
sprintf(axisVal, "%4.3f", axis_value[idx]);
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES))
sprintf(axisVal, "%4.4f", axis_value[idx] * unit_conv); // Report inches to 4 decimals
else
sprintf(axisVal, "%4.3f", axis_value[idx] * unit_conv); // Report mm to 3 decimals
strcat(rpt, axisVal);
if (idx < (N_AXIS-1))
@@ -119,7 +159,6 @@ static void report_util_axis_values(float *axis_value, char *rpt) {
}
}
void get_state(char *foo)
{
// pad them to same length
@@ -158,8 +197,16 @@ void report_status_message(uint8_t status_code, uint8_t client)
#ifdef ENABLE_SD_CARD
// do we need to stop a running SD job?
if (get_sd_state(false) == SDCARD_BUSY_PRINTING) {
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number());
closeFile();
if (status_code == STATUS_GCODE_UNSUPPORTED_COMMAND) {
grbl_sendf(client, "error:%d\r\n", status_code); // most senders seem to tolerate this error and keep on going
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number());
// don't close file
}
else {
grbl_notifyf("SD print error", "Error:%d during SD file at line: %d", status_code, sd_get_current_line_number());
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number());
closeFile();
}
return;
}
#endif
@@ -206,8 +253,11 @@ void report_feedback_message(uint8_t message_code) // OK to send to all clients
grbl_send(CLIENT_ALL, "[MSG:Restoring spindle]\r\n"); break;
case MESSAGE_SLEEP_MODE:
grbl_send(CLIENT_ALL, "[MSG:Sleeping]\r\n"); break;
#ifdef ENABLE_SD_CARD
case MESSAGE_SD_FILE_QUIT:
grbl_notifyf("SD print canceled", "Reset during SD file at line: %d", sd_get_current_line_number());
grbl_sendf(CLIENT_ALL, "[MSG:Reset during SD file at line: %d]\r\n", sd_get_current_line_number()); break;
#endif
}
}
@@ -215,7 +265,10 @@ void report_feedback_message(uint8_t message_code) // OK to send to all clients
// Welcome message
void report_init_message(uint8_t client)
{
grbl_send(client,"\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n");
grbl_send(client,"\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n");
#ifdef CPU_MAP_NAME
grbl_send(client,"[MSG:Using cpu_map..." CPU_MAP_NAME "]\r\n");
#endif
}
// Grbl help message
@@ -430,8 +483,13 @@ void report_gcode_modes(uint8_t client)
sprintf(temp, " T%d", gc_state.tool);
strcat(modes_rpt, temp);
sprintf(temp, " F%4.3f", gc_state.feed_rate);
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
sprintf(temp, " F%.1f", gc_state.feed_rate);
} else {
sprintf(temp, " F%.0f", gc_state.feed_rate);
}
strcat(modes_rpt, temp);
#ifdef VARIABLE_SPINDLE
@@ -529,6 +587,9 @@ void report_build_info(char *line, uint8_t client)
#if defined (ENABLE_WIFI)
grbl_send(client, (char *)wifi_config.info());
#endif
#if defined (ENABLE_BLUETOOTH)
grbl_send(client, (char *)bt_config.info());
#endif
}
@@ -617,12 +678,27 @@ void report_realtime_status(uint8_t client)
strcat(status, temp);
// Returns planner and serial read buffer states.
#ifdef REPORT_FIELD_BUFFER_STATE
if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_BUFFER_STATE)) {
sprintf(temp, "|Bf:%d,%d", plan_get_block_buffer_available(), serial_get_rx_buffer_available(CLIENT_SERIAL));
#ifdef REPORT_FIELD_BUFFER_STATE
if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_BUFFER_STATE)) {
int bufsize = DEFAULTBUFFERSIZE;
#if defined (ENABLE_WIFI) && defined(ENABLE_TELNET)
if (client == CLIENT_TELNET){
bufsize = telnet_server.get_rx_buffer_available();
}
#endif //ENABLE_WIFI && ENABLE_TELNET
#if defined(ENABLE_BLUETOOTH)
if (client == CLIENT_BT){
//TODO FIXME
bufsize = 512 - SerialBT.available();
}
#endif //ENABLE_BLUETOOTH
if (client == CLIENT_SERIAL){
bufsize = serial_get_rx_buffer_available(CLIENT_SERIAL);
}
sprintf(temp, "|Bf:%d,%d", plan_get_block_buffer_available(), bufsize);
strcat(status, temp);
}
#endif
#endif
#ifdef USE_LINE_NUMBERS
#ifdef REPORT_FIELD_LINE_NUMBERS
@@ -640,12 +716,19 @@ void report_realtime_status(uint8_t client)
// Report realtime feed speed
#ifdef REPORT_FIELD_CURRENT_FEED_SPEED
#ifdef VARIABLE_SPINDLE
sprintf(temp, "|FS:%.0f,%.0f", st_get_realtime_rate(), sys.spindle_speed);
#ifdef VARIABLE_SPINDLE
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
sprintf(temp, "|FS:%.1f,%.0f", st_get_realtime_rate(), sys.spindle_speed / MM_PER_INCH);
} else {
sprintf(temp, "|FS:%.0f,%.0f", st_get_realtime_rate(), sys.spindle_speed);
}
strcat(status, temp);
#else
sprintf(temp, "|F:%.0f", st_get_realtime_rate());
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
sprintf(temp, "|F:%.1f", st_get_realtime_rate() / MM_PER_INCH);
} else {
sprintf(temp, "|F:%.0f", st_get_realtime_rate());
}
strcat(status, temp);
#endif
#endif

View File

@@ -106,9 +106,13 @@
#define CLIENT_COUNT 4 // total number of client types regardless if they are used
// functions to send data to the user.
void grbl_send(uint8_t client, char *text);
void grbl_send(uint8_t client, const char *text);
void grbl_sendf(uint8_t client, const char *format, ...);
//function to notify
void grbl_notify(const char *title, const char *msg);
void grbl_notifyf(const char *title, const char *format, ...);
// Prints system status messages.
void report_status_message(uint8_t status_code, uint8_t client);
void report_realtime_steps();

View File

@@ -19,6 +19,7 @@
*/
#include "grbl.h"
#include "commands.h"
#define RX_RING_BUFFER (RX_BUFFER_SIZE+1)
#define TX_RING_BUFFER (TX_BUFFER_SIZE+1)
@@ -28,7 +29,7 @@ portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
uint8_t serial_rx_buffer[CLIENT_COUNT][RX_RING_BUFFER];
uint8_t serial_rx_buffer_head[CLIENT_COUNT] = {0};
volatile uint8_t serial_rx_buffer_tail[CLIENT_COUNT] = {0};
static TaskHandle_t serialCheckTaskHandle = 0;
// Returns the number of bytes available in the RX serial buffer.
uint8_t serial_get_rx_buffer_available(uint8_t client)
@@ -43,10 +44,10 @@ uint8_t serial_get_rx_buffer_available(uint8_t client)
void serial_init()
{
Serial.begin(BAUD_RATE);
serialCheckTaskHandle = 0;
// create a task to check for incoming data
xTaskCreatePinnedToCore( serialCheckTask, // task
"servoSyncTask", // name for task
"serialCheckTask", // name for task
8192, // size of task stack
NULL, // parameters
1, // priority
@@ -61,9 +62,9 @@ void serial_init()
// REaltime stuff is acted upon, then characters are added to the appropriate buffer
void serialCheckTask(void *pvParameters)
{
uint8_t data;
uint8_t data = 0;
uint8_t next_head;
uint8_t client; // who send the data
uint8_t client = CLIENT_ALL; // who send the data
uint8_t client_idx = 0; // index of data buffer
@@ -180,9 +181,13 @@ void serialCheckTask(void *pvParameters)
}
} // switch data
} // if something available
COMMANDS::handle();
#ifdef ENABLE_WIFI
wifi_config.handle();
#endif
#endif
#ifdef ENABLE_BLUETOOTH
bt_config.handle();
#endif
#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN)
Serial2Socket.handle_flush();
#endif
@@ -195,9 +200,9 @@ void serialCheckTask(void *pvParameters)
// Realtime stuff is acted upon, then characters are added to the appropriate buffer
void serialCheck()
{
uint8_t data;
uint8_t next_head;
uint8_t client; // who send the data
uint8_t data = 0;
uint8_t next_head;
uint8_t client = CLIENT_SERIAL; // who send the data
uint8_t client_idx = 0; // index of data buffer
@@ -216,6 +221,7 @@ void serialCheck()
client = CLIENT_SERIAL;
data = Serial.read();
}
#if defined (ENABLE_BLUETOOTH) || (defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN))
else
{ //currently is wifi or BT but better to prepare both can be live
#ifdef ENABLE_BLUETOOTH
@@ -232,6 +238,7 @@ void serialCheck()
}
#endif
}
#endif
client_idx = client - 1; // for zero based array

View File

@@ -37,7 +37,6 @@
#define SERIAL_NO_DATA 0xff
// a task to read for incoming data from serial port
static TaskHandle_t serialCheckTaskHandle = 0;
void serialCheckTask(void *pvParameters);
void serialCheck();

View File

@@ -73,6 +73,7 @@ bool Serial_2_Socket::attachWS(void * web_socket){
bool Serial_2_Socket::detachWS(){
_web_socket = NULL;
return true;
}
Serial_2_Socket::operator bool() const
@@ -94,8 +95,12 @@ size_t Serial_2_Socket::write(uint8_t c)
size_t Serial_2_Socket::write(const uint8_t *buffer, size_t size)
{
if((buffer == NULL) ||(!_web_socket)) {
if(buffer == NULL)log_i("[SOCKET]No buffer");
if(!_web_socket)log_i("[SOCKET]No socket");
if(buffer == NULL){
log_i("[SOCKET]No buffer");
}
if(!_web_socket){
log_i("[SOCKET]No socket");
}
return 0;
}
#if defined(ENABLE_SERIAL2SOCKET_OUT)

335
Grbl_Esp32/servo_axis.cpp Normal file
View File

@@ -0,0 +1,335 @@
/*
servo_axis.cpp
Part of Grbl_ESP32
copyright (c) 2018 - Bart Dring. This file was intended for use on the ESP32
CPU. Do not use this with Grbl for atMega328P
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/>.
See servo_axis.h for more details
*/
#include "grbl.h"
#ifdef USE_SERVO_AXES
#ifdef SERVO_X_PIN
ServoAxis X_Servo_Axis(X_AXIS, SERVO_X_PIN, SERVO_X_CHANNEL_NUM);
#endif
#ifdef SERVO_Y_PIN
ServoAxis Y_Servo_Axis(Y_AXIS, SERVO_Y_PIN, SERVO_Y_CHANNEL_NUM);
#endif
#ifdef SERVO_Z_PIN
ServoAxis Z_Servo_Axis(Z_AXIS, SERVO_Z_PIN, SERVO_Z_CHANNEL_NUM);
#endif
void init_servos()
{
#ifdef SERVO_X_PIN
X_Servo_Axis.init();
Y_Servo_Axis.set_range(SERVO_X_RANGE_MIN, SERVO_X_RANGE_MAX);
X_Servo_Axis.set_homing_type(SERVO_HOMING_OFF);
X_Servo_Axis.set_disable_on_alarm(true);
X_Servo_Axis.set_disable_with_steppers(false);
#endif
#ifdef SERVO_Y_PIN
Y_Servo_Axis.init();
Y_Servo_Axis.set_range(SERVO_Y_RANGE_MIN, SERVO_Y_RANGE_MAX);
#endif
#ifdef SERVO_Z_PIN
Z_Servo_Axis.init();
Z_Servo_Axis.set_range(SERVO_Z_RANGE_MIN, SERVO_Z_RANGE_MAX);
Z_Servo_Axis.set_homing_type(SERVO_HOMING_TARGET);
Z_Servo_Axis.set_homing_position(SERVO_Z_RANGE_MAX);
#endif
// setup a task that will calculate the determine and set the servo positions
xTaskCreatePinnedToCore( servosSyncTask, // task
"servosSyncTask", // name for task
4096, // size of task stack
NULL, // parameters
1, // priority
&servosSyncTaskHandle,
0 // core
);
}
// this is the task
void servosSyncTask(void *pvParameters)
{
TickType_t xLastWakeTime;
const TickType_t xServoFrequency = SERVO_TIMER_INT_FREQ; // in ticks (typically ms)
uint16_t servo_delay_counter = 0;
while(true) { // don't ever return from this or the task dies
vTaskDelayUntil(&xLastWakeTime, xServoFrequency);
#ifdef SERVO_X_PIN
X_Servo_Axis.set_location();
#endif
#ifdef SERVO_Y_PIN
Y_Servo_Axis.set_location();
#endif
#ifdef SERVO_Z_PIN
Z_Servo_Axis.set_location();
#endif
}
}
// =============================== Class Stuff ================================= //
ServoAxis::ServoAxis(uint8_t axis, uint8_t pin_num, uint8_t channel_num) // constructor
{
_axis = axis;
_pin_num = pin_num;
_channel_num = channel_num;
}
void ServoAxis::init()
{
ledcSetup(_channel_num, _pwm_freq, _pwm_resolution_bits);
ledcAttachPin(_pin_num, _channel_num);
disable();
}
/*
void ServoAxis::set_location()
{
// These are the pulse lengths for the minimum and maximum positions
// Note: Some machines will have the physical max/min inverted with pulse length max/min due to invert setting $3=...
float servo_pulse_min, servo_pulse_max;
float min_pulse_cal, max_pulse_cal; // calibration values in percent 110% = 1.1
uint32_t servo_pulse_len;
float mpos, offset, wpos;
// skip location if we are in alarm mode
if (_disable_on_alarm && (sys.state == STATE_ALARM)) {
disable();
return;
}
// track the disable status of the steppers if desired.
if (_disable_with_steppers && get_stepper_disable()) {
disable();
return;
}
if ( (_homing_type == SERVO_HOMING_TARGET) && (sys.state == STATE_HOMING) ) {
wpos = _homing_position; // go to servos home position
}
else {
mpos = system_convert_axis_steps_to_mpos(sys_position, _axis); // get the axis machine position in mm
offset = gc_state.coord_system[_axis]+gc_state.coord_offset[_axis]; // get the current axis work offset
wpos = mpos - offset; // determine the current work position
}
// get the calibration values
if (_cal_is_valid(false)) { // if calibration settings are OK then apply them
min_pulse_cal = (settings.steps_per_mm[_axis] / 100.0);
max_pulse_cal = (settings.max_travel[_axis] / -100.0);
if (bit_istrue(settings.dir_invert_mask,bit(_axis))) { // the offset needs to be backwards
min_pulse_cal = 1.0 + (1.0 - min_pulse_cal);
max_pulse_cal = 1.0 + (1.0 - max_pulse_cal);
}
}
else { // settings are not valid so don't apply any calibration
min_pulse_cal = 1.0;
max_pulse_cal = 1.0;
}
if (bit_istrue(settings.dir_invert_mask,bit(_axis))) { // this allows the user to change the direction via settings
servo_pulse_min = SERVO_MAX_PULSE;
servo_pulse_max = SERVO_MIN_PULSE;
}
else {
servo_pulse_min = SERVO_MIN_PULSE;
servo_pulse_max = SERVO_MAX_PULSE;
}
// apply the calibrations
servo_pulse_min *= min_pulse_cal;
servo_pulse_max *= max_pulse_cal;
// determine the pulse length
servo_pulse_len = (uint32_t)mapConstrain(wpos,
_position_min, _position_max,
servo_pulse_min, servo_pulse_max );
_write_pwm(servo_pulse_len);
}
*/
void ServoAxis::set_location()
{
// These are the pulse lengths for the minimum and maximum positions
// Note: Some machines will have the physical max/min inverted with pulse length max/min due to invert setting $3=...
float servo_pulse_min, servo_pulse_max;
float min_pulse_cal, max_pulse_cal; // calibration values in percent 110% = 1.1
uint32_t servo_pulse_len;
float servo_pos, mpos, offset, wpos;
// skip location if we are in alarm mode
if (_disable_on_alarm && (sys.state == STATE_ALARM)) {
disable();
return;
}
// track the disable status of the steppers if desired.
if (_disable_with_steppers && get_stepper_disable()) {
disable();
return;
}
if ( (_homing_type == SERVO_HOMING_TARGET) && (sys.state == STATE_HOMING) ) {
servo_pos = _homing_position; // go to servos home position
}
else {
mpos = system_convert_axis_steps_to_mpos(sys_position, _axis); // get the axis machine position in mm
if (_use_mpos) {
servo_pos = mpos;
}
else {
offset = gc_state.coord_system[_axis]+gc_state.coord_offset[_axis]; // get the current axis work offset
servo_pos = mpos - offset; // determine the current work position
}
}
// get the calibration values
if (_cal_is_valid(false)) { // if calibration settings are OK then apply them
min_pulse_cal = (settings.steps_per_mm[_axis] / 100.0);
max_pulse_cal = (settings.max_travel[_axis] / -100.0);
if (bit_istrue(settings.dir_invert_mask,bit(_axis))) { // the offset needs to be backwards
min_pulse_cal = 1.0 + (1.0 - min_pulse_cal);
max_pulse_cal = 1.0 + (1.0 - max_pulse_cal);
}
}
else { // settings are not valid so don't apply any calibration
min_pulse_cal = 1.0;
max_pulse_cal = 1.0;
}
if (bit_istrue(settings.dir_invert_mask,bit(_axis))) { // this allows the user to change the direction via settings
servo_pulse_min = SERVO_MAX_PULSE;
servo_pulse_max = SERVO_MIN_PULSE;
}
else {
servo_pulse_min = SERVO_MIN_PULSE;
servo_pulse_max = SERVO_MAX_PULSE;
}
// apply the calibrations
servo_pulse_min *= min_pulse_cal;
servo_pulse_max *= max_pulse_cal;
// determine the pulse length
servo_pulse_len = (uint32_t)mapConstrain(servo_pos,
_position_min, _position_max,
servo_pulse_min, servo_pulse_max );
_write_pwm(servo_pulse_len);
}
void ServoAxis::_write_pwm(uint32_t duty)
{
if (ledcRead(_channel_num) != duty) { // only write if it is changing
ledcWrite(_channel_num, duty);
}
}
// sets the PWM to zero. This allows most servos to be manually moved
void ServoAxis::disable()
{
_write_pwm(0);
}
// checks to see if calibration values are in an acceptable range
// vebose = true if you want an error sent to serial port
bool ServoAxis::_cal_is_valid(bool verbose)
{
bool settingsOK = true;
if ( (settings.steps_per_mm[_axis] < SERVO_CAL_MIN) || (settings.steps_per_mm[_axis] > SERVO_CAL_MAX) ) {
if (verbose) {
grbl_sendf(CLIENT_SERIAL, "[MSG:Servo cal ($10%d) Error: %4.4f s/b between %.2f and %.2f]\r\n", _axis, settings.steps_per_mm[_axis], SERVO_CAL_MIN, SERVO_CAL_MAX);
}
settingsOK = false;
}
// Note: Max travel is set positive via $$, but stored as a negative number
if ( (settings.max_travel[_axis] < -SERVO_CAL_MAX) || (settings.max_travel[_axis] > -SERVO_CAL_MIN) ) {
if (verbose) {
grbl_sendf(CLIENT_SERIAL, "[MSG:Servo cal ($13%d) Error: %4.4f s/b between %.2f and %.2f]\r\n", _axis, -settings.max_travel[_axis], SERVO_CAL_MIN, SERVO_CAL_MAX);
}
settingsOK = false;
}
return settingsOK;
}
/*
Use this to set the max and min position in mm of the servo
This is used when mapping pulse length to the position
*/
void ServoAxis::set_range(float min, float max) {
if (min < max) {
_position_min = min;
_position_max = max;
}
else {
grbl_send(CLIENT_SERIAL, "[MSG:Error setting range. Min not smaller than max]\r\n");
}
}
/*
Sets the mode the servo will be in during homing
See servo_axis.h for SERVO_HOMING_xxxxx types
*/
void ServoAxis::set_homing_type(uint8_t homing_type)
{
if (homing_type <= SERVO_HOMING_TARGET)
_homing_type = homing_type;
}
/*
Use this to set the homing position the servo will be commanded to go if
the current homing mode is SERVO_HOMING_TARGET
*/
void ServoAxis::set_homing_position(float homing_position)
{
_homing_position = homing_position;
}
/*
Use this to set the disable on alarm feature. If true, then hobby servo PWM
will be disable in Grbl alarm mode (like before homing). Typical hobby servo
can be moved by hand in this mode
*/
void ServoAxis::set_disable_on_alarm (bool disable_on_alarm)
{
_disable_on_alarm = disable_on_alarm;
}
void ServoAxis::set_disable_with_steppers(bool disable_with_steppers) {
_disable_with_steppers = disable_with_steppers;
}
#endif

134
Grbl_Esp32/servo_axis.h Normal file
View File

@@ -0,0 +1,134 @@
/*
solenoid_pen.h
Part of Grbl_ESP32
copyright (c) 2019 - Bart Dring. This file was intended for use on the ESP32
CPU. Do not use this with Grbl for atMega328P
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/>.
Servo Axis Class
The Servo axis feature allows you to use a hobby servo on any axis.
This is done using a repeating RTOS task. Grbl continues to calculate
the position of the axis in real time. The task looks at the current position of
the axis and calculates the required PWM value to go to that location. You define the travel
of the servo in millimeters.
Grbl still uses the acceleration and speed values you have in the settings, so it
will coordinate servo axes with stepper motor axes. This assumes these values are within the
capabilities of the servo
Usage
1. In config.h un-comment #define USE_SERVO_AXES
2. In a cpu_map.h section, define servo pins and PWM channels like this ....
#define SERVO_Y_PIN GPIO_NUM_14
#define SERVO_Y_CHANNEL_NUM 6
undefine any step and direction pins associated with that axis
3. In servo_axis.cpp init_servos() function, configure servos like this ....
X_Servo_Axis.set_range(0.0, 20.0); // millimeter
X_Servo_Axis.set_homing_type(SERVO_HOMING_OFF);
X_Servo_Axis.set_disable_on_alarm(true);
The positions can be calibrated using the settings. $10x (resolution) settings adjust the minimum
position and $13x (max travel) settings adjust the maximum position. If the servo is traveling
backwards from what you want, you can use the $3 direction setting to compensate.
*/
#ifndef servo_axis_h
#define servo_axis_h
// this is the pulse range of a the servo. Typical servos are 0.001 to 0.002 seconds
// some servos have a wider range. You can adjust this here or in the calibration feature
#define SERVO_MIN_PULSE_SEC 0.001 // min pulse in seconds
#define SERVO_MAX_PULSE_SEC 0.002 // max pulse in seconds
#define SERVO_POSITION_MIN_DEFAULT 0.0 // mm
#define SERVO_POSITION_MAX_DEFAULT 20.0 // mm
#define SERVO_PULSE_FREQ 50 // 50Hz ...This is a standard analog servo value. Digital ones can repeat faster
#define SERVO_PULSE_RES_BITS 16 // bits of resolution of PWM (16 is max)
#define SERVO_PULSE_RES_COUNT 65535 // see above TODO...do the math here 2^SERVO_PULSE_RES_BITS
#define SERVO_TIME_PER_BIT ((1.0 / (float)SERVO_PULSE_FREQ) / ((float)SERVO_PULSE_RES_COUNT) ) // seconds
#define SERVO_MIN_PULSE (uint16_t)(SERVO_MIN_PULSE_SEC / SERVO_TIME_PER_BIT) // in timer counts
#define SERVO_MAX_PULSE (uint16_t)(SERVO_MAX_PULSE_SEC / SERVO_TIME_PER_BIT) // in timer counts
#define SERVO_PULSE_RANGE (SERVO_MAX_PULSE-SERVO_MIN_PULSE)
#define SERVO_CAL_MIN 20.0 // Percent: the minimum allowable calibration value
#define SERVO_CAL_MAX 180.0 // Percent: the maximum allowable calibration value
#define SERVO_TIMER_INT_FREQ 20 // Hz This is the task frequency
#define SERVO_HOMING_OFF 0 // servo is off during homing
#define SERVO_HOMING_TARGET 1 // servo is send to a location during homing
static TaskHandle_t servosSyncTaskHandle = 0;
extern float my_location;
void init_servos();
void servosSyncTask(void *pvParameters);
class ServoAxis{
public:
ServoAxis(uint8_t axis, uint8_t pin_num, uint8_t channel_num); // constructor
void init();
void set_location();
void disable(); // sets PWM to 0% duty cycle. Most servos can be manually moved in this state
void set_range(float min, float max);
void set_homing_type(uint8_t homing_type);
void set_homing_position(float homing_position);
void set_disable_on_alarm (bool disable_on_alarm);
void set_disable_with_steppers(bool disable_with_steppers);
void set_use_mpos(bool use_mpos);
private:
int _axis; // these should be assign in constructor using Grbl X_AXIS type values
int _pin_num; // The GPIO pin being used
int _channel_num; // The PWM channel
uint32_t _pwm_freq = SERVO_PULSE_FREQ;
uint32_t _pwm_resolution_bits = SERVO_PULSE_RES_BITS;
float _pulse_min = SERVO_MIN_PULSE; // in pwm counts
float _pulse_max = SERVO_MAX_PULSE; // in pwm counts
float _position_min = SERVO_POSITION_MIN_DEFAULT; // position in millimeters
float _position_max = SERVO_POSITION_MAX_DEFAULT; // position in millimeters
uint8_t _homing_type = SERVO_HOMING_OFF;
float _homing_position = SERVO_POSITION_MAX_DEFAULT;
bool _disable_on_alarm = true;
bool _disable_with_steppers = false;
bool _use_mpos = true;
bool _validate_cal_settings();
void _write_pwm(uint32_t duty);
bool _cal_is_valid(bool verbose); // checks to see if calibration values are in acceptable range
};
#endif

View File

@@ -23,6 +23,8 @@
#ifdef USE_PEN_SERVO
static TaskHandle_t servoSyncTaskHandle = 0;
// used to delay turn on
bool servo_pen_enable = false;
@@ -106,15 +108,17 @@ void servoSyncTask(void *pvParameters)
vTaskDelayUntil(&xLastWakeTime, xServoFrequency);
if (!servo_pen_enable) {
servo_delay_counter++;
servo_pen_enable = (servo_delay_counter > SERVO_TURNON_DELAY);
} else {
mpos_z = system_convert_axis_steps_to_mpos(sys_position, Z_AXIS); // get the machine Z in mm
z_offset = gc_state.coord_system[Z_AXIS]+gc_state.coord_offset[Z_AXIS]; // get the current z work offset
wpos_z = mpos_z - z_offset; // determine the current work Z
if (sys.state != STATE_ALARM) { // don't move until alarm is cleared...typically homing
if (!servo_pen_enable ) {
servo_delay_counter++;
servo_pen_enable = (servo_delay_counter > SERVO_TURNON_DELAY);
} else {
mpos_z = system_convert_axis_steps_to_mpos(sys_position, Z_AXIS); // get the machine Z in mm
z_offset = gc_state.coord_system[Z_AXIS]+gc_state.coord_offset[Z_AXIS]; // get the current z work offset
wpos_z = mpos_z - z_offset; // determine the current work Z
calc_pen_servo(wpos_z); // calculate kinematics and move the servos
calc_pen_servo(wpos_z); // calculate kinematics and move the servos
}
}
}
}
@@ -130,13 +134,29 @@ void calc_pen_servo(float penZ)
}
if (validate_servo_settings(false)) { // if calibration settings are OK then apply them
// Apply a calibration to the minimum position
servo_pen_pulse_min = SERVO_MIN_PULSE * (settings.steps_per_mm[Z_AXIS] / 100.0);
// Apply a calibration to the maximum position
servo_pen_pulse_max = SERVO_MAX_PULSE * (settings.max_travel[Z_AXIS] / -100.0);
if (bit_istrue(settings.dir_invert_mask,bit(Z_AXIS))) { // this allows the user to change the direction via settings
// Apply a calibration to the minimum position
servo_pen_pulse_max = SERVO_MIN_PULSE * (settings.steps_per_mm[Z_AXIS] / 100.0);
// Apply a calibration to the maximum position
servo_pen_pulse_min = SERVO_MAX_PULSE * (settings.max_travel[Z_AXIS] / -100.0);
}
else {
// Apply a calibration to the minimum position
servo_pen_pulse_min = SERVO_MIN_PULSE * (settings.steps_per_mm[Z_AXIS] / 100.0);
// Apply a calibration to the maximum position
servo_pen_pulse_max = SERVO_MAX_PULSE * (settings.max_travel[Z_AXIS] / -100.0);
}
} else { // use the defaults
servo_pen_pulse_min = SERVO_MIN_PULSE;
servo_pen_pulse_max = SERVO_MAX_PULSE;
if (bit_istrue(settings.dir_invert_mask,bit(Z_AXIS))) { // this allows the user to change the direction via settings
servo_pen_pulse_min = SERVO_MAX_PULSE;
servo_pen_pulse_max = SERVO_MIN_PULSE;
}
else {
servo_pen_pulse_min = SERVO_MIN_PULSE;
servo_pen_pulse_max = SERVO_MAX_PULSE;
}
}
// determine the pulse length

View File

@@ -32,7 +32,7 @@
// the pulse lengths for the min and max travel .. (Note: Servo brands vary)
// If the servo goes backward from what you want, flip the values
// Note: this is not necessarily the servos limits (just the travel you want)
#define SERVO_MIN_PULSE_SEC 0.0012 // min pulse in seconds
#define SERVO_MIN_PULSE_SEC 0.001 // min pulse in seconds
#define SERVO_MAX_PULSE_SEC 0.002 // max pulse in seconds
// Pulse repeat rate (PWM Frequency)
@@ -54,7 +54,7 @@
#define SERVO_PULSE_RES_COUNT 65535 // see above TODO...do the math here 2^SERVO_PULSE_RES_BITS
// A way to reduce the turn on current
#define SERVO_TURNON_DELAY 25 // Wait this many task counts to turn on servo
#define SERVO_TURNON_DELAY SERVO_TIMER_INT_FREQ*3 // Wait this many task counts to turn on servo
#define SERVO_TIME_PER_BIT ((1.0 / (float)SERVO_PULSE_FREQ) / ((float)SERVO_PULSE_RES_COUNT) ) // seconds
@@ -67,12 +67,10 @@
#ifndef servo_h
#define servo_h
static TaskHandle_t servoSyncTaskHandle = 0;
void servo_init();
void servo_disable();
bool validate_servo_settings(bool verbose);
void servoSyncTask(void *pvParameters);
void calc_pen_servo(float penZ);
#endif
#endif

View File

@@ -49,11 +49,16 @@ void settings_init()
// Method to restore EEPROM-saved Grbl global settings back to defaults.
void settings_restore(uint8_t restore_flag) {
if (restore_flag & SETTINGS_RESTORE_ALL){
#if defined(ENABLE_BLUETOOTH) || defined(ENABLE_WIFI)
if (restore_flag & SETTINGS_RESTORE_WIFI_SETTINGS){
#ifdef ENABLE_WIFI
wifi_config.reset_ESP();
wifi_config.reset_settings();
#endif
#ifdef ENABLE_BLUETOOTH
bt_config.reset_settings();
#endif
}
#endif
if (restore_flag & SETTINGS_RESTORE_DEFAULTS) {
settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS;
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;

View File

@@ -51,6 +51,7 @@
#define SETTINGS_RESTORE_PARAMETERS bit(1)
#define SETTINGS_RESTORE_STARTUP_LINES bit(2)
#define SETTINGS_RESTORE_BUILD_INFO bit(3)
#define SETTINGS_RESTORE_WIFI_SETTINGS bit(4)
#ifndef SETTINGS_RESTORE_ALL
#define SETTINGS_RESTORE_ALL 0xFF // All bitflags
#endif

View File

@@ -23,6 +23,8 @@
#ifdef USE_PEN_SOLENOID
static TaskHandle_t solenoidSyncTaskHandle = 0;
// used to delay turn on
bool solenoid_pen_enable;
uint16_t solenoide_hold_count;
@@ -89,10 +91,7 @@ void calc_solenoid(float penZ)
uint32_t solenoid_pen_pulse_len;
if (!solenoid_pen_enable) // only proceed if startup delay as expired
return;
return;
if (penZ < 0 && (sys.state != STATE_ALARM)) { // alarm also makes it go up
solenoide_hold_count = 0; // reset this count

View File

@@ -22,6 +22,8 @@
This is designed to use a solenoid to lift a pen.
When the current Z location is below zero the pen is down
If the Z goes to zero or above the pen goes up.
There are two power levels, the initial pull up strength, then the hold strength
Note: There is a still a virtual Z axis that has a finite speed.
If your gcode is commanding long travels in Z, there will be delays
@@ -37,14 +39,14 @@
#define SOLENOID_TURNON_DELAY (SOLENOID_TIMER_INT_FREQ/2)
#define SOLENOID_PULSE_LEN_UP 255
#define SOLENOID_PULSE_LEN_HOLD 80 // a lower value to prevent overheating
#define SOLENOID_HOLD_DELAY (SOLENOID_TIMER_INT_FREQ/2) // in task counts
#define SOLENOID_HOLD_DELAY (SOLENOID_TIMER_INT_FREQ/2) // in task counts...after this delay power will change to hold level
#define SOLENOID_PULSE_LEN_HOLD 80 // solenoid hold level ... typically a lower value to prevent overheating
#define SOLENOID_TIMER_INT_FREQ 50
#ifndef solenoid_h
#define solenoid_h
static TaskHandle_t solenoidSyncTaskHandle = 0;
void solenoid_init();
void solenoid_disable();
void solenoidSyncTask(void *pvParameters);

View File

@@ -49,7 +49,7 @@ void spindle_stop()
{
spindle_set_enable(false);
#ifdef SPINDLE_PWM_PIN
grbl_analogWrite(SPINDLE_PWM_CHANNEL, 0);
grbl_analogWrite(SPINDLE_PWM_CHANNEL, SPINDLE_PWM_OFF_VALUE);
#endif
}
@@ -86,7 +86,7 @@ void spindle_set_speed(uint32_t pwm_value)
#else
spindle_set_enable(pwm_value != 0);
#endif
grbl_analogWrite(SPINDLE_PWM_CHANNEL, pwm_value);
grbl_analogWrite(SPINDLE_PWM_CHANNEL, pwm_value);
}
// Called by spindle_set_state() and step segment generator. Keep routine small and efficient.

File diff suppressed because it is too large Load Diff

View File

@@ -76,12 +76,13 @@
extern uint64_t stepper_idle_counter;
extern bool stepper_idle;
extern uint8_t ganged_mode;
// -- Task handles for use in the notifications
void IRAM_ATTR onSteppertimer();
void IRAM_ATTR onStepperOffTimer();
void stepper_init();
void initRMT();
// Enable steppers, but cycle does not start unless called by motion control or realtime command.
void st_wake_up();
@@ -112,6 +113,7 @@ float st_get_realtime_rate();
// disable (or enable) steppers via STEPPERS_DISABLE_PIN
void set_stepper_disable(uint8_t disable);
bool get_stepper_disable(); // returns the state of the pin
void set_step_pin_on(uint8_t axis, uint8_t isOn);
void set_direction_pin_on(uint8_t axis, uint8_t isOn);

View File

@@ -24,23 +24,26 @@
void system_ini() // Renamed from system_init() due to conflict with esp32 files
{
// setup control inputs
#ifdef CONTROL_SAFETY_DOOR_PIN
pinMode(CONTROL_SAFETY_DOOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_SAFETY_DOOR_PIN), isr_control_inputs, CHANGE);
#endif
#ifdef CONTROL_RESET_PIN
pinMode(CONTROL_RESET_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_RESET_PIN), isr_control_inputs, CHANGE);
#endif
#ifdef CONTROL_FEED_HOLD_PIN
pinMode(CONTROL_FEED_HOLD_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_FEED_HOLD_PIN), isr_control_inputs, CHANGE);
#endif
#ifdef CONTROL_CYCLE_START_PIN
pinMode(CONTROL_CYCLE_START_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_CYCLE_START_PIN), isr_control_inputs, CHANGE);
#endif
#ifndef IGNORE_CONTROL_PINS
#ifdef CONTROL_SAFETY_DOOR_PIN
pinMode(CONTROL_SAFETY_DOOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_SAFETY_DOOR_PIN), isr_control_inputs, CHANGE);
#endif
#ifdef CONTROL_RESET_PIN
pinMode(CONTROL_RESET_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_RESET_PIN), isr_control_inputs, CHANGE);
#endif
#ifdef CONTROL_FEED_HOLD_PIN
pinMode(CONTROL_FEED_HOLD_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_FEED_HOLD_PIN), isr_control_inputs, CHANGE);
#endif
#ifdef CONTROL_CYCLE_START_PIN
pinMode(CONTROL_CYCLE_START_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONTROL_CYCLE_START_PIN), isr_control_inputs, CHANGE);
#endif
#endif
}
void IRAM_ATTR isr_control_inputs()
@@ -50,6 +53,7 @@ void IRAM_ATTR isr_control_inputs()
if (pin) {
if (bit_istrue(pin,CONTROL_PIN_INDEX_RESET))
{
grbl_send(CLIENT_SERIAL, "[MSG:Reset via control pin]\r\n"); // help debug reason for reset
mc_reset();
}
else if (bit_istrue(pin,CONTROL_PIN_INDEX_CYCLE_START))
@@ -205,6 +209,9 @@ uint8_t system_execute_line(char *line, uint8_t client)
#ifdef ENABLE_RESTORE_EEPROM_WIPE_ALL
case '*': settings_restore(SETTINGS_RESTORE_ALL); break;
#endif
#if defined(ENABLE_BLUETOOTH) || defined(ENABLE_WIFI)
case '@': settings_restore(SETTINGS_RESTORE_WIFI_SETTINGS); break;
#endif
default: return(STATUS_INVALID_STATEMENT);
}
report_feedback_message(MESSAGE_RESTORE_DEFAULTS);
@@ -225,43 +232,7 @@ uint8_t system_execute_line(char *line, uint8_t client)
helper_var = true; // Set helper_var to flag storing method.
// No break. Continues into default: to read remaining command characters.
}
case 'W':
//TODO
break;
#ifdef ENABLE_SD_CARD // ==================== SD Card ============================
case 'F':
char fileLine[255];
if ( line[char_counter+1] == 0 ) {
// show the files
//Serial.println("Show the files");
listDir(SD, "/", 10); // 10 directory levels should be fine
}
else if (line[char_counter+1] == 'M') {
sd_mount();
}
else if (line[char_counter+1] == '=') { // run a file
if (sys.state != STATE_IDLE) { return(STATUS_SYSTEM_GC_LOCK); } // must be in idle to run a file
char_counter += 2;
helper_var = char_counter; // Set helper variable as counter to start of user info line.
// shift the user info over to the beginning of the line "$F=/FOO.NC" becomes "/FOO.NC"
do {
line[char_counter-helper_var] = line[char_counter];
} while (line[char_counter++] != 0);
openFile(SD, line);
if (!readFileLine(fileLine)) {
return(STATUS_SD_FILE_EMPTY);
closeFile();
}
else {
report_status_message(gc_execute_line(fileLine, CLIENT_SERIAL), CLIENT_SERIAL); // execute the first line
}
}
else {
return(STATUS_INVALID_STATEMENT);
}
break;
#endif // =============================== SD Card ========================================
default : // Storing setting methods [IDLE/ALARM]
if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); }
if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }
@@ -423,28 +394,34 @@ uint8_t system_check_travel_limits(float *target)
// defined by the CONTROL_PIN_INDEX in the header file.
uint8_t system_control_get_state()
{
uint8_t defined_pin_mask = 0; // a mask of defined pins
#ifdef IGNORE_CONTROL_PINS
return 0;
#endif
#endif
uint8_t control_state = 0;
#ifdef CONTROL_SAFETY_DOOR_PIN
if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) { control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; }
#endif
#ifdef CONTROL_RESET_PIN
if (digitalRead(CONTROL_RESET_PIN)) { control_state |= CONTROL_PIN_INDEX_RESET; }
#endif
#ifdef CONTROL_FEED_HOLD_PIN
if (digitalRead(CONTROL_FEED_HOLD_PIN)) { control_state |= CONTROL_PIN_INDEX_FEED_HOLD; }
#endif
#ifdef CONTROL_CYCLE_START_PIN
if (digitalRead(CONTROL_CYCLE_START_PIN)) { control_state |= CONTROL_PIN_INDEX_CYCLE_START; }
#endif
#ifdef CONTROL_SAFETY_DOOR_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_SAFETY_DOOR;
if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) { control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; }
#endif
#ifdef CONTROL_RESET_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_RESET;
if (digitalRead(CONTROL_RESET_PIN)) { control_state |= CONTROL_PIN_INDEX_RESET; }
#endif
#ifdef CONTROL_FEED_HOLD_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_FEED_HOLD;
if (digitalRead(CONTROL_FEED_HOLD_PIN)) { control_state |= CONTROL_PIN_INDEX_FEED_HOLD; }
#endif
#ifdef CONTROL_CYCLE_START_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_CYCLE_START;
if (digitalRead(CONTROL_CYCLE_START_PIN)) { control_state |= CONTROL_PIN_INDEX_CYCLE_START; }
#endif
#ifdef INVERT_CONTROL_PIN_MASK
control_state ^= INVERT_CONTROL_PIN_MASK;
control_state ^= (INVERT_CONTROL_PIN_MASK & defined_pin_mask);
#endif
return(control_state);
}

View File

@@ -33,6 +33,7 @@
#include <WiFi.h>
#include <Preferences.h>
#include "report.h"
#include "commands.h"
Telnet_Server telnet_server;
@@ -40,6 +41,9 @@ bool Telnet_Server::_setupdone = false;
uint16_t Telnet_Server::_port = 0;
WiFiServer * Telnet_Server::_telnetserver = NULL;
WiFiClient Telnet_Server::_telnetClients[MAX_TLNT_CLIENTS];
#ifdef ENABLE_TELNET_WELCOME_MSG
IPAddress Telnet_Server::_telnetClientsIP[MAX_TLNT_CLIENTS];
#endif
Telnet_Server::Telnet_Server(){
_RXbufferSize = 0;
@@ -53,7 +57,7 @@ Telnet_Server::~Telnet_Server(){
bool Telnet_Server::begin(){
bool no_error = true;
_setupdone = false;
end();
Preferences prefs;
_RXbufferSize = 0;
_RXbufferpos = 0;;
@@ -65,7 +69,7 @@ bool Telnet_Server::begin(){
if (penabled == 0) return false;
//create instance
_telnetserver= new WiFiServer(_port);
_telnetserver= new WiFiServer(_port, MAX_TLNT_CLIENTS);
_telnetserver->setNoDelay(true);
String s = "[MSG:TELNET Started " + String(_port) + "]\r\n";
grbl_send(CLIENT_ALL,(char *)s.c_str());
@@ -92,6 +96,9 @@ void Telnet_Server::clearClients(){
for(i = 0; i < MAX_TLNT_CLIENTS; i++){
//find free/disconnected spot
if (!_telnetClients[i] || !_telnetClients[i].connected()){
#ifdef ENABLE_TELNET_WELCOME_MSG
_telnetClientsIP[i] = IPAddress(0, 0, 0, 0);
#endif
if(_telnetClients[i]) _telnetClients[i].stop();
_telnetClients[i] = _telnetserver->available();
break;
@@ -106,48 +113,64 @@ void Telnet_Server::clearClients(){
size_t Telnet_Server::write(const uint8_t *buffer, size_t size){
size_t wsize = 0;
if ( !_setupdone || _telnetserver == NULL) {
log_i("[TELNET out blocked]");
log_d("[TELNET out blocked]");
return 0;
}
clearClients();
log_i("[TELNET out]");
//log_d("[TELNET out]");
//push UART data to all connected telnet clients
for(uint8_t i = 0; i < MAX_TLNT_CLIENTS; i++){
if (_telnetClients[i] && _telnetClients[i].connected()){
log_i("[TELNET out connected]");
_telnetClients[i].write(buffer, size);
wifi_config.wait(0);
//log_d("[TELNET out connected]");
wsize = _telnetClients[i].write(buffer, size);
COMMANDS::wait(0);
}
}
return wsize;
}
void Telnet_Server::handle(){
COMMANDS::wait(0);
//check if can read
if ( !_setupdone || _telnetserver == NULL) {
return;
}
clearClients();
//check clients for data
uint8_t c;
//uint8_t c;
for(uint8_t i = 0; i < MAX_TLNT_CLIENTS; i++){
if (_telnetClients[i] && _telnetClients[i].connected()){
if(_telnetClients[i].available()){
//get data from the telnet client and push it to grbl
while(_telnetClients[i].available() && (available() < TELNETRXBUFFERSIZE)) {
wifi_config.wait(0);
c = _telnetClients[i].read();
if ((char)c != '\r')push(c);
if ((char)c == '\n')return;
}
#ifdef ENABLE_TELNET_WELCOME_MSG
if (_telnetClientsIP[i] != _telnetClients[i].remoteIP()){
report_init_message(CLIENT_TELNET);
_telnetClientsIP[i] = _telnetClients[i].remoteIP();
}
#endif
if(_telnetClients[i].available()){
uint8_t buf[1024];
COMMANDS::wait(0);
int readlen = _telnetClients[i].available();
int writelen = TELNETRXBUFFERSIZE - available();
if (readlen > 1024) readlen = 1024;
if (readlen > writelen) readlen = writelen;
if (readlen > 0) {
_telnetClients[i].read(buf, readlen);
push(buf, readlen);
}
return;
}
}
else {
if (_telnetClients[i]) {
#ifdef ENABLE_TELNET_WELCOME_MSG
_telnetClientsIP[i] = IPAddress(0, 0, 0, 0);
#endif
_telnetClients[i].stop();
}
}
wifi_config.wait(0);
COMMANDS::wait(0);
}
}
@@ -160,6 +183,10 @@ int Telnet_Server::available(){
return _RXbufferSize;
}
int Telnet_Server::get_rx_buffer_available(){
return TELNETRXBUFFERSIZE - _RXbufferSize;
}
bool Telnet_Server::push (uint8_t data){
log_i("[TELNET]push %c",data);
if ((1 + _RXbufferSize) <= TELNETRXBUFFERSIZE){
@@ -174,18 +201,22 @@ bool Telnet_Server::push (uint8_t data){
return false;
}
bool Telnet_Server::push (const char * data){
int data_size = strlen(data);
bool Telnet_Server::push (const uint8_t * data, int data_size){
if ((data_size + _RXbufferSize) <= TELNETRXBUFFERSIZE){
int data_processed = 0;
int current = _RXbufferpos + _RXbufferSize;
if (current > TELNETRXBUFFERSIZE) current = current - TELNETRXBUFFERSIZE;
for (int i = 0; i < data_size; i++){
if (current > (TELNETRXBUFFERSIZE-1)) current = 0;
_RXbuffer[current] = data[i];
current ++;
wifi_config.wait(0);
if (char(data[i]) != '\r') {
_RXbuffer[current] = data[i];
current ++;
data_processed++;
}
COMMANDS::wait(0);
//vTaskDelay(1 / portTICK_RATE_MS); // Yield to other tasks
}
_RXbufferSize+=strlen(data);
_RXbufferSize+=data_processed;
return true;
}
return false;
@@ -195,7 +226,7 @@ int Telnet_Server::read(void){
if (_RXbufferSize > 0) {
int v = _RXbuffer[_RXbufferpos];
log_i("[TELNET]read %c",v);
//log_d("[TELNET]read %c",char(v));
_RXbufferpos++;
if (_RXbufferpos > (TELNETRXBUFFERSIZE-1))_RXbufferpos = 0;
_RXbufferSize--;

View File

@@ -43,12 +43,17 @@ class Telnet_Server {
int read(void);
int peek(void);
int available();
int get_rx_buffer_available();
bool push (uint8_t data);
bool push (const char * data);
bool push (const uint8_t * data, int datasize);
static uint16_t port(){return _port;}
private:
static bool _setupdone;
static WiFiServer * _telnetserver;
static WiFiClient _telnetClients[MAX_TLNT_CLIENTS];
#ifdef ENABLE_TELNET_WELCOME_MSG
static IPAddress _telnetClientsIP[MAX_TLNT_CLIENTS];
#endif
static uint16_t _port;
void clearClients();
uint32_t _lastflush;

File diff suppressed because it is too large Load Diff

View File

@@ -24,16 +24,10 @@
#include "config.h"
#include "commands.h"
class WebSocketsServer;
class WebServer;
//Authentication level
typedef enum {
LEVEL_GUEST = 0,
LEVEL_USER = 1,
LEVEL_ADMIN = 2
} level_authenticate_type;
#ifdef ENABLE_AUTHENTICATION
struct auth_ip {
IPAddress ip;
@@ -46,21 +40,6 @@ struct auth_ip {
#endif
class ESPResponseStream{
public:
void print(const char *data);
void println(const char *data);
void flush();
ESPResponseStream(WebServer * webserver);
private:
bool _header_sent;
WebServer * _webserver;
String _buffer;
};
class Web_Server {
public:
Web_Server();
@@ -69,17 +48,14 @@ class Web_Server {
void end();
void handle();
static long get_client_ID();
static uint16_t port(){return _port;}
private:
static bool _setupdone;
static WebServer * _webserver;
static long _id_connection;
static WebSocketsServer * _socket_server;
static uint16_t _port;
static uint16_t _data_port;
static String _hostname;
static uint8_t _upload_status;
static char * mac2str (uint8_t mac [8]);
static String formatBytes (uint32_t bytes);
static String getContentType (String filename);
static String get_Splited_Value(String data, char separator, int index);
static level_authenticate_type is_authenticated();
@@ -91,10 +67,7 @@ class Web_Server {
static bool ClearAuthIP (IPAddress ip, const char * sessionID);
static auth_ip * GetAuth (IPAddress ip, const char * sessionID);
static level_authenticate_type ResetAuthIP (IPAddress ip, const char * sessionID);
static bool isLocalPasswordValid (const char * password);
#endif
static String get_param (String & cmd_params, const char * id, bool withspace);
static bool execute_internal_command (int cmd, String cmd_params, level_authenticate_type auth_level, ESPResponseStream *espresponse);
#ifdef ENABLE_SSDP
static void handle_SSDP ();
#endif

View File

@@ -20,7 +20,6 @@
#ifdef ARDUINO_ARCH_ESP32
//#include "grbl.h"
#include "config.h"
#ifdef ENABLE_WIFI
@@ -33,21 +32,13 @@
#include <Preferences.h>
#include "wificonfig.h"
#include "wifiservices.h"
//#include "http_ESP32.h"
#include "commands.h"
#include "report.h"
#ifdef __cplusplus
extern "C" {
#endif
esp_err_t esp_task_wdt_reset();
#ifdef __cplusplus
}
#endif
WiFiConfig wifi_config;
bool WiFiConfig::restart_ESP_module = false;
String WiFiConfig::_hostname = "";
bool WiFiConfig::_events_registered = false;
WiFiConfig::WiFiConfig(){
}
@@ -55,6 +46,16 @@ WiFiConfig::~WiFiConfig(){
end();
}
//just simple helper to convert mac address to string
char * WiFiConfig::mac2str (uint8_t mac [8])
{
static char macstr [18];
if (0 > sprintf (macstr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ) {
strcpy (macstr, "00:00:00:00:00:00");
}
return macstr;
}
const char *WiFiConfig::info(){
static String result;
String tmp;
@@ -126,7 +127,7 @@ bool WiFiConfig::isHostnameValid (const char * hostname)
//only letter and digit
for (int i = 0; i < strlen (hostname); i++) {
c = hostname[i];
if (! (isdigit (c) || isalpha (c) || c == '_') ) {
if (! (isdigit (c) || isalpha (c) || c == '-') ) {
return false;
}
if (c == ' ') {
@@ -136,6 +137,7 @@ bool WiFiConfig::isHostnameValid (const char * hostname)
return true;
}
/**
* Check if SSID string is valid
*/
@@ -183,17 +185,6 @@ bool WiFiConfig::isValidIP(const char * string){
return ip.fromString(string);
}
/*
* delay is to avoid with asyncwebserver and may need to wait sometimes
*/
void WiFiConfig::wait(uint32_t milliseconds){
uint32_t timeout = millis();
esp_task_wdt_reset(); //for a wait 0;
//wait feeding WDT
while ( (millis() - timeout) < milliseconds) {
esp_task_wdt_reset();
}
}
/**
* WiFi events
@@ -284,7 +275,7 @@ bool WiFiConfig::ConnectSTA2AP(){
break;
}
grbl_sendf(CLIENT_ALL,"[MSG:%s]\r\n",msg.c_str());
wait (500);
COMMANDS::wait (500);
count++;
status = WiFi.status();
}
@@ -383,7 +374,7 @@ bool WiFiConfig::StartAP(){
WiFi.softAPConfig(ip, ip, mask);
//Start AP
if(WiFi.softAP(SSID.c_str(), (password.length() > 0)?password.c_str():NULL, channel)) {
grbl_sendf(CLIENT_ALL,"\n[MSG:AP Started %s]\r\n", WiFi.softAPIP().toString().c_str());
grbl_sendf(CLIENT_ALL,"\n[MSG:Local access point %s started, %s]\r\n", SSID.c_str(), WiFi.softAPIP().toString().c_str());
return true;
} else {
grbl_send(CLIENT_ALL,"[MSG:Starting AP failed]\r\n");
@@ -400,6 +391,8 @@ void WiFiConfig::StopWiFi(){
if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA))WiFi.disconnect(true);
if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA))WiFi.softAPdisconnect(true);
wifi_services.end();
WiFi.enableSTA (false);
WiFi.enableAP (false);
WiFi.mode(WIFI_OFF);
grbl_send(CLIENT_ALL,"\n[MSG:WiFi Off]\r\n");
}
@@ -408,27 +401,36 @@ void WiFiConfig::StopWiFi(){
* begin WiFi setup
*/
void WiFiConfig::begin() {
Preferences prefs;
//stop active services
Preferences prefs;
//stop active services
wifi_services.end();
//setup events
WiFi.onEvent(WiFiConfig::WiFiEvent);
//open preferences as read-only
prefs.begin(NAMESPACE, true);
int8_t wifiMode = prefs.getChar(ESP_WIFI_MODE, DEFAULT_WIFI_MODE);
prefs.end();
if (wifiMode == ESP_WIFI_AP) {
//setup events
if (!_events_registered) {
//cumulative function and no remove so only do once
WiFi.onEvent(WiFiConfig::WiFiEvent);
_events_registered = true;
}
//open preferences as read-only
prefs.begin(NAMESPACE, true);
//Get hostname
String defV = DEFAULT_HOSTNAME;
_hostname = prefs.getString(HOSTNAME_ENTRY, defV);
int8_t wifiMode = prefs.getChar(ESP_RADIO_MODE, DEFAULT_RADIO_MODE);
if (wifiMode == ESP_WIFI_AP) {
StartAP();
//start services
wifi_services.begin();
} else if (wifiMode == ESP_WIFI_STA){
} else if (wifiMode == ESP_WIFI_STA){
if(!StartSTA()){
grbl_send(CLIENT_ALL,"[MSG:Cannot connect to AP]\r\n");
defV = DEFAULT_STA_SSID;
grbl_sendf(CLIENT_ALL,"[MSG:Cannot connect to %s]\r\n", prefs.getString(STA_SSID_ENTRY, defV).c_str());
StartAP();
}
//start services
wifi_services.begin();
}else WiFi.mode(WIFI_OFF);
}else WiFi.mode(WIFI_OFF);
prefs.end();
}
/**
@@ -439,16 +441,9 @@ void WiFiConfig::end() {
}
/**
* Restart ESP
* Reset ESP
*/
void WiFiConfig::restart_ESP(){
restart_ESP_module=true;
}
/**
* Restart ESP
*/
void WiFiConfig::reset_ESP(){
void WiFiConfig::reset_settings(){
Preferences prefs;
prefs.begin(NAMESPACE, false);
String sval;
@@ -459,12 +454,28 @@ void WiFiConfig::reset_ESP(){
if (prefs.putString(HOSTNAME_ENTRY, sval) == 0){
error = true;
}
bbuf = DEFAULT_NOTIFICATION_TYPE;
if (prefs.putChar(NOTIFICATION_TYPE, bbuf) ==0 ) {
error = true;
}
sval = DEFAULT_TOKEN;
if (prefs.putString(NOTIFICATION_T1, sval) != sval.length()){
error = true;
}
if (prefs.putString(NOTIFICATION_T2, sval) != sval.length()){
error = true;
}
if (prefs.putString(NOTIFICATION_TS, sval) != sval.length()){
error = true;
}
sval = DEFAULT_STA_SSID;
if (prefs.putString(STA_SSID_ENTRY, sval) == 0){
error = true;
}
sval = DEFAULT_STA_PWD;
if (prefs.putString(STA_PWD_ENTRY, sval) == 0){
if (prefs.putString(STA_PWD_ENTRY, sval) != sval.length()){
error = true;
}
sval = DEFAULT_AP_SSID;
@@ -472,7 +483,7 @@ void WiFiConfig::reset_ESP(){
error = true;
}
sval = DEFAULT_AP_PWD;
if (prefs.putString(AP_PWD_ENTRY, sval) == 0){
if (prefs.putString(AP_PWD_ENTRY, sval) != sval.length()){
error = true;
}
@@ -492,8 +503,8 @@ void WiFiConfig::reset_ESP(){
if (prefs.putChar(TELNET_ENABLE_ENTRY, bbuf) ==0 ) {
error = true;
}
bbuf = DEFAULT_WIFI_MODE;
if (prefs.putChar(ESP_WIFI_MODE, bbuf) ==0 ) {
bbuf = DEFAULT_RADIO_MODE;
if (prefs.putChar(ESP_RADIO_MODE, bbuf) ==0 ) {
error = true;
}
ibuf = DEFAULT_WEBSERVER_PORT;
@@ -527,20 +538,16 @@ void WiFiConfig::reset_ESP(){
grbl_send(CLIENT_ALL,"[MSG:WiFi reset done]\r\n");
}
}
bool WiFiConfig::Is_WiFi_on(){
return !(WiFi.getMode() == WIFI_MODE_NULL);
}
/**
* Handle not critical actions that must be done in sync environement
*/
void WiFiConfig::handle() {
//in case of restart requested
if (restart_ESP_module) {
end();
ESP.restart();
while (1) {};
}
void WiFiConfig::handle() {
//Services
COMMANDS::wait(0);
wifi_services.handle();
}

View File

@@ -19,14 +19,12 @@
*/
//Preferences entries
#define NAMESPACE "GRBL"
#define HOSTNAME_ENTRY "ESP_HOSTNAME"
#define STA_SSID_ENTRY "STA_SSID"
#define STA_PWD_ENTRY "STA_PWD"
#define STA_IP_ENTRY "STA_IP"
#define STA_GW_ENTRY "STA_GW"
#define STA_MK_ENTRY "STA_MK"
#define ESP_WIFI_MODE "WIFI_MODE"
#define AP_SSID_ENTRY "AP_SSID"
#define AP_PWD_ENTRY "AP_PWD"
#define AP_IP_ENTRY "AP_IP"
@@ -36,14 +34,18 @@
#define TELNET_ENABLE_ENTRY "TELNET_ON"
#define TELNET_PORT_ENTRY "TELNET_PORT"
#define STA_IP_MODE_ENTRY "STA_IP_MODE"
#define NOTIFICATION_TYPE "NOTIF_TYPE"
#define NOTIFICATION_T1 "NOTIF_T1"
#define NOTIFICATION_T2 "NOTIF_T2"
#define NOTIFICATION_TS "NOTIF_TS"
//Wifi Mode
#define ESP_WIFI_OFF 0
#define ESP_WIFI_STA 1
#define ESP_WIFI_AP 2
//Notifications
#define ESP_PUSHOVER_NOTIFICATION 1
#define ESP_EMAIL_NOTIFICATION 2
#define ESP_LINE_NOTIFICATION 3
#define DHCP_MODE 0
#define STATIC_MODE 0
#define STATIC_MODE 1
//Switch
#define ESP_SAVE_ONLY 0
@@ -56,7 +58,6 @@
#define DEFAULT_STA_IP "0.0.0.0"
#define DEFAULT_STA_GW "0.0.0.0"
#define DEFAULT_STA_MK "0.0.0.0"
#define DEFAULT_WIFI_MODE ESP_WIFI_AP
#define DEFAULT_AP_SSID "GRBL_ESP"
#define DEFAULT_AP_PWD "12345678"
#define DEFAULT_AP_IP "192.168.0.1"
@@ -68,6 +69,8 @@
#define DEFAULT_TELNET_STATE 1
#define DEFAULT_STA_IP_MODE DHCP_MODE
#define HIDDEN_PASSWORD "********"
#define DEFAULT_TOKEN ""
#define DEFAULT_NOTIFICATION_TYPE 0
//boundaries
#define MAX_SSID_LENGTH 32
@@ -84,7 +87,9 @@
#define MIN_TELNET_PORT 1
#define MIN_CHANNEL 1
#define MAX_CHANNEL 14
#define MIN_NOTIFICATION_TOKEN_LENGTH 0
#define MAX_NOTIFICATION_TOKEN_LENGTH 63
#define MAX_NOTIFICATION_SETTING_LENGTH 127
#ifndef _WIFI_CONFIG_H
#define _WIFI_CONFIG_H
@@ -95,14 +100,14 @@ public:
WiFiConfig();
~WiFiConfig();
static const char *info();
static void wait(uint32_t milliseconds);
static bool isValidIP(const char * string);
static bool isPasswordValid (const char * password);
static bool isSSIDValid (const char * ssid);
static bool isHostnameValid (const char * hostname);
static uint32_t IP_int_from_string(String & s);
static String IP_string_from_int(uint32_t ip_int);
static String Hostname(){return _hostname;}
static char * mac2str (uint8_t mac [8]);
static bool StartAP();
static bool StartSTA();
static void StopWiFi();
@@ -110,12 +115,13 @@ public:
static void begin();
static void end();
static void handle();
static void restart_ESP();
static void reset_ESP();
private :
static void reset_settings();
static bool Is_WiFi_on();
private :
static bool ConnectSTA2AP();
static void WiFiEvent(WiFiEvent_t event);
static bool restart_ESP_module;
static String _hostname;
static bool _events_registered;
};
extern WiFiConfig wifi_config;

View File

@@ -43,6 +43,10 @@
#ifdef ENABLE_TELNET
#include "telnet_server.h"
#endif
#ifdef ENABLE_NOTIFICATIONS
#include "notifications_service.h"
#endif
#include "commands.h"
WiFiServices wifi_services;
@@ -66,18 +70,7 @@ bool WiFiServices::begin(){
WiFi.scanNetworks (true);
//Start SPIFFS
SPIFFS.begin(true);
#ifdef ENABLE_MDNS
//no need in AP mode
if(WiFi.getMode() == WIFI_STA){
//start mDns
if (!MDNS.begin(h.c_str())) {
grbl_send(CLIENT_ALL,"[MSG:Cannot start mDNS]\r\n");
no_error = false;
} else {
grbl_sendf(CLIENT_ALL,"[MSG:Start mDNS with hostname:%s]\r\n",h.c_str());
}
}
#endif
#ifdef ENABLE_OTA
ArduinoOTA
.onStart([]() {
@@ -108,15 +101,33 @@ bool WiFiServices::begin(){
});
ArduinoOTA.begin();
#endif
#ifdef ENABLE_MDNS
//no need in AP mode
if(WiFi.getMode() == WIFI_STA){
//start mDns
if (!MDNS.begin(h.c_str())) {
grbl_send(CLIENT_ALL,"[MSG:Cannot start mDNS]\r\n");
no_error = false;
} else {
grbl_sendf(CLIENT_ALL,"[MSG:Start mDNS with hostname:http://%s.local/]\r\n",h.c_str());
}
}
#endif
#ifdef ENABLE_HTTP
web_server.begin();
#endif
#ifdef ENABLE_TELNET
telnet_server.begin();
#endif
#ifdef ENABLE_NOTIFICATIONS
notificationsservice.begin();
#endif
return no_error;
}
void WiFiServices::end(){
#ifdef ENABLE_NOTIFICATIONS
notificationsservice.end();
#endif
#ifdef ENABLE_TELNET
telnet_server.end();
#endif
@@ -133,11 +144,12 @@ void WiFiServices::end(){
#ifdef ENABLE_MDNS
//Stop mDNS
//MDNS.end();
MDNS.end();
#endif
}
void WiFiServices::handle(){
COMMANDS::wait(0);
#ifdef ENABLE_OTA
ArduinoOTA.handle();
#endif

View File

@@ -6,7 +6,7 @@
### Project Overview
[![Build Status](https://travis-ci.org/bdring/Grbl_Esp32.svg?branch=master)](https://travis-ci.org/bdring/Grbl_Esp32)
[![Build Status](https://travis-ci.com/odaki/Grbl_Esp32.svg?branch=master)](https://travis-ci.com/odaki/Grbl_Esp32)
This is a port of [Grbl](https://github.com/gnea/grbl) for the ESP32. The ESP32 is potentially a great target for Grbl for the following reasons
@@ -20,13 +20,6 @@ This is a port of [Grbl](https://github.com/gnea/grbl) for the ESP32. The ESP32
- **Fast Boot** - Boots almost instantly and does not need to be formally shutdown (unlike Raspberry Pi or Beagle Bone)
- **RTOS (Real Time operating System)** - Custom features can be added without affecting the performance of the motion control system.
### Issues / Changes
1. **Direction pin delay** - Not implemented yet. Some drivers require a couple of microseconds after the direction pin is set before you start the step pulse. The original plan was to [use the RMT feature](http://www.buildlog.net/blog/?s=rmt), but that has issues when trying to use it in an Interrupt. **This is typically a option in Grbl that is not used.**
2. **Limit Switch debouncing** is not supported yet. It does not seem to be a problem on my test rigs. The dev board uses R/C filters on all inputs.
3. **Step Pulse Invert:** This has not been fully tested. I suggest...leaving $2=0
### Using It
@@ -36,16 +29,6 @@ I use the ESP32 Dev Module version of the ESP32. I suggest starting with that if
For basic instructions on using Grbl use the [gnea/grbl wiki](https://github.com/gnea/grbl/wiki). That is the Arduino version of Grbl, so keep that in mind regarding hardware setup. If you have questions ask via the GitHub issue system for this project.
Be sure you have external pullup resistors on any GPIO34-39 that you use. These default to door, start, hold and reset functions.
Using Bluetooth:
- [See the Wiki page](https://github.com/bdring/Grbl_Esp32/wiki/Using-Bluetooth)
Using SD Card
- [See this wiki page](https://github.com/bdring/Grbl_Esp32/wiki/Using-the-SD-Card)
### Roadmap
The roadmap is now [on the wiki](https://github.com/bdring/Grbl_Esp32/wiki/Development-Roadmap).
@@ -68,7 +51,6 @@ Start asking questions...I'll put the frequent ones here.
### Donation
This project requires a lot of work and often expensive items for testing. Please consider a donation to it.
This project requires a lot of work and often expensive items for testing. Please consider a safe, secure and highly appreciated donation via the PayPal link below.
[![](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TKNJ9Z775VXB2)

150
doc/Commands.txt Normal file
View File

@@ -0,0 +1,150 @@
This file defines the [ESP...] style commands. They can be used via serial, Bluetooth or Wifi
These are used for basic wireless settings as well as SD card commands
Some commands need to be authenticated with a password. Authentication
is optional via #define ENABLE_AUTHENTICATION in the config.h file.
The default password is "admin"
============== Examples (assumes "admin" password): ===============
Command: [ESP800]pwd=admin
Reply: FW version:1.1f # FW target:grbl-embedded # FW HW:Direct SD # primary sd:/sd # secondary sd:none # authentication:yes # webcommunication: Sync: 81# hostname:grblesp
Command: [ESP111]
Reply: 192.168.1.11
Command: [ESP121]pwd=admin
Reply: 80
Command: [ESP121]pwd=admin
Reply: 80
Command: [ESP121]81 pwd=admin
Reply: ok
Command: [ESP121]pwd=admin
Reply: 81
=============== Command Reference ========================
* Set/Get STA SSID
[ESP100]<SSID>pwd=<admin password>
* Set STA Password
[ESP101]<Password>pwd=<admin password>
* Set/Get STA IP mode (DHCP/STATIC)
[ESP102]<mode>pwd=<admin password>
* Set/Get STA IP/Mask/GW
[ESP103]IP=<IP> MSK=<IP> GW=<IP> pwd=<admin password>
* Set/Get AP SSID
[ESP105]<SSID>pwd=<admin password>
* Change AP Password
[ESP106]<Password>pwd=<admin password>
* Set/Get AP IP
[ESP107]<IP>pwd=<admin password>
* Set/Get AP channel
[ESP108]<channel>pwd=<admin password>
* Set/Get radio state which can be STA, AP, BT, OFF
[ESP110]<state>pwd=<admin password>
* Get current IP
[ESP111]<header answer>
* Get/Set hostname
[ESP112]<Hostname> pwd=<admin password>
* Get/Set immediate Radio (WiFi/BT) state which can be ON, OFF
[ESP115]<state>pwd=<admin password>
* Get/Set HTTP state which can be ON, OFF
[ESP120]<state>pwd=<admin password>
* Get/Set HTTP port
[ESP121]<port>pwd=<admin password>
* Get/Set Telnet state which can be ON, OFF
[ESP130]<state>pwd=<admin password>
* Get/Set Telnet port
[ESP131]<port>pwd=<admin password>
* Get/Set btname
[ESP140]< Bluetooth name> pwd=<admin password>
* Get SD Card Status
[ESP200] pwd=<user/admin password>
* Get SD Card Content
[ESP210] pwd=<user/admin password>
* Print SD file
[ESP220] <Filename> pwd=<user/admin password>
*Get full EEPROM settings content
but do not give any passwords
[ESP400] pwd=<user/admin password>
*Set EEPROM setting
position in EEPROM, type: B(byte), I(integer/long), S(string), A(IP address / mask)
[ESP401]P=<position> T=<type> V=<value> pwd=<user/admin password>
Positions:
HOSTNAME_ENTRY "ESP_HOSTNAME" String
STA_SSID_ENTRY "STA_SSID" String
STA_PWD_ENTRY "STA_PWD" String
STA_IP_ENTRY "STA_IP" IP
STA_GW_ENTRY "STA_GW" IP
STA_MK_ENTRY "STA_MK" IP
ESP_WIFI_MODE "WIFI_MODE" Byte (0=OFF, STA=1, AP=2)
AP_SSID_ENTRY "AP_SSID" String
AP_PWD_ENTRY "AP_PWD" String
AP_IP_ENTRY "AP_IP" IP
AP_CHANNEL_ENTRY "AP_CHANNEL" Byte
HTTP_ENABLE_ENTRY "HTTP_ON" Byte (0=Disabled, 1=Enabled)
HTTP_PORT_ENTRY "HTTP_PORT" Integer
TELNET_ENABLE_ENTRY "TELNET_ON" Byte (0=Disabled, 1=Enabled)
TELNET_PORT_ENTRY "TELNET_PORT" Integer
STA_IP_MODE_ENTRY "STA_IP_MODE" Byte (0=DHCP, 1=STATIC)
*Get available AP list (limited to 30)
output is JSON or plain text according parameter
[ESP410] pwd=<user/admin password>
*Get current settings of ESP3D
output is JSON or plain text according parameter
[ESP420]pwd=<user/admin password>
* Restart ESP
[ESP444]RESTART pwd=<admin password>
* Change / Reset user password
[ESP555]<password>pwd=<admin password>
if no password set it use default one
* Send Notification
[ESP600]msg [pwd=<admin password>]
* Set/Get Notification settings
[ESP610]type=<NONE/PUSHOVER/EMAIL/LINE> T1=<token1> T2=<token2> TS=<Settings> [pwd=<admin password>]
Get will give type and settings only, not the protected T1/T2
* Read SPIFFS file and send each line to serial
[ESP700]<filename> pwd=<user/admin password>
* Format SPIFFS
[ESP710]FORMAT pwd=<admin password>
* SPIFFS total size and used size
[ESP720]<header answer> pwd=<user/admin password>
* Get fw version and basic information
[ESP800]<header answer>

1
embedded/build.bat Normal file
View File

@@ -0,0 +1 @@
bin2c /infile tool.html.gz /outfile out.h /targetfolder .

125
embedded/gulpfile.js Normal file
View File

@@ -0,0 +1,125 @@
var gulp = require('gulp'),
jshint = require('gulp-jshint'),
gulpif = require('gulp-if'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
cleanCSS = require('gulp-clean-css'),
removeCode = require('gulp-remove-code'),
merge = require('merge-stream'),
del = require('del'),
zip = require('gulp-zip'),
gzip = require('gulp-gzip'),
htmlmin = require('gulp-htmlmin'),
replace = require('gulp-replace'),
fs = require('fs'),
smoosher = require('gulp-smoosher');
var demoMode = false;
var testMode = false;
function clean() {
return del(['dist']);
}
function clean2() {
return del(['dist/js', 'dist/css']);
}
function lint() {
return gulp.src('www/js/**/script.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
}
function Copytest() {
return merge(
gulp.src(['www/tool.html'])
.pipe(removeCode({production: false}))
.pipe(gulp.dest('dist')),
gulp.src(['www/images/**/*.*'])
.pipe(gulp.dest('dist/images'))
)
}
function Copy() {
return merge(
gulp.src(['www/tool.html'])
.pipe(removeCode({production: true}))
.pipe(gulp.dest('dist')),
gulp.src(['www/images/**/*.*'])
.pipe(gulp.dest('dist/images'))
)
}
function concatApptest() {
return merge(
gulp.src([ 'www/js/**/*.js'])
.pipe(concat('script.js'))
.pipe(removeCode({production: false}))
.pipe(gulp.dest('./dist/js')),
gulp.src([ 'www/css/**/*.css'])
.pipe(concat('style.css'))
.pipe(gulp.dest('./dist/css/'))
)
}
function concatApp() {
return merge(
gulp.src([ 'www/js/**/*.js'])
.pipe(concat('script.js'))
.pipe(removeCode({production: true}))
.pipe(gulp.dest('./dist/js')),
gulp.src([ 'www/css/**/*.css'])
.pipe(concat('style.css'))
.pipe(gulp.dest('./dist/css/'))
)
}
function minifyApp() {
return merge(
gulp.src(['dist/js/script.js'])
.pipe(uglify({mangle: true}))
.pipe(gulp.dest('./dist/js/')),
gulp.src('dist/css/style.css')
.pipe(cleanCSS({debug: true}, function(details) {
console.log(details.name + ': ' + details.stats.originalSize);
console.log(details.name + ': ' + details.stats.minifiedSize);
}))
.pipe(gulp.dest('./dist/css/')),
gulp.src('dist/tool.html')
.pipe(htmlmin({collapseWhitespace: true, minifyCSS: true}))
.pipe(gulp.dest('dist'))
)
}
function smoosh() {
return gulp.src('dist/tool.html')
.pipe(smoosher())
.pipe(gulp.dest('dist'))
}
function compress() {
return gulp.src('dist/tool.html')
.pipe(gzip())
.pipe(gulp.dest('.'));
}
gulp.task(clean);
gulp.task(lint);
gulp.task(Copy);
gulp.task(Copytest);
gulp.task(concatApp);
gulp.task(concatApptest);
gulp.task(minifyApp);
gulp.task(smoosh);
gulp.task(clean2);
var defaultSeries = gulp.series(clean, lint, Copy, concatApp, smoosh);
var packageSeries = gulp.series(clean, lint, Copy, concatApp,minifyApp, smoosh, compress, clean2);
gulp.task('default', defaultSeries);
gulp.task('package', packageSeries);

15
embedded/install.bat Normal file
View File

@@ -0,0 +1,15 @@
npm install --global gulp-cli
npm install --save-dev gulp
npm install --save-dev gulp-jshint
npm install --save-dev jshint
npm install --save-dev gulp-if
npm install --save-dev gulp-concat
npm install --save-dev gulp-uglify
npm install --save-dev gulp-clean-css
npm install --save-dev gulp-remove-code
npm install --save-dev del
npm install --save-dev gulp-zip
npm install --save-dev gulp-gzip
npm install --save-dev gulp-htmlmin
npm install --save-dev gulp-replace
npm install --save-dev gulp-smoosher

319
embedded/out.h Normal file
View File

@@ -0,0 +1,319 @@
/*
File Generated with bin2c Conversion Tool v0.14.0 - Windows - [FINAL].
Free for any use.
Compiled on Jan 1 2017 at 05:41:46.
DO NOT MODIFY THIS FILE!!!
*/
/*
ut.h
*/
const unsigned char a[4862] = {
0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xED, 0x5C, 0x7D, 0x93, 0xDA, 0x46,
0x93, 0xFF, 0x2A, 0xB2, 0x52, 0x36, 0x70, 0x2B, 0x40, 0x12, 0xAF, 0x8B, 0x16, 0xF2, 0x24, 0xB1,
0x7D, 0xF1, 0x95, 0x13, 0xBB, 0xBC, 0xEB, 0x7B, 0xAE, 0x2A, 0x4E, 0xB9, 0x84, 0x34, 0x80, 0xCE,
0x42, 0xD2, 0x49, 0xC3, 0xEE, 0x62, 0xC2, 0x77, 0xBF, 0xEE, 0x79, 0x91, 0x46, 0x42, 0xB0, 0xEC,
0x26, 0x79, 0xF2, 0xFC, 0x91, 0x60, 0x23, 0x98, 0x99, 0xEE, 0xE9, 0xE9, 0xE9, 0xFE, 0x75, 0x4F,
0x0F, 0xCE, 0xD5, 0x8A, 0xAE, 0xC3, 0xD9, 0xD5, 0x8A, 0xB8, 0xFE, 0xEC, 0x2A, 0xA3, 0xDB, 0x90,
0xCC, 0xB0, 0x65, 0xB7, 0x88, 0x23, 0xDA, 0x5E, 0xB8, 0xEB, 0x20, 0xDC, 0x4E, 0x32, 0x37, 0xCA,
0xDA, 0x19, 0x49, 0x83, 0x85, 0xD3, 0x5E, 0x67, 0x6D, 0x4A, 0xEE, 0x69, 0x3B, 0x0B, 0xBE, 0x92,
0xB6, 0xEB, 0xFF, 0xEF, 0x26, 0xA3, 0x13, 0xCB, 0x34, 0x9F, 0x3B, 0xED, 0x3B, 0x32, 0xFF, 0x12,
0xD0, 0x23, 0xBD, 0x8C, 0x1D, 0xB6, 0xC2, 0xD7, 0xE4, 0x7E, 0x3F, 0x8F, 0xFD, 0x6D, 0x69, 0x0A,
0xFD, 0x47, 0x12, 0xDE, 0x12, 0x1A, 0x78, 0xAE, 0xF6, 0x33, 0xD9, 0x10, 0xDD, 0xC8, 0xBF, 0x1B,
0xDF, 0xA5, 0x81, 0x1B, 0x1A, 0x8A, 0x0C, 0x0A, 0xAF, 0x7E, 0x72, 0xEF, 0x84, 0x41, 0x44, 0xDA,
0x2B, 0x12, 0x2C, 0x57, 0x30, 0x57, 0xA7, 0x6F, 0x8F, 0x07, 0x23, 0xAB, 0xDF, 0x73, 0xBC, 0x38,
0x8C, 0xD3, 0xC9, 0x37, 0xBD, 0x5E, 0xCF, 0x99, 0xBB, 0xDE, 0x97, 0x65, 0x1A, 0x6F, 0x22, 0xBF,
0x2D, 0x5A, 0x17, 0x8B, 0xC5, 0xBE, 0xE3, 0x01, 0x1F, 0x17, 0x88, 0xD3, 0xDD, 0xDA, 0x4D, 0x97,
0x41, 0xD4, 0x4E, 0x19, 0x0F, 0x77, 0x43, 0x63, 0x47, 0xB4, 0x84, 0x64, 0x21, 0x1A, 0x12, 0xD7,
0xF7, 0x83, 0x68, 0xC9, 0x5B, 0xAC, 0x01, 0xCC, 0x2B, 0x5B, 0x38, 0x15, 0x36, 0xED, 0xA9, 0x3B,
0x0F, 0xC9, 0x6E, 0x1E, 0xA7, 0x3E, 0x49, 0x27, 0xA6, 0xC3, 0x3F, 0xB4, 0xB3, 0xC4, 0xF5, 0x60,
0x20, 0x34, 0xAC, 0xDD, 0xFB, 0xF6, 0x5D, 0xE0, 0xD3, 0x15, 0x53, 0xCA, 0xBE, 0xC3, 0xC6, 0xB7,
0xF9, 0x30, 0xE2, 0xEF, 0x8A, 0x2E, 0x41, 0x3A, 0xB1, 0x92, 0x7B, 0x2D, 0x8B, 0xC3, 0xC0, 0xD7,
0xBE, 0xF1, 0x7D, 0x5F, 0x4A, 0x35, 0x8F, 0x29, 0x8D, 0xD7, 0x13, 0x1B, 0x35, 0x49, 0x81, 0x6C,
0x15, 0x50, 0xC2, 0x66, 0x21, 0x93, 0x28, 0xBE, 0x4B, 0xDD, 0x44, 0xCA, 0x36, 0xB1, 0xD7, 0xEB,
0x3D, 0x5D, 0xED, 0xD8, 0x9E, 0xB8, 0x61, 0xB0, 0x8C, 0x26, 0x28, 0xBF, 0x98, 0x78, 0x46, 0x71,
0x1B, 0x66, 0x34, 0x9D, 0x51, 0xDF, 0x38, 0x68, 0x5A, 0xE5, 0x4D, 0xCC, 0x36, 0xCA, 0xA3, 0xF2,
0xA6, 0xD5, 0x4E, 0x4E, 0x35, 0x3E, 0xBE, 0x15, 0xB7, 0x24, 0xC5, 0x9D, 0x0C, 0x85, 0x08, 0x34,
0x4E, 0xA4, 0x6A, 0xE0, 0x63, 0x65, 0x8D, 0x55, 0xA5, 0xD4, 0x08, 0x59, 0xD7, 0xB7, 0x3A, 0xEC,
0x3B, 0x10, 0xBB, 0xAE, 0x6F, 0xB5, 0xAB, 0xD5, 0xF4, 0xA1, 0x14, 0x8F, 0xE2, 0x26, 0x76, 0x48,
0xEC, 0xB5, 0x0D, 0xDB, 0x24, 0x68, 0x32, 0x9A, 0x06, 0x89, 0x22, 0xF8, 0x24, 0xA2, 0xAB, 0x76,
0xBC, 0x68, 0xD3, 0x6D, 0x42, 0x9A, 0xB1, 0xEF, 0xB7, 0x76, 0x35, 0xB6, 0x7A, 0x89, 0xAF, 0xFD,
0x3F, 0xD6, 0xC4, 0x0F, 0x5C, 0xAD, 0xB9, 0x06, 0x03, 0xE0, 0x7C, 0x47, 0x43, 0xD0, 0x79, 0x6B,
0xA7, 0xD8, 0xB1, 0x68, 0x1F, 0xA0, 0x61, 0xD4, 0x10, 0x5C, 0x5E, 0xDA, 0xB5, 0x04, 0x97, 0xA3,
0x23, 0x04, 0x96, 0x6D, 0x9A, 0xB5, 0x14, 0x96, 0xC5, 0x49, 0x3A, 0x91, 0x7B, 0xAB, 0x9A, 0xAD,
0x10, 0xD9, 0xF3, 0xBC, 0x8A, 0xC3, 0x98, 0x55, 0x77, 0x31, 0xC1, 0x58, 0x32, 0x70, 0x63, 0x44,
0x1C, 0xB0, 0xDA, 0x88, 0xD4, 0x78, 0x29, 0xF3, 0x5D, 0xAE, 0xD0, 0xD4, 0xF5, 0x83, 0x4D, 0x36,
0x19, 0x82, 0x91, 0xD5, 0x38, 0x81, 0xBB, 0x4B, 0xE2, 0x2C, 0xA0, 0x41, 0x1C, 0x4D, 0x52, 0x12,
0xBA, 0x34, 0xB8, 0x25, 0x8E, 0x1F, 0x64, 0x49, 0xE8, 0x6E, 0x27, 0xF3, 0x30, 0xF6, 0xBE, 0xE4,
0x0E, 0x81, 0xE8, 0xA3, 0x31, 0xF7, 0x65, 0x3E, 0xE1, 0x13, 0x2F, 0x4E, 0x5D, 0x46, 0xC8, 0x64,
0x28, 0xE4, 0xDF, 0x77, 0x5C, 0x0F, 0xF9, 0xEC, 0x0A, 0xC4, 0xA8, 0x91, 0xD0, 0x34, 0x4D, 0x39,
0x50, 0x73, 0x0D, 0x77, 0xB2, 0x88, 0xBD, 0x4D, 0x06, 0xCF, 0x55, 0x0C, 0x36, 0xBF, 0x53, 0xC1,
0x26, 0x71, 0x23, 0x12, 0xEE, 0x0E, 0x65, 0xAF, 0x07, 0xA7, 0x23, 0xFE, 0x5F, 0x56, 0x06, 0x82,
0x9F, 0x44, 0xDD, 0x79, 0x7C, 0xDF, 0xCE, 0x56, 0xAE, 0x1F, 0xDF, 0x4D, 0x4C, 0x0D, 0xA9, 0xF0,
0x6F, 0xBA, 0x9C, 0xBB, 0x4D, 0xD3, 0xC0, 0x57, 0xC7, 0x1C, 0xB4, 0x9C, 0x73, 0x06, 0x09, 0x49,
0xDB, 0x0C, 0xA1, 0x73, 0xAD, 0x21, 0xB8, 0x89, 0x0E, 0x34, 0x76, 0x68, 0xDB, 0x1D, 0x6A, 0xF4,
0x34, 0xE2, 0x0E, 0xF0, 0x25, 0x57, 0x20, 0x1A, 0x95, 0x35, 0x01, 0x12, 0x70, 0xD3, 0x90, 0xAB,
0xEB, 0xA1, 0x6E, 0x8A, 0x3E, 0x34, 0xA3, 0x9A, 0x2E, 0xA1, 0xC9, 0x8A, 0xF7, 0x86, 0xEE, 0x1C,
0x94, 0x2D, 0x2D, 0x20, 0x88, 0x18, 0x2E, 0x71, 0x43, 0x28, 0x43, 0x70, 0xC5, 0x98, 0x70, 0x15,
0x2C, 0xBA, 0xDC, 0x71, 0x0C, 0x1B, 0xE1, 0xF6, 0x32, 0x43, 0x09, 0xA2, 0x45, 0x2C, 0xF7, 0xB3,
0x07, 0xC6, 0x3F, 0x86, 0x2D, 0x5D, 0xC4, 0xE9, 0xBA, 0x8D, 0x9E, 0x91, 0xC6, 0xC5, 0x64, 0x7C,
0x16, 0x3E, 0x03, 0x0B, 0x1C, 0x02, 0x0E, 0x7B, 0xFD, 0x22, 0x64, 0xA0, 0x19, 0x6B, 0x96, 0x2D,
0x27, 0x3B, 0x37, 0x94, 0x0D, 0x06, 0x83, 0x63, 0xD6, 0x52, 0xB4, 0x06, 0x6B, 0x77, 0x29, 0x1D,
0xEA, 0xC0, 0x86, 0xD0, 0x2F, 0xCF, 0xB2, 0xA1, 0x20, 0xCA, 0x08, 0xD5, 0x8E, 0x18, 0xC9, 0xA8,
0x6C, 0x4A, 0x0F, 0x8E, 0x6D, 0xC7, 0x6D, 0x9A, 0x42, 0xF8, 0xE6, 0x0E, 0xAA, 0x5A, 0x80, 0x46,
0xDC, 0x8C, 0x80, 0x6E, 0xDB, 0xF1, 0x86, 0x6A, 0x1D, 0x6B, 0x90, 0x19, 0x05, 0xDF, 0x83, 0xBE,
0xB2, 0xC2, 0xB9, 0xAB, 0xED, 0xCA, 0xF6, 0x34, 0x1C, 0xBA, 0x0B, 0x72, 0xE9, 0x00, 0x05, 0x6A,
0x12, 0x02, 0xEE, 0x13, 0x96, 0x66, 0x98, 0xD0, 0x39, 0x96, 0x1D, 0x96, 0x69, 0x1B, 0xD6, 0x68,
0x60, 0xD8, 0xBD, 0x9E, 0xD1, 0x19, 0xB6, 0x84, 0x0C, 0xA8, 0xEB, 0xA4, 0xE2, 0xCC, 0xDC, 0x47,
0xE6, 0x34, 0x3A, 0x66, 0x77, 0xEA, 0x60, 0xB3, 0x64, 0x66, 0x7D, 0xD3, 0x74, 0x94, 0x10, 0xED,
0x91, 0x88, 0x92, 0xB4, 0x1A, 0x35, 0xD7, 0x81, 0xEF, 0x87, 0x84, 0x27, 0x60, 0xF1, 0xC6, 0x5B,
0xB5, 0x11, 0x76, 0x40, 0x9F, 0x6B, 0x37, 0x0A, 0x92, 0x4D, 0xC8, 0x40, 0xCC, 0x39, 0xDE, 0xE3,
0x6D, 0xD2, 0x0C, 0x54, 0x94, 0xC4, 0x01, 0x63, 0x7E, 0xA6, 0xC5, 0xB0, 0x7D, 0x4B, 0xDC, 0x14,
0x24, 0x72, 0x4E, 0xA4, 0x19, 0x8F, 0xB4, 0xE7, 0x1A, 0x13, 0x5C, 0xC7, 0x5F, 0xDB, 0x9B, 0x0C,
0x93, 0x25, 0x12, 0x12, 0x8F, 0x72, 0x71, 0x70, 0xAD, 0x07, 0x8D, 0xD5, 0x06, 0xA6, 0xF3, 0x76,
0x92, 0xC2, 0x32, 0xD2, 0xED, 0x69, 0xB4, 0xEE, 0xF5, 0x46, 0xEE, 0x7C, 0x54, 0xC1, 0x20, 0x9B,
0x0C, 0x7D, 0xB7, 0x5F, 0xE2, 0x22, 0x10, 0xDD, 0x28, 0xB5, 0x71, 0x68, 0x2F, 0x35, 0x31, 0x94,
0x2F, 0x35, 0x4D, 0x6A, 0x28, 0x27, 0x87, 0x94, 0x07, 0xF1, 0xA1, 0x46, 0x58, 0x7B, 0x3C, 0x34,
0x2F, 0xCD, 0x8A, 0xB0, 0x96, 0x6D, 0xCF, 0xFB, 0xE6, 0xDE, 0x73, 0x13, 0xDC, 0x54, 0x89, 0xC1,
0x2C, 0x8D, 0x1A, 0x2B, 0x29, 0xA9, 0xB0, 0xB2, 0x71, 0x01, 0xCA, 0xA3, 0xD1, 0xC8, 0x39, 0xC8,
0x02, 0xDD, 0x10, 0x4C, 0xAC, 0x04, 0xF2, 0x35, 0xC1, 0xF5, 0xB4, 0x51, 0x1C, 0x6C, 0xA5, 0xE0,
0xDA, 0xCE, 0x36, 0x9E, 0x47, 0xB2, 0xAC, 0x26, 0x9F, 0xF1, 0x17, 0x0B, 0xD3, 0x1F, 0x57, 0x23,
0xC1, 0x90, 0x5C, 0x7A, 0xC3, 0x3C, 0x84, 0x78, 0xA3, 0x61, 0xCF, 0x97, 0xAC, 0x7C, 0x37, 0x5A,
0x82, 0xB6, 0x6A, 0xA0, 0xCF, 0xF6, 0x89, 0x4F, 0x2A, 0x9C, 0xC8, 0xDC, 0xF3, 0x7C, 0x4B, 0x72,
0x72, 0x2F, 0xFB, 0xFD, 0xBE, 0xBD, 0xEF, 0xAC, 0xDC, 0xAC, 0x4D, 0xD2, 0x14, 0x20, 0xA7, 0x0C,
0xDB, 0x65, 0x5A, 0x3E, 0xFA, 0xCF, 0x06, 0xC4, 0xA3, 0xD2, 0xD4, 0x62, 0xDA, 0xB8, 0xDF, 0x1B,
0xF4, 0xFA, 0x4F, 0x46, 0x32, 0x74, 0xCD, 0x6F, 0x3C, 0x32, 0xEE, 0x8F, 0x7B, 0x8F, 0x91, 0xB1,
0x4A, 0x5B, 0x92, 0x59, 0x88, 0xDB, 0xE6, 0x61, 0xB6, 0x46, 0xD3, 0x62, 0xF3, 0x4F, 0xEA, 0x9A,
0xEF, 0xF1, 0xBF, 0x46, 0xD7, 0xB5, 0xF2, 0xD4, 0x6A, 0xDB, 0x9E, 0x0F, 0xFA, 0xB6, 0xF7, 0xFB,
0xB4, 0x3D, 0x1C, 0xCD, 0xAD, 0xE1, 0xF8, 0x69, 0xDA, 0xE6, 0xB4, 0x15, 0xA9, 0x6B, 0xF5, 0x2D,
0x7D, 0x04, 0x61, 0x45, 0x78, 0xC8, 0x49, 0x3C, 0xF1, 0x2F, 0xC1, 0x8C, 0x16, 0x55, 0xB7, 0xEB,
0xF7, 0x16, 0x3D, 0x57, 0x65, 0x52, 0xC2, 0x3E, 0xD1, 0xA4, 0x00, 0x98, 0x68, 0x51, 0x90, 0x8F,
0xB7, 0x4C, 0x0E, 0xC9, 0x26, 0x07, 0x64, 0xE7, 0xC0, 0x9E, 0x77, 0xD9, 0x33, 0x6D, 0xAF, 0x22,
0xE6, 0x68, 0x68, 0x79, 0xD6, 0x25, 0x13, 0x33, 0x58, 0x2F, 0x77, 0x22, 0x96, 0xAD, 0xDC, 0xA8,
0x9A, 0x12, 0x0F, 0xEB, 0xF0, 0x8A, 0x27, 0xE0, 0x9C, 0x56, 0x88, 0x50, 0x83, 0x25, 0x26, 0xBE,
0x2A, 0xF3, 0x9A, 0x20, 0xE2, 0x5F, 0xEE, 0x78, 0x20, 0x38, 0x93, 0xF4, 0xF4, 0xCA, 0x7B, 0xA6,
0x48, 0x3F, 0xE4, 0xD8, 0x87, 0x56, 0xFA, 0xD7, 0xAF, 0x2B, 0x04, 0xD1, 0x20, 0x43, 0xF8, 0x22,
0x0D, 0x82, 0x1D, 0xA6, 0xF2, 0xD6, 0x89, 0xB0, 0xB1, 0x45, 0x10, 0x12, 0xF6, 0x9D, 0xBB, 0x6B,
0x3E, 0xF6, 0xB2, 0x0F, 0xBB, 0x1A, 0x44, 0xC9, 0x86, 0xFE, 0x82, 0xA7, 0xE7, 0x29, 0x8E, 0xFB,
0x75, 0x32, 0x91, 0xCB, 0xC2, 0xAF, 0xED, 0x4D, 0x12, 0xC6, 0xAE, 0xDF, 0x9E, 0x6F, 0x20, 0x9A,
0xFD, 0x9D, 0x97, 0xFD, 0x6B, 0xF3, 0x32, 0xE7, 0xA4, 0x9B, 0x0F, 0xE6, 0x9E, 0x79, 0x10, 0xBA,
0xFB, 0xC3, 0xF9, 0xD8, 0x77, 0x1F, 0xB5, 0xA9, 0xC2, 0x2A, 0xFE, 0xDE, 0xDA, 0x7F, 0x9F, 0xAD,
0xED, 0x59, 0x73, 0xD3, 0xAF, 0x9E, 0xF4, 0xAD, 0xF9, 0xD0, 0x1F, 0x0F, 0x1E, 0xB7, 0xB5, 0x1C,
0xC0, 0xFE, 0xDE, 0xDA, 0x7F, 0xF3, 0xAD, 0xB5, 0x87, 0x97, 0xEE, 0xDC, 0xDB, 0xE7, 0x40, 0x5D,
0x82, 0xF3, 0x32, 0x7A, 0x2B, 0x68, 0x5E, 0x4A, 0x05, 0x04, 0x9A, 0x8B, 0x0A, 0xD3, 0x22, 0x8E,
0x41, 0xA9, 0x27, 0x0A, 0x4C, 0xAC, 0xFE, 0xF2, 0xB4, 0x1A, 0xD3, 0x41, 0x9D, 0x17, 0x0D, 0x0E,
0xC3, 0x24, 0xDF, 0xAB, 0xBE, 0x92, 0x34, 0xF4, 0xF0, 0xA5, 0x92, 0x2A, 0x9D, 0xBD, 0xFE, 0xE5,
0xD8, 0x9F, 0x57, 0x54, 0x3F, 0x30, 0x9F, 0x3B, 0xB2, 0x6E, 0x0A, 0xD2, 0xCA, 0x9D, 0xC2, 0xCF,
0x60, 0x3B, 0x6B, 0x5E, 0x66, 0xCC, 0x92, 0x20, 0xD2, 0xEC, 0x4C, 0xC3, 0xCD, 0x74, 0x53, 0x2D,
0x88, 0x16, 0x41, 0x04, 0x96, 0xB0, 0xFF, 0xC7, 0x17, 0xB2, 0x5D, 0xA4, 0xEE, 0x9A, 0x64, 0x1A,
0x0E, 0xD9, 0x99, 0xCF, 0x77, 0xCC, 0x5C, 0x30, 0x63, 0x9D, 0xA4, 0x31, 0x75, 0x29, 0x69, 0x9A,
0xAD, 0x3D, 0x16, 0xAD, 0x0E, 0x3B, 0x7A, 0x43, 0x00, 0xD3, 0x65, 0x6B, 0xFF, 0x97, 0x68, 0x70,
0x1D, 0xFB, 0x6E, 0x51, 0xFF, 0x62, 0x46, 0x94, 0x57, 0x63, 0x17, 0xC1, 0x3D, 0xF1, 0x9D, 0xAF,
0xED, 0x20, 0xF2, 0xC9, 0x3D, 0x56, 0xDC, 0xCC, 0xA2, 0x10, 0xCC, 0x78, 0x61, 0x7D, 0xD9, 0x61,
0x25, 0x62, 0x70, 0x5A, 0x68, 0x30, 0x1D, 0xA5, 0x38, 0x27, 0x35, 0x88, 0x9F, 0xD1, 0x5C, 0x16,
0x21, 0x24, 0x1A, 0xAC, 0xA8, 0x56, 0x5B, 0x89, 0x3D, 0x6C, 0x55, 0x93, 0x90, 0x7E, 0x4B, 0x88,
0xCA, 0xF2, 0x7F, 0x70, 0xC1, 0x5D, 0xB1, 0xA6, 0x52, 0x75, 0xD1, 0x32, 0xCB, 0x95, 0xC7, 0x52,
0x55, 0x52, 0xED, 0x14, 0x45, 0xFE, 0x63, 0xB4, 0xA2, 0xFB, 0x18, 0x39, 0x5E, 0x0B, 0xE4, 0xE6,
0x24, 0x0B, 0x13, 0x4A, 0x7D, 0x16, 0x4B, 0x50, 0x16, 0x42, 0x81, 0x59, 0xCA, 0xA5, 0xEC, 0x96,
0x73, 0x58, 0xEB, 0xE6, 0x70, 0x58, 0xBA, 0xA8, 0x9A, 0xD4, 0xA8, 0xE3, 0x9B, 0x05, 0xC1, 0x97,
0xD4, 0x03, 0x56, 0x72, 0x15, 0x2B, 0xB1, 0xC5, 0x84, 0x4E, 0x9E, 0xFC, 0xE2, 0xAB, 0x8E, 0x8B,
0x8D, 0xAF, 0x63, 0xC5, 0xD9, 0x47, 0xAA, 0xAF, 0x54, 0x9E, 0x5C, 0xE0, 0x4B, 0x8A, 0x57, 0xAE,
0x40, 0x9B, 0x42, 0x3A, 0xD9, 0x5B, 0x35, 0xF1, 0xA1, 0x94, 0x5E, 0x18, 0x4D, 0xBF, 0x33, 0x20,
0xEB, 0xC7, 0x2F, 0xE5, 0x50, 0x9C, 0xDF, 0xB9, 0xDB, 0x27, 0xEE, 0x6D, 0xCA, 0xD6, 0xC8, 0xFB,
0x06, 0x63, 0xF5, 0x2A, 0x26, 0xF3, 0x52, 0x42, 0x22, 0x0D, 0xB2, 0x7D, 0xA0, 0xCF, 0x0B, 0xD7,
0xA3, 0xE1, 0xE8, 0x28, 0x3D, 0xBB, 0x57, 0xDC, 0x5F, 0x75, 0xF9, 0x4D, 0xEE, 0x55, 0x97, 0xDF,
0xEB, 0xB2, 0xDB, 0xA6, 0x2B, 0x3F, 0xB8, 0xD5, 0x58, 0xFB, 0x54, 0xCF, 0x4D, 0xC8, 0x9D, 0xC3,
0x62, 0x37, 0x94, 0x08, 0xE7, 0xE3, 0x97, 0x33, 0xA6, 0x3E, 0xFB, 0x6F, 0xAB, 0x63, 0x6B, 0x2F,
0xA2, 0x79, 0x96, 0x38, 0xFC, 0xFD, 0xAA, 0x0B, 0xE4, 0xB3, 0x2B, 0x1E, 0x4D, 0x67, 0x57, 0x2B,
0x7B, 0xF6, 0x86, 0x6A, 0x19, 0x21, 0xEB, 0x4C, 0xDB, 0xC6, 0x1B, 0xCD, 0x8F, 0xB5, 0x28, 0xA6,
0xDA, 0xCA, 0xC5, 0x8B, 0x90, 0x68, 0xAB, 0x31, 0x87, 0xEF, 0xE0, 0x4D, 0xB2, 0x16, 0x91, 0x80,
0xAE, 0x48, 0xAA, 0x34, 0x75, 0x96, 0x5F, 0x0D, 0x2D, 0x09, 0xB1, 0xC0, 0xAB, 0xF1, 0x90, 0xAF,
0x05, 0x54, 0x8B, 0x53, 0xF8, 0xE2, 0x03, 0x9C, 0x21, 0xC3, 0x54, 0x5B, 0x04, 0xE9, 0xFA, 0x0E,
0x62, 0xA5, 0x16, 0x2C, 0x80, 0x05, 0x1E, 0x84, 0xB1, 0xE4, 0x06, 0x2B, 0xB2, 0x67, 0x38, 0xA1,
0xE7, 0x46, 0x30, 0x04, 0x14, 0x03, 0x78, 0xA3, 0x01, 0x7B, 0xA2, 0x4D, 0xB4, 0x2B, 0x57, 0xF3,
0x42, 0x37, 0xCB, 0xA6, 0x7A, 0x7E, 0x8A, 0xD0, 0xB5, 0x55, 0x4A, 0x16, 0x53, 0x7D, 0x45, 0x69,
0x92, 0x4D, 0xBA, 0xDD, 0x25, 0xC8, 0xB2, 0x99, 0xC3, 0x89, 0x7A, 0xDD, 0x0D, 0x37, 0x5E, 0x9B,
0x7F, 0xED, 0xBE, 0xBA, 0x7E, 0xDF, 0x7B, 0xD9, 0xFE, 0xE7, 0xAB, 0xEF, 0x3F, 0xBE, 0xD1, 0x67,
0x67, 0x0F, 0xBD, 0xEA, 0xBA, 0xA0, 0x61, 0xA9, 0x11, 0xD4, 0xAE, 0x98, 0x9D, 0x81, 0xB0, 0xAE,
0x05, 0xFE, 0x54, 0xBF, 0x7E, 0xFF, 0xE6, 0xF5, 0xEB, 0x6B, 0xFD, 0xB0, 0x5B, 0xDE, 0xA3, 0xE8,
0xB3, 0xD7, 0xD0, 0xBA, 0xD2, 0x5E, 0x43, 0x60, 0xCC, 0xB6, 0x19, 0x25, 0x6B, 0xA1, 0xE9, 0x03,
0x02, 0xDC, 0x44, 0x60, 0xC4, 0x52, 0x28, 0x8D, 0xA5, 0x50, 0x3A, 0x46, 0x53, 0x3E, 0x0F, 0x4B,
0x9F, 0x78, 0x1C, 0xD7, 0xB5, 0x08, 0xC2, 0xC8, 0x54, 0x5F, 0x6F, 0xB1, 0x31, 0xFB, 0xE5, 0x57,
0x5D, 0x5B, 0x6F, 0x42, 0x1A, 0x24, 0xB8, 0xF1, 0xF2, 0x93, 0x3E, 0xD3, 0x04, 0x27, 0xA9, 0x31,
0x1A, 0x69, 0x4A, 0x85, 0x52, 0x17, 0x33, 0xF0, 0x54, 0x8C, 0xCF, 0x51, 0xCA, 0xCE, 0x74, 0x50,
0xBC, 0x17, 0x06, 0xDE, 0x17, 0x58, 0x23, 0x89, 0x7C, 0x9C, 0xAA, 0xD9, 0x72, 0x74, 0xED, 0xD6,
0x0D, 0x37, 0x40, 0xF7, 0x91, 0x8D, 0xD5, 0x67, 0x25, 0x13, 0x4A, 0xD2, 0x78, 0x99, 0x62, 0x45,
0x43, 0x58, 0xE1, 0x6D, 0x90, 0x05, 0xF3, 0x20, 0x0C, 0xE8, 0x76, 0xB2, 0x82, 0x7C, 0x8C, 0x44,
0x52, 0xF4, 0x24, 0x5D, 0xF2, 0x29, 0xD9, 0x07, 0xB0, 0xFC, 0xA9, 0x0E, 0x86, 0x0D, 0x8B, 0xEF,
0x4A, 0x16, 0x60, 0xD3, 0x29, 0xFF, 0x7B, 0xA0, 0xF7, 0xE3, 0xAA, 0xE3, 0x97, 0xD7, 0x57, 0x14,
0xA8, 0xA8, 0xAF, 0x31, 0x87, 0x99, 0xEA, 0xE6, 0xF3, 0x5C, 0xA9, 0xE7, 0xA9, 0xA2, 0xB4, 0xEE,
0x1F, 0xE2, 0x35, 0x24, 0x86, 0x7E, 0xB3, 0x81, 0xB7, 0x99, 0x0D, 0xA3, 0xE1, 0x86, 0x61, 0x43,
0x51, 0xC3, 0x07, 0xB2, 0x00, 0x69, 0x57, 0x28, 0x39, 0xF5, 0x0F, 0x66, 0x45, 0x39, 0x73, 0x6E,
0x3F, 0xA4, 0x04, 0x6C, 0xDF, 0x0F, 0xD2, 0x66, 0x4B, 0x57, 0x24, 0x81, 0x93, 0x3C, 0x8C, 0xCC,
0x6E, 0x97, 0x92, 0xB2, 0x6F, 0x82, 0x4D, 0x33, 0x8C, 0xE3, 0x9F, 0x6F, 0x03, 0x72, 0xF7, 0x7D,
0x0C, 0x1A, 0xC2, 0x03, 0x76, 0x1F, 0xFF, 0xC0, 0xF8, 0x14, 0xEC, 0x40, 0x83, 0xB6, 0x81, 0xAE,
0x6D, 0x51, 0x77, 0xBA, 0xA4, 0xEE, 0x29, 0xD4, 0x36, 0x7C, 0x4E, 0x61, 0x90, 0x0D, 0x8F, 0x2D,
0x7B, 0xC0, 0x2E, 0x86, 0x53, 0x5D, 0xA4, 0x79, 0x7A, 0xB7, 0xE0, 0x83, 0x43, 0xB7, 0x8C, 0x9D,
0xE0, 0x63, 0x0D, 0x0A, 0x3E, 0xF8, 0xF9, 0x01, 0x3E, 0x98, 0x8F, 0x23, 0x1F, 0x8B, 0x0B, 0x64,
0xC3, 0x23, 0x4F, 0x6E, 0xA1, 0x75, 0x2C, 0xBE, 0xDE, 0x09, 0x8E, 0x63, 0xD8, 0x6C, 0xC1, 0x84,
0xE5, 0xC9, 0xFA, 0xEC, 0x02, 0x14, 0x08, 0x3C, 0x40, 0x8F, 0xA0, 0x8A, 0x99, 0x70, 0x11, 0xA1,
0x53, 0xAE, 0x48, 0x34, 0x17, 0x9E, 0xCC, 0xE5, 0xEA, 0x13, 0x5F, 0x2B, 0xC3, 0xF3, 0x25, 0x98,
0xF9, 0x26, 0x30, 0x53, 0x73, 0xE9, 0x2A, 0xA7, 0xC4, 0xEB, 0x3E, 0x69, 0xBC, 0x2A, 0x75, 0x17,
0x6D, 0xA7, 0x2B, 0xED, 0x08, 0x1F, 0x92, 0x82, 0x7F, 0x29, 0xDD, 0xF2, 0xEB, 0xD2, 0xCE, 0x8B,
0x83, 0x00, 0x1A, 0x21, 0x87, 0x64, 0x66, 0x84, 0x2B, 0xD5, 0x1C, 0x6E, 0xC0, 0xCA, 0x80, 0xF7,
0x0A, 0xDB, 0x67, 0x3F, 0x83, 0x1F, 0xE4, 0x5F, 0xAE, 0x41, 0x4B, 0xF2, 0x4B, 0xC9, 0x80, 0x2A,
0x6D, 0x62, 0x45, 0xAC, 0x55, 0x48, 0x2A, 0x26, 0x43, 0x07, 0xC8, 0x71, 0xE2, 0x33, 0xDA, 0x2A,
0x1B, 0xC7, 0xE3, 0x82, 0x5C, 0xCF, 0x11, 0xDC, 0xE1, 0x91, 0x96, 0xFB, 0x63, 0x06, 0xE9, 0xE6,
0x26, 0x2B, 0x34, 0x7A, 0xF0, 0x7E, 0x8E, 0x37, 0x16, 0xC8, 0x27, 0x21, 0xFE, 0x23, 0xC3, 0xFD,
0x07, 0x80, 0xAF, 0xE4, 0xBD, 0x47, 0x71, 0xF0, 0xEE, 0x28, 0x0A, 0x2A, 0xF6, 0xF2, 0x34, 0xE4,
0x03, 0xDE, 0x07, 0x18, 0xC0, 0x71, 0xEE, 0x10, 0xFD, 0x70, 0x3D, 0xEA, 0x8C, 0x8F, 0x81, 0xBE,
0xC5, 0x5D, 0x0E, 0x7E, 0xF8, 0xB1, 0x1E, 0xFE, 0x72, 0xCE, 0x70, 0x84, 0x8C, 0xD8, 0xF0, 0x75,
0xB6, 0xD4, 0x8F, 0xB3, 0x9F, 0x7D, 0x20, 0xB0, 0x79, 0x70, 0x06, 0x8E, 0x96, 0x79, 0xEC, 0xBD,
0x73, 0x03, 0xDA, 0x81, 0xFF, 0xC0, 0xA9, 0x80, 0x89, 0xC2, 0xCA, 0x83, 0x1C, 0x89, 0x72, 0xCF,
0xE1, 0x3D, 0x87, 0xC6, 0x5F, 0xDD, 0x74, 0xEE, 0x7E, 0x90, 0x85, 0x26, 0x70, 0xFE, 0xCD, 0xFD,
0x88, 0xA5, 0x28, 0x65, 0x1B, 0x28, 0x65, 0x2D, 0x75, 0x5D, 0x3C, 0x2D, 0x85, 0x9E, 0x55, 0x6F,
0xF6, 0x06, 0x44, 0xA7, 0xC1, 0x02, 0x0E, 0xEE, 0x98, 0xAD, 0x40, 0xF0, 0xEF, 0xD5, 0x18, 0x5A,
0x91, 0x2E, 0xEA, 0x7C, 0x0D, 0x62, 0x25, 0xA5, 0x6E, 0x44, 0x0F, 0x9D, 0x9F, 0xC0, 0x21, 0x69,
0x26, 0xB3, 0x8F, 0x70, 0xF0, 0x9D, 0x88, 0xE5, 0x55, 0x42, 0xA1, 0x7A, 0x49, 0x20, 0xAD, 0x81,
0x93, 0xE7, 0x8B, 0xFC, 0x8C, 0xE7, 0xE6, 0xCF, 0xBC, 0x51, 0xA8, 0xBC, 0xB8, 0xF2, 0x2F, 0xD4,
0xB6, 0x4A, 0xCF, 0x17, 0xE8, 0x3D, 0xF4, 0xDD, 0x01, 0x50, 0x3C, 0x42, 0xA8, 0x44, 0x90, 0xA8,
0x82, 0xC9, 0xB6, 0x87, 0x85, 0xC3, 0xE0, 0x79, 0x44, 0x97, 0xC2, 0xE5, 0xCB, 0x4E, 0x26, 0x6D,
0xFF, 0x98, 0xDB, 0x14, 0x71, 0x71, 0x33, 0x5F, 0x07, 0xF4, 0x03, 0xF9, 0xBF, 0x0D, 0x98, 0x1C,
0x46, 0x33, 0xE1, 0x15, 0xBC, 0xBD, 0x16, 0x3C, 0x20, 0xD1, 0x0D, 0x12, 0x3A, 0x5B, 0x6C, 0x22,
0x56, 0x6C, 0x01, 0x5F, 0xB8, 0x9D, 0xBB, 0x10, 0x09, 0x77, 0xB7, 0x70, 0x46, 0x06, 0x52, 0xC5,
0xF9, 0x75, 0x83, 0x4E, 0xBD, 0x4D, 0x8A, 0x45, 0x14, 0x84, 0xEC, 0x0E, 0x1C, 0x3B, 0x03, 0xDA,
0xD4, 0xBB, 0x7A, 0xCB, 0x88, 0xA6, 0xF0, 0x30, 0x82, 0xA9, 0xE5, 0x80, 0xB6, 0x9A, 0xE4, 0x02,
0xE9, 0x7C, 0x21, 0x6F, 0x83, 0xC7, 0xD2, 0x86, 0x96, 0xCB, 0xF9, 0x49, 0x57, 0xD8, 0x4C, 0x1B,
0xDD, 0x86, 0xA3, 0x1D, 0x8F, 0xE8, 0x9F, 0xF4, 0x59, 0x97, 0x79, 0x81, 0xEE, 0x04, 0x57, 0xB4,
0x13, 0x92, 0x68, 0x49, 0x57, 0x6D, 0xCB, 0x69, 0x45, 0x17, 0x53, 0xFA, 0x4B, 0xF0, 0xEB, 0x05,
0xCE, 0x7C, 0x64, 0xC6, 0x23, 0x13, 0xEA, 0x17, 0xD1, 0x85, 0xFE, 0xD0, 0xA4, 0xFA, 0x05, 0xE7,
0x9E, 0xFB, 0xBB, 0x90, 0xC2, 0x08, 0x2E, 0x2E, 0x9C, 0x94, 0xD0, 0x4D, 0x1A, 0x69, 0x6C, 0x5A,
0xD5, 0x39, 0xF5, 0x7D, 0xAE, 0x48, 0xB0, 0xAF, 0x6C, 0xF5, 0x39, 0x00, 0xC3, 0x51, 0x94, 0x59,
0x64, 0x13, 0x0D, 0xBB, 0xDF, 0x90, 0x71, 0x9C, 0x7D, 0x96, 0xD9, 0x44, 0x03, 0xB3, 0x09, 0xCB,
0x1E, 0xE3, 0xDF, 0x06, 0x2C, 0x5A, 0x9D, 0x4A, 0x24, 0x05, 0x8D, 0x81, 0xDD, 0x80, 0x60, 0xDE,
0xB0, 0xE0, 0x01, 0xE1, 0xBF, 0x31, 0x6C, 0x60, 0xF8, 0xC7, 0x87, 0xE4, 0x3D, 0x28, 0x78, 0x8F,
0x1A, 0xC2, 0x14, 0x1B, 0x18, 0xD6, 0xE1, 0xE4, 0xEA, 0x3B, 0x0D, 0xAD, 0x3B, 0x13, 0x3A, 0xAB,
0x72, 0xAC, 0xE7, 0x61, 0x97, 0x79, 0xB0, 0xCC, 0xA0, 0x8E, 0x4B, 0xCF, 0xE4, 0x5C, 0xC6, 0x47,
0xE4, 0x1A, 0x8E, 0x0A, 0x9E, 0x80, 0xAB, 0x67, 0x49, 0x66, 0x97, 0x79, 0x5A, 0x26, 0x67, 0x8A,
0x4F, 0xC1, 0x75, 0xAC, 0x72, 0xED, 0x3F, 0x86, 0xA9, 0x7D, 0x59, 0xCB, 0xA4, 0x77, 0xE6, 0x72,
0xFB, 0x9C, 0x4B, 0xBF, 0xC7, 0x45, 0x1B, 0x71, 0xC9, 0x46, 0x39, 0x4F, 0x85, 0xE5, 0xF0, 0x5C,
0x9E, 0xC3, 0x3F, 0x81, 0xE7, 0xF8, 0x8F, 0xE0, 0xC9, 0xF3, 0x3F, 0xC5, 0xC0, 0xF1, 0x4C, 0x2F,
0xED, 0x9B, 0x1B, 0xE9, 0xF9, 0xF6, 0x6D, 0xF7, 0xE1, 0x4F, 0x03, 0x82, 0x33, 0xF8, 0xA3, 0xE6,
0x4F, 0x1B, 0x3F, 0x8D, 0x8C, 0x9E, 0xF6, 0xD6, 0x36, 0xC6, 0xDA, 0xDB, 0x91, 0x61, 0xF5, 0xD8,
0xBB, 0xA9, 0xBD, 0xB5, 0xC4, 0x63, 0x6C, 0x58, 0x16, 0x7F, 0x0C, 0x78, 0xE3, 0x10, 0x1E, 0x26,
0x7B, 0x5C, 0x1A, 0xD6, 0x88, 0xBD, 0x5F, 0xB2, 0x26, 0x1B, 0x86, 0xDB, 0xE2, 0x61, 0x1B, 0xD6,
0x98, 0x3D, 0xC6, 0xAC, 0x6D, 0x88, 0x5C, 0x87, 0xDA, 0x57, 0x5C, 0x60, 0x1A, 0x7F, 0x81, 0x15,
0xB2, 0xB3, 0x6A, 0x83, 0xA7, 0xBB, 0x0D, 0xB6, 0xD2, 0xDA, 0x85, 0xF2, 0xB4, 0xE6, 0x33, 0x1E,
0x10, 0x48, 0x6B, 0xA7, 0x20, 0xC9, 0xC5, 0x94, 0x30, 0xF4, 0x51, 0x71, 0x44, 0x67, 0x29, 0x9E,
0xA1, 0x03, 0x8E, 0xE8, 0xAD, 0x82, 0x07, 0x9C, 0x65, 0xB1, 0xFC, 0x7C, 0x0D, 0xF9, 0x69, 0xB4,
0xCC, 0x9A, 0xC4, 0xA0, 0x52, 0x69, 0x80, 0x0B, 0xA4, 0x43, 0xE3, 0xB7, 0xF1, 0x1D, 0x49, 0x7F,
0x80, 0xDC, 0xA0, 0xD9, 0x02, 0x98, 0xA5, 0x95, 0x16, 0x72, 0x45, 0xBF, 0x6D, 0x5B, 0x13, 0x32,
0xA3, 0xDF, 0x5A, 0x13, 0xB3, 0x60, 0x8B, 0xB5, 0x3F, 0x97, 0x7A, 0x2B, 0x96, 0x69, 0xB1, 0x0C,
0x11, 0x45, 0x44, 0xB4, 0x81, 0x5C, 0x1E, 0x00, 0x73, 0xD1, 0x84, 0xA7, 0x7A, 0x12, 0xBC, 0x66,
0x83, 0x26, 0x9A, 0x7E, 0x41, 0x3A, 0x9C, 0xC0, 0xA0, 0x17, 0xE5, 0x21, 0xBF, 0xA9, 0x5F, 0x6E,
0x62, 0xEA, 0x86, 0x1A, 0x2F, 0x96, 0x33, 0x22, 0x8A, 0x0D, 0xA7, 0x69, 0x20, 0xC0, 0xFB, 0x2A,
0x09, 0x44, 0x6C, 0xFF, 0x34, 0xC5, 0x3B, 0xCF, 0xDB, 0x24, 0xBC, 0x4A, 0xAB, 0xE9, 0x6C, 0xE8,
0xD5, 0x9A, 0x40, 0x1C, 0xD4, 0xD6, 0x41, 0x04, 0x06, 0xD3, 0x60, 0x99, 0x18, 0x47, 0x8C, 0x15,
0x58, 0xD4, 0xB4, 0x71, 0x09, 0x9F, 0x78, 0x6C, 0x6B, 0xE0, 0x0C, 0x71, 0x4E, 0x0F, 0xB8, 0x0E,
0x1B, 0xC8, 0x88, 0xC5, 0x21, 0xA2, 0xDA, 0xFF, 0x5C, 0x37, 0xFC, 0xD8, 0xDB, 0xAC, 0x61, 0x0F,
0x3B, 0x4B, 0x42, 0x5F, 0x85, 0x04, 0x3F, 0x7E, 0xBF, 0x7D, 0x03, 0x7B, 0x27, 0x92, 0xEC, 0x56,
0x27, 0x88, 0x22, 0x92, 0xFE, 0x78, 0xF3, 0xD3, 0xDB, 0x29, 0x35, 0x50, 0x93, 0x06, 0x6C, 0xF3,
0x33, 0x35, 0xF8, 0x71, 0x25, 0x47, 0xA5, 0x78, 0x08, 0xB1, 0x87, 0xBE, 0xC1, 0x52, 0xCB, 0xBB,
0x05, 0x46, 0x45, 0xA3, 0xD4, 0xC7, 0xC3, 0x96, 0xDD, 0x72, 0xD8, 0xEA, 0x68, 0x2A, 0xBD, 0x4C,
0xBD, 0x57, 0x3E, 0x11, 0xB0, 0x4A, 0x71, 0x17, 0x86, 0x90, 0xA6, 0x69, 0x44, 0x17, 0x56, 0xEB,
0xE1, 0x38, 0x86, 0x61, 0x11, 0x82, 0x99, 0xE2, 0xAD, 0x45, 0x4C, 0x03, 0xB3, 0x0C, 0x31, 0x25,
0x01, 0x6C, 0x68, 0xCC, 0xE0, 0x2C, 0x80, 0x09, 0xA9, 0xCC, 0x37, 0xF5, 0x3D, 0x61, 0x77, 0x06,
0x59, 0x07, 0xE4, 0xA3, 0x4D, 0x69, 0x72, 0x25, 0xD3, 0xAD, 0x5A, 0x75, 0x07, 0x33, 0x69, 0x83,
0xB2, 0x47, 0x6B, 0xDF, 0x62, 0xC9, 0x00, 0xEA, 0x29, 0x98, 0x9A, 0x10, 0xBC, 0x25, 0x3F, 0xAE,
0x0B, 0x07, 0xE2, 0x68, 0x4B, 0x6F, 0x5B, 0xA0, 0x57, 0x4E, 0xDF, 0x14, 0xFD, 0x10, 0x75, 0x3B,
0x78, 0x3A, 0x6D, 0xBD, 0x78, 0xD1, 0x64, 0xCA, 0xBA, 0xF9, 0x30, 0x13, 0x46, 0xC1, 0xB2, 0x6E,
0x80, 0x18, 0x15, 0x57, 0x14, 0xB8, 0xA9, 0x81, 0x18, 0x6D, 0xF6, 0x89, 0x16, 0x28, 0x63, 0x19,
0x36, 0xA0, 0x84, 0x61, 0x5B, 0x88, 0x35, 0x36, 0x7E, 0x1E, 0xF2, 0xC7, 0x88, 0xB5, 0x59, 0x88,
0x0F, 0x6F, 0x2D, 0x5B, 0xBC, 0x5B, 0x1A, 0x0E, 0xB3, 0xCE, 0x40, 0x0C, 0xBC, 0x52, 0xD0, 0xEE,
0x2D, 0x1E, 0x91, 0xB7, 0xF8, 0x6C, 0x68, 0xF7, 0x36, 0x3C, 0x00, 0x59, 0xB7, 0x36, 0x8B, 0x80,
0x15, 0x0E, 0xFC, 0x6B, 0x5B, 0x08, 0x6F, 0x35, 0xBA, 0x72, 0x89, 0x39, 0xAB, 0x81, 0xE0, 0x64,
0x0A, 0x56, 0x3D, 0xCE, 0xCA, 0x32, 0xCF, 0xE0, 0x05, 0x6B, 0x3E, 0xE0, 0xD3, 0xAF, 0xF0, 0xE9,
0x3F, 0x91, 0xCF, 0xB8, 0xC2, 0x67, 0x7C, 0x06, 0x1F, 0x59, 0x3B, 0x60, 0xF9, 0x13, 0x2C, 0xB3,
0x71, 0x75, 0xF3, 0x52, 0xE4, 0x6A, 0x9F, 0x44, 0xB2, 0xF6, 0xA9, 0x91, 0x57, 0x48, 0x65, 0x19,
0x3D, 0xB9, 0x77, 0xC0, 0x7C, 0x5D, 0x51, 0x47, 0x6C, 0x80, 0x1F, 0x33, 0xD0, 0x55, 0xCC, 0x04,
0xED, 0xEC, 0xA2, 0x01, 0x49, 0xB9, 0x9B, 0x82, 0x2B, 0x4F, 0x3F, 0x83, 0x00, 0xD1, 0x97, 0x52,
0x56, 0x5D, 0x94, 0x23, 0x67, 0x0D, 0x9C, 0xB9, 0x42, 0xCC, 0x75, 0x2E, 0xF2, 0x61, 0xAC, 0x29,
0xDE, 0xBC, 0x9C, 0x81, 0x6C, 0x5C, 0xCA, 0x8A, 0x3D, 0x8A, 0xB1, 0x7C, 0x84, 0x34, 0x3B, 0xF3,
0x79, 0x43, 0x9D, 0xEF, 0x93, 0x28, 0x1C, 0x7D, 0xD2, 0x15, 0x57, 0x7E, 0x09, 0xF1, 0x83, 0x92,
0x26, 0x43, 0xAA, 0xB2, 0xE8, 0x7A, 0xA3, 0x85, 0x99, 0x26, 0x72, 0x56, 0xD3, 0xC5, 0x92, 0x54,
0x38, 0x1F, 0xF7, 0x49, 0x7C, 0x43, 0x5F, 0x28, 0xFC, 0x2A, 0x04, 0xBF, 0x0A, 0xAB, 0x7E, 0x15,
0x0A, 0xBF, 0x9A, 0x56, 0xFD, 0x2A, 0xFC, 0x43, 0xFD, 0x4A, 0xF1, 0xAA, 0x4B, 0x1E, 0x9E, 0x2F,
0x31, 0xD0, 0x42, 0x90, 0x86, 0x78, 0x2C, 0xDE, 0x06, 0x18, 0x72, 0xFB, 0xE8, 0x45, 0x7D, 0xF4,
0xBB, 0x01, 0x73, 0x3E, 0x9B, 0x0D, 0xC5, 0x07, 0x06, 0x6A, 0x74, 0xC5, 0x1E, 0xA3, 0x1F, 0xB0,
0x77, 0x9B, 0x7B, 0x22, 0xF4, 0x9F, 0x17, 0xA7, 0x0B, 0xA3, 0xD2, 0x71, 0x5B, 0xCA, 0x27, 0x00,
0x2D, 0xDF, 0xFE, 0x3C, 0xAB, 0x39, 0xBC, 0x99, 0x53, 0x51, 0x57, 0x09, 0xF5, 0xCA, 0x76, 0x85,
0xC5, 0x76, 0x39, 0x72, 0xBF, 0x2A, 0x7D, 0x25, 0xE3, 0x90, 0xF2, 0x3C, 0xD9, 0x56, 0x8E, 0xCF,
0xFF, 0x24, 0x73, 0x39, 0x1A, 0xEF, 0x8A, 0x9A, 0x54, 0x39, 0xE4, 0x1D, 0x25, 0x60, 0xA5, 0x3A,
0x75, 0xAC, 0x3C, 0x2E, 0x16, 0x29, 0x89, 0xB0, 0x76, 0xCC, 0x94, 0xE2, 0x08, 0xAF, 0x12, 0x9A,
0xFA, 0x0F, 0xFC, 0x83, 0xE6, 0x63, 0x17, 0x8E, 0x89, 0x17, 0xB8, 0x99, 0x3C, 0x3D, 0x00, 0x73,
0x2C, 0xE5, 0x4F, 0x6C, 0x10, 0x81, 0x0C, 0xF6, 0x80, 0xA7, 0x4C, 0xC0, 0x4E, 0xB1, 0x85, 0x31,
0xB0, 0x81, 0x71, 0xBA, 0x3D, 0xC1, 0x1B, 0xC6, 0x94, 0xD9, 0x2B, 0x05, 0x60, 0x71, 0x52, 0x4B,
0x52, 0x88, 0x6C, 0x70, 0xB6, 0x7D, 0xCF, 0xCB, 0x35, 0xEC, 0xA2, 0xA1, 0xE0, 0xCD, 0x0A, 0x46,
0x90, 0x13, 0x80, 0x6A, 0xA3, 0x4D, 0x18, 0x3E, 0x9B, 0x92, 0xCA, 0x3C, 0x9E, 0x64, 0x08, 0xF3,
0x74, 0xC0, 0x09, 0xD7, 0xCD, 0x96, 0x32, 0x9D, 0x3A, 0x94, 0x45, 0x53, 0x9E, 0x4A, 0x44, 0xE4,
0x4E, 0xFB, 0x9F, 0x9F, 0xDE, 0xFE, 0x48, 0x69, 0x22, 0x4E, 0xF0, 0x70, 0xA0, 0xD6, 0xBB, 0xCC,
0x04, 0xBE, 0xE5, 0x3F, 0x85, 0x98, 0xC2, 0x9A, 0x20, 0x6E, 0x42, 0x26, 0x85, 0xAD, 0xBC, 0x6C,
0x75, 0x41, 0x22, 0x2F, 0xF6, 0xC9, 0xC7, 0x0F, 0x6F, 0x9A, 0xB4, 0x65, 0xB0, 0x4E, 0x96, 0x34,
0xA8, 0x1D, 0x6A, 0xE2, 0x72, 0x7C, 0x73, 0x45, 0xD1, 0xB6, 0xD5, 0x61, 0xAE, 0xD2, 0x29, 0x2A,
0x59, 0xA2, 0xAA, 0x15, 0xC2, 0x9A, 0xA3, 0x4E, 0x1C, 0xC1, 0xE2, 0xFC, 0x2D, 0xA6, 0x4A, 0xC4,
0x5B, 0xE1, 0xAF, 0x0B, 0xA7, 0x79, 0x6E, 0xD0, 0xDA, 0x41, 0xC6, 0xD9, 0x9F, 0x4E, 0xA3, 0x0E,
0x1B, 0x83, 0xC9, 0x26, 0x69, 0x41, 0x93, 0x6D, 0x9A, 0xD8, 0xC8, 0xD3, 0x2B, 0xA9, 0xE3, 0xFF,
0xBA, 0x7E, 0xF7, 0x33, 0x20, 0x7A, 0x0A, 0x09, 0x2E, 0x8E, 0xCF, 0x92, 0x38, 0xCA, 0xC8, 0x0D,
0xB9, 0xA7, 0x27, 0x0C, 0xF6, 0x84, 0x88, 0xA2, 0xDA, 0x66, 0xD4, 0xA6, 0xC4, 0x7B, 0x12, 0xC2,
0x36, 0x56, 0xCA, 0x23, 0x7B, 0x5C, 0x4D, 0x42, 0xA2, 0xA6, 0xFE, 0x9F, 0xAF, 0x6E, 0xE0, 0x5C,
0x6F, 0x3C, 0x33, 0x5B, 0xD0, 0x94, 0xC1, 0xF6, 0x34, 0x2B, 0xDB, 0xC5, 0xCB, 0x8C, 0xBB, 0xBC,
0x8D, 0xD9, 0x37, 0x2C, 0x8C, 0x08, 0xD0, 0x85, 0xED, 0x4C, 0x36, 0xAC, 0x04, 0x20, 0xB3, 0x6F,
0xC2, 0x7F, 0xDF, 0xE0, 0x77, 0x45, 0xCA, 0xFC, 0x1F, 0x90, 0xBD, 0x1E, 0x5F, 0x17, 0xDE, 0xB6,
0xB4, 0x3A, 0x3C, 0xA3, 0x3D, 0xE1, 0x7E, 0xE5, 0x7B, 0x20, 0x49, 0x20, 0x4A, 0xA1, 0x80, 0x6A,
0x5A, 0xA7, 0xD3, 0xD1, 0x2F, 0xF0, 0xF0, 0xF0, 0x1A, 0xAF, 0xFF, 0x9B, 0x66, 0x0B, 0xF3, 0xDD,
0xFD, 0x9E, 0x8B, 0x74, 0x12, 0x06, 0x64, 0xF1, 0xB6, 0xC5, 0x31, 0x07, 0x8F, 0x0E, 0xE6, 0xB3,
0xA9, 0xAC, 0xB7, 0xB4, 0x76, 0x4F, 0x96, 0x09, 0x45, 0x3A, 0x01, 0x28, 0x6C, 0xE1, 0xC7, 0x0D,
0xCE, 0x29, 0x7C, 0xE3, 0x75, 0x9C, 0xAE, 0x5F, 0xBA, 0xD4, 0x75, 0xA2, 0x8E, 0x9B, 0x24, 0xB8,
0x49, 0x1C, 0x8E, 0xD4, 0x3C, 0xBB, 0x9A, 0x72, 0x52, 0x35, 0xD9, 0xDC, 0xF1, 0x90, 0x89, 0x65,
0x1D, 0xC3, 0x57, 0x33, 0xF7, 0x8B, 0x50, 0xE0, 0xEB, 0xB5, 0x5E, 0x30, 0xF7, 0x8D, 0x90, 0x87,
0x4B, 0xA3, 0x98, 0xAF, 0x28, 0x69, 0x1B, 0xA1, 0x71, 0xC8, 0xA0, 0xC5, 0x14, 0xED, 0xD6, 0x78,
0xB2, 0xE3, 0x0A, 0x4B, 0x7B, 0xFF, 0xEE, 0xFA, 0x06, 0x4F, 0x13, 0x8C, 0x8F, 0xCE, 0x2C, 0xCE,
0xED, 0x70, 0x15, 0x76, 0x20, 0x32, 0xBD, 0xBA, 0x05, 0x8E, 0x6F, 0x01, 0x90, 0x09, 0x00, 0x2C,
0x6A, 0x87, 0x17, 0x9D, 0x01, 0x46, 0x8C, 0x67, 0x16, 0x0E, 0x8D, 0x23, 0x1C, 0x5A, 0xF1, 0x38,
0xE6, 0x5E, 0x53, 0x37, 0xF7, 0xAF, 0xA7, 0xED, 0xD5, 0x13, 0x76, 0x29, 0xF7, 0xB9, 0xF3, 0x2C,
0x4B, 0x4C, 0xA7, 0x3B, 0x35, 0x3E, 0xAA, 0xA0, 0x81, 0x5B, 0x46, 0x03, 0xE1, 0xBC, 0xEC, 0x5F,
0x24, 0x34, 0xF5, 0xEF, 0xC0, 0xF9, 0xD8, 0x6F, 0xE1, 0xF1, 0x4C, 0x07, 0x1B, 0xE0, 0x3F, 0x83,
0x63, 0x36, 0x28, 0x86, 0x79, 0x6D, 0xD4, 0xDA, 0x17, 0x7E, 0xAB, 0x5E, 0x10, 0xFC, 0xA9, 0x9E,
0xBB, 0xB8, 0x3B, 0xC7, 0x77, 0xF1, 0x92, 0x40, 0x8D, 0x9C, 0x0F, 0x7B, 0x2D, 0x48, 0x79, 0x10,
0xEB, 0x2A, 0x17, 0x37, 0xDA, 0xB7, 0x7A, 0x4B, 0xCA, 0x7D, 0x7C, 0x13, 0xEE, 0x7E, 0xA7, 0x73,
0x17, 0xD7, 0x2F, 0x4F, 0x33, 0x02, 0x65, 0xFE, 0x27, 0x90, 0x73, 0xC5, 0x9D, 0x88, 0x49, 0xE7,
0xAB, 0xFC, 0xC4, 0x58, 0xF1, 0x73, 0x01, 0x39, 0x91, 0xF8, 0x51, 0xD5, 0x54, 0xC7, 0x5F, 0x55,
0x9D, 0xF6, 0x0C, 0xB6, 0xFD, 0x27, 0x10, 0x4C, 0x22, 0x52, 0x19, 0xC5, 0x8C, 0x07, 0x01, 0x4A,
0xEF, 0xEA, 0x8F, 0x04, 0x26, 0x8E, 0x4B, 0x05, 0xDD, 0x23, 0xF0, 0x88, 0xFF, 0xFE, 0x03, 0x96,
0xF2, 0xD7, 0x40, 0x92, 0x6A, 0x61, 0xE7, 0x82, 0xD2, 0xC1, 0xEE, 0x9E, 0xB8, 0x67, 0x3B, 0xC1,
0x46, 0xDE, 0xB8, 0x3D, 0xCD, 0xC4, 0xFE, 0x10, 0x07, 0x39, 0xC6, 0x44, 0x5E, 0x38, 0x27, 0xF7,
0x67, 0x7A, 0x97, 0x04, 0xD8, 0x3F, 0xCD, 0x17, 0x0F, 0xC9, 0x15, 0x19, 0x9D, 0x83, 0xBC, 0xAE,
0x82, 0xE4, 0x88, 0x3B, 0x3A, 0x16, 0x7C, 0x64, 0xED, 0xF1, 0xC5, 0x0B, 0xBD, 0x5F, 0xFE, 0xAA,
0xF6, 0xFE, 0xF6, 0x9B, 0xC0, 0x7C, 0x81, 0x75, 0x0B, 0x17, 0x6C, 0xDC, 0xD7, 0x5B, 0x86, 0x6E,
0xC3, 0xE1, 0x56, 0x8E, 0x6A, 0x95, 0x07, 0x79, 0x6E, 0xE4, 0x81, 0x84, 0x18, 0x16, 0x1C, 0x16,
0x37, 0x70, 0xCE, 0x9E, 0x3A, 0x9E, 0xC3, 0xA5, 0x11, 0x4D, 0x4D, 0xF0, 0xC1, 0x87, 0x1C, 0xDB,
0x09, 0x3A, 0x58, 0x7B, 0xEC, 0x9B, 0x06, 0x9D, 0x66, 0x84, 0xBE, 0x41, 0x53, 0x01, 0x2D, 0x37,
0x15, 0x6B, 0x8F, 0x2E, 0xA6, 0xD6, 0xC3, 0x00, 0xC1, 0xB7, 0x26, 0x3A, 0xC7, 0x0E, 0x0B, 0x93,
0xEE, 0x5B, 0xED, 0xC8, 0x88, 0x66, 0x7D, 0x13, 0x8E, 0xEC, 0x1E, 0x58, 0x74, 0x9A, 0xCF, 0x0F,
0xA9, 0x7E, 0x18, 0xF3, 0xBB, 0x59, 0xD0, 0x31, 0x9A, 0x0F, 0x1E, 0x31, 0x0C, 0x8B, 0xF4, 0xCA,
0xE1, 0xB2, 0xA4, 0x3A, 0x0C, 0x95, 0x8F, 0x8A, 0xA5, 0x45, 0x30, 0x15, 0xB8, 0xF1, 0x16, 0x6F,
0x3A, 0x9B, 0x27, 0xDC, 0xF9, 0x9C, 0x04, 0xFD, 0x38, 0xAD, 0xBC, 0xC4, 0x3E, 0x40, 0x61, 0xF6,
0xDB, 0x73, 0xA5, 0x24, 0x5F, 0xC9, 0xE4, 0x4F, 0xC9, 0x73, 0x94, 0x27, 0x43, 0x76, 0x61, 0xB3,
0xA7, 0xE9, 0x95, 0x3B, 0x67, 0xB1, 0x91, 0xE2, 0x50, 0x67, 0x9C, 0x88, 0xBA, 0x75, 0x97, 0xC2,
0x15, 0x6A, 0xBC, 0x35, 0x65, 0xC3, 0xBE, 0xFD, 0x78, 0xFD, 0xEA, 0x83, 0x7A, 0x62, 0xC3, 0xAC,
0x04, 0xC4, 0x8B, 0x28, 0x64, 0x2B, 0x17, 0xFA, 0x8B, 0xF7, 0xDF, 0x5D, 0x5F, 0xFF, 0xF3, 0xDD,
0x87, 0x97, 0xF5, 0x43, 0x28, 0x0E, 0xB9, 0xFE, 0xF8, 0xFD, 0x4F, 0x6F, 0x6E, 0xA6, 0x5B, 0xCC,
0x2A, 0x83, 0x3A, 0xC4, 0x0F, 0x1E, 0x38, 0xB9, 0xC1, 0xB1, 0x2D, 0x50, 0x8E, 0x6D, 0x2F, 0x5E,
0x00, 0x84, 0x3F, 0x83, 0x26, 0xE9, 0x9A, 0x65, 0x0B, 0xD8, 0x1B, 0x81, 0x7A, 0x76, 0x8A, 0x58,
0xD8, 0x08, 0xE4, 0xD9, 0x09, 0x95, 0xAA, 0x16, 0xB0, 0x21, 0x24, 0x39, 0x77, 0x41, 0xE4, 0xC7,
0x77, 0x35, 0xD1, 0xE2, 0xF8, 0xED, 0x89, 0x73, 0xD5, 0x15, 0xD7, 0xD3, 0x57, 0x5D, 0xF1, 0x83,
0x19, 0xF6, 0xFF, 0xCC, 0xF9, 0x7F, 0xE5, 0xCC, 0x32, 0xCA, 0x3A, 0x47, 0x00, 0x00
};
size_t a_SIZE = 4862;
const char * a_NAME = "ool.html.gz";

30
embedded/package.json Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "embedded4ESP3D",
"description": "Embedded files for ESP3D",
"devDependencies": {
"del": "^2.2.2",
"deprecated": "0.0.1",
"fs": "0.0.1-security",
"gulp": "github:gulpjs/gulp#4.0",
"gulp-bytediff": "^1.0.0",
"gulp-cdnizer": "^1.1.7",
"gulp-clean-css": "^2.4.0",
"gulp-concat": "^2.6.1",
"gulp-gzip": "^1.4.0",
"gulp-htmlmin": "^3.0.0",
"gulp-if": "^2.0.2",
"gulp-jshint": "^2.0.4",
"gulp-ng-annotate": "^2.0.0",
"gulp-remove-code": "^1.0.2",
"gulp-replace": "^0.5.4",
"gulp-smoosher": "0.0.9",
"gulp-uglify": "^2.1.2",
"gulp-util": "^3.0.1",
"gulp-zip": "^3.2.0",
"jshint": "^2.9.5",
"merge-stream": "^1.0.1"
},
"repository": "https://github.com/luc-github/ESP3D",
"author": "Luc LEBOSSE",
"license": "(ISC OR GPL-3.0)"
}

BIN
embedded/tool.html.gz Normal file

Binary file not shown.

139
embedded/www/css/style.css Normal file
View File

@@ -0,0 +1,139 @@
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%; font-size:10px;}
body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333333;background-color:#ffffff;}
.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;}
table{border:0px;border-spacing:0;max-width:100%;}
.table-bordered{ width:100%; border:1px solid #dddddd;margin-bottom:20px;}
td{white-space:nowrap; padding:2mm;}
th{text-align:left;}
.table>thead>tr>th,.table>tbody>tr>th,.table>thead>tr>td,.table>tbody>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #dddddd;}
.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td{border:1px solid #dddddd;}
.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px;}
.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9;}
@media (min-width:768px){.container{width:750px;}}
@media (min-width:992px){.container{width:970px;}}
@media (min-width:1200px){.container{width:1170px;}}
.nav{ width:100%; color:#cccccc;padding-left:10;padding-right:10;list-style:none;background-color:#333333;border-radius:6px ;margin-bottom:20px;}
a{position:relative;display:block;padding:10px 15px;text-decoration:none;color:#cccccc;}
.active{color:#ffffff;background-color:#000000;}
.active a,a:hover,a:focus{color:#FFFFFF;}
.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05);}
.panel-body{padding:15px;}
.panel-heading{padding:10px 15px;color:#333333;background-color:#f5f5f5;border-color:#dddddd;border-top-right-radius:3px;border-top-left-radius:3px;border-bottom:1px solid #dddddd;}
label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold;}
.text-info{color:#31708f;}
.form-control{display:block;width:auto;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff
;background-image:none;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);
* -webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;
* transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);
* box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);}
.form-group{margin-bottom:15px;}
.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
.btn-primary{color:#ffffff;background-color:#337ab7;border-color:#2e6da4;}
.btn-primary:focus,.btn-primary:active,.btn-primary:hover,.btn-primary.focus,.btn-primary.active,.btn-primary.hover{color:#ffffff;background-color:#286090;border-color:#122b40;}
caption{padding-top:8px;padding-bottom:8px;color:#777777;text-align:left;}
.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px;}
.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d;}
.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442;}
.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);}
.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;}
.has-error .control-label{color:#a94442;}
.has-success .form-control {border-color: #3c763d;-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);}
.has-success .form-control:focus {border-color: #2b542c;-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;}
.has-success .control-label{color: #3c763d;}
.btn-danger{color:#ffffff;background-color:#d9534f;border-color:#d43f3a;}
.btn-danger:focus,.btn-danger:active,.btn-danger:hover,.btn-danger.focus,.btn-danger.active,.btn-danger.hover{color: #ffffff;background-color:#c9302c;border-color:#761c19;}
.btnimg {cursor:hand; border-radius:6px ;;border:1px solid #FFFFFF;}
.btnimg:hover{background-color:#F0F0F0;border-color:#00FFFF;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;}
.btnroundimg {cursor:hand; border-radius:30px;}
.btnroundimg:hover{background-color:#F0F0F0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;}
.blacklink {color:#000000;}
.blacklink:hover, .filelink:focus {color:#0094FF;}
input[type="file"]::-webkit-file-upload-button{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #5bc0de;border-color: #46b8da;}
input[type="file"]::-webkit-file-upload-button:focus{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #31b0d5;border-color: #1b6d85;}
input[type="file"]::-webkit-file-upload-button:hover{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #31b0d5;border-color: #269abc;}
.filelink {color:#000000;}
.filelink:hover, .filelink:focus {color:#0094FF;}
.panel-footer{padding:10px 15px;color:#31708f;background-color:#f5f5f5;border-color:#dddddd;border-top:1px solid #dddddd;}
.loader {
border: 4px solid #f3f3f3; /* Light grey */
border-top: 4px solid #3498db; /* Blue */
border-radius: 50%;
width: 12px;
height: 12px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.panel-footer{padding:10px 15px;color:#31708f;background-color:#f5f5f5;border-color:#dddddd;border-top:1px solid #dddddd;}
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 10000; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border: 2px solid #337AB7;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
position: relative;
margin: auto;
padding: 0;
background-color: #fefefe;
}
.modal-header {
padding: 2px 16px;
color: #0f0f0f;
background-color: #f2f2f2;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom: 1px solid #cfcfcf;
}
.modal-body {padding: 10px 16px;}
.modal-footer {
padding: 16px 16px;
height: 4.5em;
color: #0f0f0f;
background-color: #f2f2f2;
border-top: 1px solid #cfcfcf;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
@media (min-width: 768px) {
.modal-content {
width: 580px;
}
}
@media screen and (max-width: 767px) {
.modal-content {
width: 100%;
}
}

255
embedded/www/js/script.js Normal file
View File

@@ -0,0 +1,255 @@
var currentpath = "/";
function navbar(){
var content="<table><tr>";
var tlist = currentpath.split("/");
var path="/";
var nb = 1;
content+="<td class='btnimg' onclick=\"currentpath='/'; SendCommand('list','all');\">/</td>";
while (nb < (tlist.length-1))
{
path+=tlist[nb] + "/";
content+="<td class='btnimg' onclick=\"currentpath='"+path+"'; SendCommand('list','all');\">"+tlist[nb] +"</td><td>/</td>";
nb++;
}
content+="</tr></table>";
return content;
}
function trash_icon(){
var content ="<svg width='24' height='24' viewBox='0 0 128 128'>";
content +="<rect x='52' y='12' rx='6' ry='6' width='25' height='7' style='fill:red;' />";
content +="<rect x='52' y='16' width='25' height='2' style='fill:white;' />";
content +="<rect x='30' y='18' rx='6' ry='6' width='67' height='100' style='fill:red;' />";
content +="<rect x='20' y='18' rx='10' ry='10' width='87' height='14' style='fill:red;' />";
content +="<rect x='20' y='29' width='87' height='3' style='fill:white;' />";
content +="<rect x='40' y='43' rx='7' ry='7' width='7' height='63' style='fill:white;' />";
content +="<rect x='60' y='43' rx='7' ry='7' width='7' height='63' style='fill:white;' />";
content +="<rect x='80' y='43' rx='7' ry='7' width='7' height='63' style='fill:white;' /></svg>";
return content;
}
function back_icon(){
var content ="<svg width='24' height='24' viewBox='0 0 24 24'><path d='M7,3 L2,8 L7,13 L7,10 L17,10 L18,11 L18,15 L17,16 L10,16 L9,17 L9,19 L10,20 L20,20 L22,18 L22,8 L20,6 L7,6 z' stroke='black' fill='white' /></svg>";
return content;
}
function select_dir(directoryname){
currentpath+=directoryname + "/";
SendCommand('list','all');
}
function compareStrings(a, b) {
// case-insensitive comparison
a = a.toLowerCase();
b = b.toLowerCase();
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
function dispatchfilestatus(jsonresponse)
{
var content ="";
content ="&nbsp;&nbsp;Status: "+jsonresponse.status;
content +="&nbsp;&nbsp;|&nbsp;&nbsp;Total space: "+jsonresponse.total;
content +="&nbsp;&nbsp;|&nbsp;&nbsp;Used space: "+jsonresponse.used;
content +="&nbsp;&nbsp;|&nbsp;&nbsp;Occupation: ";
content +="<meter min='0' max='100' high='90' value='"+jsonresponse.occupation +"'></meter>&nbsp;"+jsonresponse.occupation +"%";
document.getElementById('status').innerHTML=content;
content ="";
if (currentpath!="/")
{
var pos = currentpath.lastIndexOf("/",currentpath.length-2);
var previouspath = currentpath.slice(0,pos+1);
content +="<tr style='cursor:hand;' onclick=\"currentpath='"+previouspath+"'; SendCommand('list','all');\"><td >"+back_icon()+"</td><td colspan='4'> Up..</td></tr>";
}
jsonresponse.files.sort(function(a, b) {
return compareStrings(a.name, b.name);
});
for (var i1=0;i1 <jsonresponse.files.length;i1++){
//first display files
if (String(jsonresponse.files[i1].size) != "-1")
{
content +="<TR>";
content +="<td><svg height='24' width='24' viewBox='0 0 24 24' > <path d='M1,2 L1,21 L2,22 L16,22 L17,21 L17,6 L12,6 L12,1 L2,1 z' stroke='black' fill='white' /><line x1='12' y1='1' x2='17' y2='6' stroke='black' stroke-width='1'/>";
content +="<line x1='5' y1='10' x2='13' y2='10' stroke='black' stroke-width='1'/> <line x1='5' y1='14' x2='13' y2='14' stroke='black' stroke-width='1'/> <line x1='5' y1='18' x2='13' y2='18' stroke='black' stroke-width='1'/></svg></td>";
content +="<TD class='btnimg' style=\"padding:0px;\"><a href=\""+jsonresponse.path+jsonresponse.files[i1].name+"\" target=_blank><div class=\"blacklink\">";
content +=jsonresponse.files[i1].name;
content +="</div></a></TD><TD>";
content +=jsonresponse.files[i1].size;
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Delete('"+jsonresponse.files[i1].name+"')\">";
content +=trash_icon();
content +="</div></TD><td></td></TR>";
}
}
//then display directories
for (var i2=0;i2 <jsonresponse.files.length;i2++){
if (String(jsonresponse.files[i2].size) == "-1")
{
content +="<TR>";
content+="<td><svg height='24' width='24' viewBox='0 0 24 24' ><path d='M19,11 L19,8 L18,7 L8,7 L8,5 L7,4 L2,4 L1,5 L1,22 L19,22 L20,21 L23,11 L5,11 L2,21 L1,22' stroke='black' fill='white' /></svg></td>";
content +="<TD class='btnimg blacklink' style='padding:10px 15px;' onclick=\"select_dir('" + jsonresponse.files[i2].name+"');\">";
content +=jsonresponse.files[i2].name;
content +="</TD><TD>";
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Deletedir('"+jsonresponse.files[i2].name+"')\">";
content +=trash_icon();
content +="</div></TD><td></td></TR>";
}
}
document.getElementById('file_list').innerHTML=content;
document.getElementById('path').innerHTML=navbar();}
function Delete(filename){
if (confirm("Confirm deletion of file: " + filename))SendCommand("delete",filename);
}
function Deletedir(filename){
if (confirm("Confirm deletion of directory: " + filename))SendCommand("deletedir",filename);
}
function Createdir(){
var filename = prompt("Please enter directory name", "");
if (filename != null) {
SendCommand("createdir",filename.trim());
}
}
function SendCommand(action,filename){
var xmlhttp = new XMLHttpRequest();
var url = "/files?action="+action;
url += "&filename="+encodeURI(filename);
url += "&path="+encodeURI(currentpath);
document.getElementById('loader').style.visibility="visible";
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 ) {
if(xmlhttp.status == 200) {
var jsonresponse = JSON.parse(xmlhttp.responseText);
document.getElementById('loader').style.visibility="hidden";
dispatchfilestatus(jsonresponse);}
else SubmitRequest ()
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function Sendfile(){
var files = document.getElementById('file-select').files;
if (files.length==0)return;
document.getElementById('upload-button').value = "Uploading...";
document.getElementById('prg').style.visibility = "visible";
var formData = new FormData();
formData.append('path', currentpath);
for (var i3 = 0; i3 < files.length; i3++) {
var file = files[i3];
var arg = currentpath + file.name + "S";
//append file size first to check updload is complete
formData.append(arg, file.size);
formData.append('myfiles[]', file, currentpath+file.name);}
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', '/files', true);
//progress upload event
xmlhttp.upload.addEventListener("progress", updateProgress, false);
//progress function
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = (oEvent.loaded / oEvent.total)*100;
document.getElementById('prg').value=percentComplete;
document.getElementById('upload-button').value = "Uploading ..." + percentComplete.toFixed(0)+"%" ;
} else {
// Impossible because size is unknown
}
}
xmlhttp.onload = function () {
if (xmlhttp.status === 200) {
document.getElementById('upload-button').value = 'Upload';
document.getElementById('prg').style.visibility = "hidden";
document.getElementById('file-select').value="";
var jsonresponse = JSON.parse(xmlhttp.responseText);
dispatchfilestatus(jsonresponse);
} else alert('An error occurred!');
};
xmlhttp.send(formData);
}
window.onload = function() {
SendCommand('list','all');
};
function Uploadfile(){
if (!confirm("Confirm Firmware Update ?"))return;
var files = document.getElementById('fw-select').files;
if (files.length==0)return;
document.getElementById('uploadfw-button').style.visibility = 'hidden';
document.getElementById('fw-select').style.visibility = 'hidden';
document.getElementById('msg').style.visibility = "visible";
document.getElementById('msg').innerHTML="";
document.getElementById('SPIFFS').style.display = "none";
document.getElementById('prgfw').style.visibility = "visible";
var formData = new FormData();
for (var i4 = 0; i4 < files.length; i4++) {
var file = files[i4];
var arg = "/" + file.name + "S";
//append file size first to check updload is complete
formData.append(arg, file.size);
formData.append('myfile[]', file, "/"+file.name);}
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', '/updatefw', true);
//progress upload event
xmlhttp.upload.addEventListener("progress", updateProgress, false);
//progress function
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = (oEvent.loaded / oEvent.total)*100;
document.getElementById('prgfw').value=percentComplete;
document.getElementById('msg').innerHTML = "Uploading ..." + percentComplete.toFixed(0)+"%" ;
} else {
// Impossible because size is unknown
}
}
xmlhttp.onload = function () {
if (xmlhttp.status === 200) {
document.getElementById('uploadfw-button').value = 'Upload';
document.getElementById('msg').innerHTML="Restarting, please wait....";
document.getElementById('counter').style.visibility = "visible";
document.getElementById('uploadfw-button').style.visibility = 'hidden';
document.getElementById('uploadfw-button').style.width = '0px';
document.getElementById('fw-select').value="";
document.getElementById('fw-select').style.visibility = 'hidden';
document.getElementById('fw-select').style.width = '0px';
var jsonresponse = JSON.parse(xmlhttp.responseText);
if (jsonresponse.status=='1' || jsonresponse.status=='4' || jsonresponse.status=='1')alert("Update failed");
if (jsonresponse.status=='2')alert('Update canceled!');
else if (jsonresponse.status=='3')
{
var i5 = 0;
var interval;
var x = document.getElementById("prgfw");
x.max=40;
interval = setInterval(function(){
i5=i5+1;
var x = document.getElementById("prgfw");
x.value=i5;
document.getElementById('counter').innerHTML=41-i5;
if (i5>40)
{
clearInterval(interval);
location.reload();
}
},1000);
}
else alert('Update failed!');
} else alert('An error occurred!');
};
xmlhttp.send(formData);
}
function RequestLogin(){
document.getElementById('loader').style.visibility="hidden";
document.getElementById('loginpage').style.display='block';
}
function SubmitRequest (){
document.getElementById('loginpage').style.display='none';
var user = document.getElementById('login_user_text').value.trim();
var password = document.getElementById('login_password_text').value.trim();
var url = "/login?USER="+encodeURIComponent(user) + "&PASSWORD=" + encodeURIComponent(password) + "&SUBMIT=yes" ;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
RequestLogin();
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}

101
embedded/www/tool.html Normal file
View File

@@ -0,0 +1,101 @@
<html>
<head>
<!-- smoosh -->
<link href="css/style.css" rel="stylesheet">
<!-- endsmoosh -->
</head>
<body>
<div style="position:absolute;top:0;right:0;">
V1.2
&nbsp;&nbsp;
</div>
<center>
<h2>It seems you do not have any index.html neither index.html.gz, please upload it or update your firmware if necessary.</h2>
you can find one here : <a class='blacklink' href='https://github.com/luc-github/ESP3D-WEBUI'>https://github.com/luc-github/ESP3D-WEBUI</a>
</center>
<div class="panel" id="SPIFFS">
<div class="panel-heading">Flash Filesystem</div>
<div class="panel-body">
<input type="file" id="file-select" name="myfiles[]" multiple />
<input class="btn btn-primary" type="button" id="upload-button" onclick="Sendfile();" value="Upload"/>&nbsp;&nbsp;<progress style="visibility:hidden;" name='prg' id='prg' max='100'></progress>
<br><br>
<div class="panel">
<div class="panel-body">
<table>
<tr>
<td width="0%">
<input class="btn btn-primary" type="button" onclick="SendCommand('list','all');" value="Refresh"/>
</td>
<td width="0%">
<div onclick="Createdir()" class="btnimg"><svg width="40" height="40" viewBox="0 0 40 40"><rect x="5" y="10" width="30" height="20" rx="2" ry="2" fill="#31b0d5" />
<rect x="20" y="5" width="15" height="15" rx="2" ry="2" fill="#31b0d5" /><text x="15" y="25" font-size="18" font-weight="800" fill="white">+</text></svg>
</div>
</td>
<td>
<div id="loader" class="loader"></div>
</td>
<td width="100%">
<div id="path" class="info" >&nbsp;</div>
</td>
</tr>
</table>
<table class="table table-striped" style="border:1px;solid #dddddd;margin-bottom:20px;" >
<thead>
<tr>
<th width='0%'>Type</th>
<th>Name</th>
<th>Size</th>
<th width='0%'></th>
<th width='100%'></th>
</tr>
</thead>
<tbody id="file_list"></tbody>
</table>
</div>
<div class="panel-footer " id="status"></div>
</div>
</div>
</div>
<div class="panel">
<div class="panel-heading">Firmware Update</div>
<div class="panel-body">
<table>
<tr>
<td><input type="file" id="fw-select" name="myfiles[]" /></td>
<td><input class="btn btn-primary" type="button" id="uploadfw-button" onclick="Uploadfile();" value="Update"/></td>
<td><progress style="visibility:hidden;" name='prgfw' id='prgfw' max='100'></progress></td>
<td><span id='msg' style='visibility:hidden;'>Restarting, please wait....</span><span id='counter'></span></td>
</tr>
</table>
</div>
</div>
<div id="loginpage"class="modal">
<div class="modal-content" >
<div class="modal-header">
<h3>Identification</h3>
</div>
<div class="modal-body">
<span>
<span class="modal-text" translate>User:</span>
<input class='form-control' type="text" id="login_user_text" style="width:auto"/>
</span>
<hr>
<span>
<span class="modal-text" translate>Password:</span>
<input class='form-control' type="password" id="login_password_text" style="width:auto"/>
</span>
<br>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-primary" onclick="SubmitRequest()" value="Submit"/>
</div>
</div>
</div>
<!-- smoosh -->
<script src="js/script.js"></script>
<!-- endsmoosh -->
</body>
</html>

View File

@@ -111,7 +111,7 @@ struct SSDPTimer {
SSDPClass::SSDPClass() :
_server(0),
_timer(new SSDPTimer),
_timer(0),
_port(80),
_ttl(SSDP_MULTICAST_TTL),
_respondToPort(0),
@@ -134,30 +134,40 @@ _notify_time(0)
}
SSDPClass::~SSDPClass(){
delete _timer;
end();
}
void SSDPClass::end(){
if(!_server) {
return;
}
#ifdef DEBUG_SSDP
DEBUG_SSDP.printf_P(PSTR("SSDP end ... "));
#endif
// undo all initializations done in begin(), in reverse order
_stopTimer();
_server->stop();
delete (_server);
_server = 0;
}
bool SSDPClass::begin(){
_pending = false;
end();
uint32_t chipId = ((uint16_t) (ESP.getEfuseMac() >> 32));
sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
(uint16_t) ((chipId >> 16) & 0xff),
(uint16_t) ((chipId >> 8) & 0xff),
(uint16_t) chipId & 0xff );
assert(nullptr == _server);
_server = new WiFiUDP;
#ifdef DEBUG_SSDP
DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid);
#endif
if (_server) {
delete (_server);
_server = 0;
}
_server = new WiFiUDP;
if (!(_server->beginMulticast(IPAddress(SSDP_MULTICAST_ADDR), SSDP_PORT))) {
#ifdef DEBUG_SSDP
DEBUG_SSDP.println("Error begin");
@@ -187,7 +197,7 @@ void SSDPClass::_send(ssdp_method_t method){
_deviceType,
ip[0], ip[1], ip[2], ip[3], _port, _schemaURL
);
if(len < 0) return;
IPAddress remoteAddr;
uint16_t remotePort;
if(method == NONE) {
@@ -234,7 +244,7 @@ void SSDPClass::schema(WiFiClient client){
void SSDPClass::_update(){
int nbBytes =0;
char * packetBuffer = NULL;
char * packetBuffer = nullptr;
if(!_pending && _server) {
ssdp_method_t method = NONE;
@@ -430,6 +440,8 @@ void SSDPClass::_onTimerStatic(SSDPClass* self) {
}
void SSDPClass::_startTimer() {
_stopTimer();
_timer= new SSDPTimer();
ETSTimer* tm = &(_timer->timer);
const int interval = 1000;
ets_timer_disarm(tm);
@@ -437,6 +449,16 @@ void SSDPClass::_startTimer() {
ets_timer_arm(tm, interval, 1 /* repeat */);
}
void SSDPClass::_stopTimer() {
if(!_timer){
return;
}
ETSTimer* tm = &(_timer->timer);
ets_timer_disarm(tm);
delete _timer;
_timer = nullptr;
}
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP)
SSDPClass SSDP;
#endif

View File

@@ -60,6 +60,7 @@ class SSDPClass{
~SSDPClass();
bool begin();
void end();
void schema(WiFiClient client);
@@ -91,6 +92,7 @@ class SSDPClass{
void _send(ssdp_method_t method);
void _update();
void _startTimer();
void _stopTimer();
static void _onTimerStatic(SSDPClass* self);
WiFiUDP *_server;

View File

@@ -36,6 +36,7 @@ void setup() {
SSDP.setModelURL("http://www.meethue.com");
SSDP.setManufacturer("Royal Philips Electronics");
SSDP.setManufacturerURL("http://www.philips.com");
SSDP.setDeviceType("upnp:rootdevice"); //to appear as root device
SSDP.begin();
Serial.printf("Ready!\n");

23
platformio.ini Normal file
View File

@@ -0,0 +1,23 @@
[platformio]
src_dir=Grbl_Esp32
lib_dir=libraries
data_dir=Grbl_Esp32/data
[common_env_data]
lib_deps_builtin =
EEPROM
BluetoothSerial
WiFi
FS
SD
SPI
Preferences
SPIFFS
WebServer
[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
upload_speed = 512000
board_build.partitions = min_spiffs.csv