From 82fdb29a18b578362f97040ce3101328ff7a9407 Mon Sep 17 00:00:00 2001 From: bdring Date: Thu, 29 Nov 2018 21:17:18 -0600 Subject: [PATCH] Added optional pen and solenoid control of Z axis - Added Servo features - Added Solenoid Features - Added cpu_maps for pen/laser controler and midtbot --- Grbl_Esp32/Grbl_Esp32.ino | 11 ++- Grbl_Esp32/config.h | 8 +- Grbl_Esp32/cpu_map.h | 120 +++++++++++++++++++++++++-- Grbl_Esp32/defaults.h | 96 ++++++++++++++++++++++ Grbl_Esp32/grbl.h | 3 + Grbl_Esp32/servo_pen.cpp | 157 ++++++++++++++++++++++++++++++++++++ Grbl_Esp32/servo_pen.h | 80 ++++++++++++++++++ Grbl_Esp32/solenoid_pen.cpp | 125 ++++++++++++++++++++++++++++ Grbl_Esp32/solenoid_pen.h | 53 ++++++++++++ 9 files changed, 644 insertions(+), 9 deletions(-) create mode 100644 Grbl_Esp32/servo_pen.cpp create mode 100644 Grbl_Esp32/servo_pen.h create mode 100644 Grbl_Esp32/solenoid_pen.cpp create mode 100644 Grbl_Esp32/solenoid_pen.h diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 0be7514d..deb702dd 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -58,10 +58,15 @@ void setup() { } #endif - - memset(sys_position,0,sizeof(sys_position)); // Clear machine position. - + + #ifdef USE_PEN_SERVO + servo_init(); + #endif + + #ifdef USE_PEN_SOLENOID + solenoid_init(); + #endif // Initialize system state. #ifdef FORCE_INITIALIZATION_ALARM diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index c5a2ec7e..40bebbd6 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -47,7 +47,6 @@ Some features should not be changed. See notes below. // If doing so, simply comment out these two defines and see instructions below. #define DEFAULTS_GENERIC #define CPU_MAP_ESP32 // currently not required -#define VERBOSE_HELP // adds addition help info, but could confuse some senders // Serial baud rate #define BAUD_RATE 115200 @@ -223,6 +222,13 @@ Some features should not be changed. See notes below. // have the same steps per mm internally. // #define COREXY // Default disabled. Uncomment to enable. +// 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 servo PWM pin and settings in servo_pen.h +//#define USE_PEN_SERVO +// Enable using a solenoid for the Z axis on a pen type machine +//#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 diff --git a/Grbl_Esp32/cpu_map.h b/Grbl_Esp32/cpu_map.h index 8235a069..41ef4125 100644 --- a/Grbl_Esp32/cpu_map.h +++ b/Grbl_Esp32/cpu_map.h @@ -19,7 +19,7 @@ */ #ifndef cpu_map_h -#define cpu_map_h +//#define cpu_map_h /* Not all pins can can work for all functions. @@ -36,6 +36,7 @@ */ +#ifdef CPU_MAP_ESP32 // This is the CPU Map for the ESP32 CNC Controller R2 // It is OK to comment out any step and direction pins. This @@ -71,9 +72,11 @@ #define SPINDLE_PWM_BIT_PRECISION 12 // be sure to match this with SPINDLE_PWM_MAX_VALUE #define SPINDLE_PWM_OFF_VALUE 0 #define SPINDLE_PWM_MAX_VALUE 4096 // (2^SPINDLE_PWM_BIT_PRECISION) -#ifndef SPINDLE_PWM_MIN_VALUE - #define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero. -#endif + + #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) // if these spindle function pins are defined, they will be activated in the code @@ -92,7 +95,113 @@ #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup #define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup - // These are some ESP32 CPU Settings that the program needs, but are generally not changed +#endif + + +#ifdef CPU_MAP_PEN_LASER // The Buildlog.net pen laser controller V1 + #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 + + #define X_LIMIT_PIN GPIO_NUM_2 + #define Y_LIMIT_PIN GPIO_NUM_4 + + // 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 + + + // 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 12 // be sure to match this with SPINDLE_PWM_MAX_VALUE + #define SPINDLE_PWM_OFF_VALUE 0 + #define SPINDLE_PWM_MAX_VALUE 4096 // (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) + + // see servo_pen.h for servo i/o mapping + + +#endif + +#ifdef CPU_MAP_MIDTBOT // Buildlog.net midtbot + #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 + + #ifndef COREXY // maybe set in config.h + #define COREXY + #endif + + #define STEPPERS_DISABLE_PIN GPIO_NUM_13 + + #define X_LIMIT_PIN GPIO_NUM_2 + #define Y_LIMIT_PIN GPIO_NUM_4 + + #ifndef USE_PEN_SERVO // maybe set in config.h + #define USE_PEN_SERVO + #endif + + #ifndef IGNORE_CONTROL_PINS // maybe set in config.h + #define IGNORE_CONTROL_PINS + #endif + #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 + + // 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 12 // be sure to match this with SPINDLE_PWM_MAX_VALUE + #define SPINDLE_PWM_OFF_VALUE 0 + #define SPINDLE_PWM_MAX_VALUE 4096 // (2^SPINDLE_PWM_BIT_PRECISION) + + #ifndef SPINDLE_PWM_MIN_VALUE + #define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero. + #endif + + // redefine some stuff from config.h + #define HOMING_CYCLE_0 (1<. + +*/ +#include "grbl.h" + +#ifdef USE_PEN_SERVO + +// used to delay turn on +bool servo_pen_enable = false; + +void servo_init() +{ + grbl_send(CLIENT_SERIAL, "[MSG:Servo Pen Mode]\r\n"); // startup message + //validate_servo_settings(true); // display any calibration errors + + // Debug stuff + grbl_sendf(CLIENT_SERIAL, "[MSG:Servo max,min pulse times %.4f sec,%.4f sec]\r\n", SERVO_MAX_PULSE_SEC, SERVO_MIN_PULSE_SEC); + grbl_sendf(CLIENT_SERIAL, "[MSG:Servo max,min pulse counts %d,%d]\r\n", SERVO_MAX_PULSE, SERVO_MIN_PULSE); + validate_servo_settings(true); // will print errors + // debug stuff + + servo_pen_enable = false; // start delay has not completed yet. + + // setup PWM channel + ledcSetup(SERVO_PEN_CHANNEL_NUM, SERVO_PULSE_FREQ, SERVO_PULSE_RES_BITS); + ledcAttachPin(SERVO_PEN_PIN, SERVO_PEN_CHANNEL_NUM); + + servo_disable(); // start it it off + + // setup a task that will calculate the determine and set the servo position + xTaskCreatePinnedToCore( servoSyncTask, // task + "servoSyncTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority + &servoSyncTaskHandle, + 0 // core + ); +} + +// turn off the PWM (0 duty) to prevent servo jitter when not in use. +void servo_disable() +{ + ledcWrite(SERVO_PEN_CHANNEL_NUM, 0); +} + +// Grbl settings are used to calibrate the servo positions +// They work on a percentage, so a value of 100 (100%) applies no calibration +// Values outside a reasonable range can cause errors, so this function checks +// that they are within a reasonable range +bool validate_servo_settings(bool verbose) // make sure the settings are reasonable..otherwise reset the settings to default +{ + bool settingsOK = true; + + if ( (settings.steps_per_mm[Z_AXIS] < SERVO_CAL_MIN) || (settings.steps_per_mm[Z_AXIS] > SERVO_CAL_MAX) ) { + if (verbose) { + grbl_sendf(CLIENT_SERIAL, "[MSG:Servo cal ($102) Error: %4.4f s/b between %.2f and %.2f]\r\n", settings.steps_per_mm[Z_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[Z_AXIS] < -SERVO_CAL_MAX) || (settings.max_travel[Z_AXIS] > -SERVO_CAL_MIN) ) { + if (verbose) { + grbl_sendf(CLIENT_SERIAL, "[MSG:Servo cal ($132) Error: %4.4f s/b between %.2f and %.2f]\r\n", -settings.max_travel[Z_AXIS], SERVO_CAL_MIN, SERVO_CAL_MAX); + } + + settingsOK = false; + } + + return settingsOK; +} + +// this is the task +void servoSyncTask(void *pvParameters) +{ + int32_t current_position[N_AXIS]; // copy of current location + float m_pos[N_AXIS]; // machine position in mm + 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); + + if (!servo_pen_enable) { + servo_delay_counter++; + servo_pen_enable = (servo_delay_counter > SERVO_TURNON_DELAY); + } else { + if(!stepper_idle) { + memcpy(current_position,sys_position,sizeof(sys_position)); // get current position in step + system_convert_array_steps_to_mpos(m_pos,current_position); // convert to millimeters + + calc_pen_servo(m_pos[Z_AXIS]); // calculate kinematics and move the servos + } else { + servo_disable(); + } + + } + } +} + +// calculate and set the PWM value for the servo +void calc_pen_servo(float penZ) +{ + uint32_t servo_pen_pulse_len; + float servo_pen_pulse_min, servo_pen_pulse_max; + + if (!servo_pen_enable) { // only proceed if startup delay as expired + return; + } + + 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); + } else { // use the defaults + servo_pen_pulse_min = SERVO_MIN_PULSE; + servo_pen_pulse_max = SERVO_MAX_PULSE; + } + + // determine the pulse length + servo_pen_pulse_len = mapConstrain(penZ, SERVO_PEN_RANGE_MIN_MM, SERVO_PEN_RANGE_MAX_MM, servo_pen_pulse_min, servo_pen_pulse_max ); + + // TODO only update it if it has changed + + // update the PWM value + // ledcWrite appears to have issues with interrupts, so make this a critical section + portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED; + taskENTER_CRITICAL(&myMutex); + ledcWrite(SERVO_PEN_CHANNEL_NUM, servo_pen_pulse_len); + taskEXIT_CRITICAL(&myMutex); +} + +#endif diff --git a/Grbl_Esp32/servo_pen.h b/Grbl_Esp32/servo_pen.h new file mode 100644 index 00000000..7ab59165 --- /dev/null +++ b/Grbl_Esp32/servo_pen.h @@ -0,0 +1,80 @@ +/* + servo.h + Part of Grbl_ESP32 + + copyright (c) 2018 - Bart Dring This file was modified 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 . + + To use this, uncomment #define USE_PEN_SERVO in config.h + + That should be the only change you need at the top level + Everything occurs as a low priority task that syncs the servo with the + current machine position. + + TODO Make it reversible (turn opposite way) + +*/ + +// ==== Begin: Things you are likely to change ==================== +//#define SERVO_PEN_PIN GPIO_NUM_27 // FYI...you can disable the Z stepper pins (step & dir) + +// 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_MAX_PULSE_SEC 0.002 // max pulse in seconds + +// Pulse repeat rate (PWM Frequency) +#define SERVO_PULSE_FREQ 50 // 50Hz ...This is a standard analog servo value. Digital ones can repeat faster + +// the range of the servo is constrained +// values above or below these will be limited to the min or max +#define SERVO_PEN_RANGE_MIN_MM 0.0 // the minimum z position in mm +#define SERVO_PEN_RANGE_MAX_MM 5.0 // the minimum z position in mm +// ==== End: Things you are likely to change ======================= + +// Begin: Advanced settings + +#define SERVO_TIMER_NUM 1 +#define SERVO_TIMER_INT_FREQ 20 // Hz This is the task frequency +#define SERVO_PEN_CHANNEL_NUM 5 + +#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 + +// A way to reduce the turn on current +#define SERVO_TURNON_DELAY 25 // 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 + +#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_CAL_MIN 20.0 // Percent: the minimum allowable calibration value +#define SERVO_CAL_MAX 180.0 // Percent: the maximum allowable calibration value + +#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 \ No newline at end of file diff --git a/Grbl_Esp32/solenoid_pen.cpp b/Grbl_Esp32/solenoid_pen.cpp new file mode 100644 index 00000000..44b006c2 --- /dev/null +++ b/Grbl_Esp32/solenoid_pen.cpp @@ -0,0 +1,125 @@ +/* + solenoid_pen.cpp + Part of Grbl_ESP32 + + copyright (c) 2018 - Bart Dring This file was modified 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 . + +*/ +#include "grbl.h" + +#ifdef USE_PEN_SOLENOID + +// used to delay turn on +bool solenoid_pen_enable; +uint16_t solenoide_hold_count; + +void solenoid_init() +{ + grbl_send(CLIENT_SERIAL, "[MSG:Solenoid Mode]\r\n"); // startup message + //validate_servo_settings(true); // display any calibration errors + + solenoid_pen_enable = false; // start delay has not completed yet. + solenoide_hold_count = 0; // initialize + + // setup PWM channel + ledcSetup(SOLENOID_CHANNEL_NUM, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS); + ledcAttachPin(SOLENOID_PEN_PIN, SOLENOID_CHANNEL_NUM); + + solenoid_disable(); // start it it off + + // setup a task that will calculate the determine and set the servo position + xTaskCreatePinnedToCore( solenoidSyncTask, // task + "solenoidSyncTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority + &solenoidSyncTaskHandle, + 0 // core + ); +} + +// turn off the PWM (0 duty) +void solenoid_disable() +{ + ledcWrite(SOLENOID_CHANNEL_NUM, 0); +} + +// this is the task +void solenoidSyncTask(void *pvParameters) +{ + int32_t current_position[N_AXIS]; // copy of current location + float m_pos[N_AXIS]; // machine position in mm + TickType_t xLastWakeTime; + const TickType_t xSolenoidFrequency = SOLENOID_TIMER_INT_FREQ; // in ticks (typically ms) + uint16_t solenoid_delay_counter = 0; + + while(true) { // don't ever return from this or the task dies + + vTaskDelayUntil(&xLastWakeTime, xSolenoidFrequency); + + if (!solenoid_pen_enable) { + solenoid_delay_counter++; + solenoid_pen_enable = (solenoid_delay_counter > SOLENOID_TURNON_DELAY); + } + else { + memcpy(current_position,sys_position,sizeof(sys_position)); // get current position in step + system_convert_array_steps_to_mpos(m_pos,current_position); // convert to millimeters + calc_solenoid(m_pos[Z_AXIS]); // calculate kinematics and move the servos + } + } +} + +// calculate and set the PWM value for the servo +void calc_solenoid(float penZ) +{ + uint32_t solenoid_pen_pulse_len; + + if (!solenoid_pen_enable) // only proceed if startup delay as expired + return; + + + + + if (penZ < 0 && (sys.state != STATE_ALARM)) { // alarm also makes it go up + solenoide_hold_count = 0; // reset this count + solenoid_pen_pulse_len = 0; // + } + else { + if (solenoide_hold_count < SOLENOID_PULSE_LEN_HOLD) { + solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_UP; + solenoide_hold_count++; + } + else { + solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_HOLD; + } + + } + + // skip setting value if it is unchanged + if (ledcRead(SOLENOID_CHANNEL_NUM) == solenoid_pen_pulse_len) + return; + + // update the PWM value + // ledcWrite appears to have issues with interrupts, so make this a critical section + portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED; + taskENTER_CRITICAL(&myMutex); + ledcWrite(SOLENOID_CHANNEL_NUM, solenoid_pen_pulse_len); + taskEXIT_CRITICAL(&myMutex); +} + +#endif + diff --git a/Grbl_Esp32/solenoid_pen.h b/Grbl_Esp32/solenoid_pen.h new file mode 100644 index 00000000..078f7dc2 --- /dev/null +++ b/Grbl_Esp32/solenoid_pen.h @@ -0,0 +1,53 @@ +/* + solenoid_pen.h + Part of Grbl_ESP32 + + copyright (c) 2018 - Bart Dring This file was modified 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 . + + Usage notes: + 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. + + 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 + between solenoid states as the Z "travels" to the location that will + change the state. + +*/ + +#define SOLENOID_PEN_PIN GPIO_NUM_16 +#define SOLENOID_CHANNEL_NUM 6 +#define SOLENOID_PWM_FREQ 5000 +#define SOLENOID_PWM_RES_BITS 8 + +#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_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); +void calc_solenoid(float penZ); + +#endif \ No newline at end of file