kopia lustrzana https://github.com/Schildkroet/GRBL-Advanced
Code refactoring
Updated makefile with new gcc9 Updated readme Added Lathe support Added separated limit inputs (fix #53) Added encoder support Added support for dynamic tool length offset on all axis fix #54pull/89/head
rodzic
e50fcc46d0
commit
880b4d86c7
|
@ -92,7 +92,6 @@
|
|||
<Add option="-u _scanf_float" />
|
||||
<Add option="-eb_lib=n" />
|
||||
<Add option="-eb_start_files" />
|
||||
<Add option="-flto" />
|
||||
<Add option="-lm" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
|
@ -340,11 +339,19 @@
|
|||
<Unit filename="HAL\USART\USART.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="HAL\USART\USART.h" />
|
||||
<Unit filename="HAL\USART\Usart.h" />
|
||||
<Unit filename="Libraries\CRC\CRC.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\CRC\CRC.h" />
|
||||
<Unit filename="Libraries\EEPROM\M24C0X.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\EEPROM\M24C0X.h" />
|
||||
<Unit filename="Libraries\Encoder\Encoder.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\Encoder\Encoder.h" />
|
||||
<Unit filename="Libraries\Ethernet\Ethernet.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
|
@ -370,26 +377,29 @@
|
|||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\GrIP\GrIP.h" />
|
||||
<Unit filename="Libraries\Printf\Print.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\Printf\Print.h" />
|
||||
<Unit filename="main.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="README.md" />
|
||||
<Unit filename="Src\debug.h" />
|
||||
<Unit filename="Src\M24C0X.c">
|
||||
<Unit filename="Src\PID.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Src\M24C0X.h" />
|
||||
<Unit filename="Src\PID.h" />
|
||||
<Unit filename="Src\Platform.h" />
|
||||
<Unit filename="Src\Print.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Src\Print.h" />
|
||||
<Unit filename="stm32f411re_flash.ld" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<debugger>
|
||||
<target_debugging_settings target="Debug" active_interface="ST-link">
|
||||
<debug_interface interface_id="ST-link" ip_address="localhost" ip_port="4242" path="${EMBITZ}\share\contrib" executable="STLinkGDB.exe" description="" dont_start_server="false" backoff_time="400" options="2" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<target_debugging_settings target="Release" active_interface="EBlink">
|
||||
<debug_interface interface_id="EBlink" ip_address="localhost" ip_port="4242" path="C:\Program Files (x86)\EmBitz\1.11\share\EBlink" executable="eblink.exe" description="" dont_start_server="false" backoff_time="400" options="0" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<family_options family_id="STMicroelectronics" />
|
||||
</debug_interface>
|
||||
<debug_interface interface_id="ST-link" ip_address="localhost" ip_port="4242" path="${EMBITZ}\share\contrib" executable="STLinkGDB.exe" description="" dont_start_server="false" backoff_time="400" options="10" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<family_options family_id="STMicroelectronics">
|
||||
<option opt_id="ID_JTAG_SWD" opt_value="swd" />
|
||||
<option opt_id="ID_VECTOR_START" opt_value="0x08000000" />
|
||||
|
@ -405,8 +415,31 @@
|
|||
</family_options>
|
||||
</debug_interface>
|
||||
</target_debugging_settings>
|
||||
<target_debugging_settings target="Release" active_interface="ST-link">
|
||||
<debug_interface interface_id="ST-link" ip_address="localhost" ip_port="4242" path="${EMBITZ}\share\contrib" executable="STLinkGDB.exe" description="" dont_start_server="false" backoff_time="400" options="10" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<target_debugging_settings target="Debug" active_interface="EBlink">
|
||||
<debug_interface interface_id="EBlink" ip_address="localhost" ip_port="4242" path="C:\Program Files (x86)\EmBitz\1.11\share\EBlink" executable="eblink.exe" description="" dont_start_server="false" backoff_time="400" options="2" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<family_options family_id="STMicroelectronics">
|
||||
<option opt_id="ID_DEV_ADDR" opt_value="" />
|
||||
<option opt_id="ID_DEV_SPEED" opt_value="4000" />
|
||||
<option opt_id="ID_JTAG_SWD" opt_value="swd" />
|
||||
<option opt_id="ID_RESET_TYPE" opt_value="System" />
|
||||
<option opt_id="ID_DEVICE_SCRIPT_LIST" opt_value="stm32-auto" />
|
||||
<option opt_id="ID_VERBOSE_LEVEL" opt_value="" />
|
||||
<option opt_id="ID_VEC_TABLE" opt_value="1" />
|
||||
<option opt_id="ID_VECTOR_START" opt_value="0x08000000" />
|
||||
<option opt_id="ID_RAM_EXEC" opt_value="0" />
|
||||
<option opt_id="ID_LOAD_PROGRAM" opt_value="1" />
|
||||
<option opt_id="ID_HOTPLUG_CONNECT" opt_value="0" />
|
||||
<option opt_id="ID_SEMIHOST_CHECK" opt_value="1" />
|
||||
<option opt_id="ID_NO_FLASH_CACHE" opt_value="0" />
|
||||
<option opt_id="ID_NO_GUI_MSGBOX" opt_value="0" />
|
||||
<option opt_id="ID_SHUTDOWN_AFTER_DISCONNECT" opt_value="1" />
|
||||
<option opt_id="ID_EBLINK_CMD_LINE" opt_value="" />
|
||||
<option opt_id="ID_CMD_RESET" opt_value="" />
|
||||
<option opt_id="ID_BEFORE_CONNECT" opt_value="" />
|
||||
<option opt_id="ID_AFTER_CONNECT" opt_value="" />
|
||||
</family_options>
|
||||
</debug_interface>
|
||||
<debug_interface interface_id="ST-link" ip_address="localhost" ip_port="4242" path="${EMBITZ}\share\contrib" executable="STLinkGDB.exe" description="" dont_start_server="false" backoff_time="400" options="2" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<family_options family_id="STMicroelectronics">
|
||||
<option opt_id="ID_JTAG_SWD" opt_value="swd" />
|
||||
<option opt_id="ID_VECTOR_START" opt_value="0x08000000" />
|
||||
|
|
|
@ -14,25 +14,25 @@
|
|||
<Option compiler="armgcc_eb" />
|
||||
<Option projectDeviceOptionsRelation="0" />
|
||||
<Compiler>
|
||||
<Add option="-g3" />
|
||||
<Add option="-O0" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-fdata-sections" />
|
||||
<Add option="-ffunction-sections" />
|
||||
<Add option="-O0" />
|
||||
<Add option="-g3" />
|
||||
</Compiler>
|
||||
<Cpp>
|
||||
<Add option="-g3" />
|
||||
<Add option="-O0" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-fdata-sections" />
|
||||
<Add option="-ffunction-sections" />
|
||||
<Add option="-O0" />
|
||||
<Add option="-g3" />
|
||||
</Cpp>
|
||||
<Assembler>
|
||||
<Add option="-Wa,--gdwarf-2" />
|
||||
</Assembler>
|
||||
<Linker>
|
||||
<Add option="-Wl,--gc-sections" />
|
||||
<Add option="-eb_use_semi" />
|
||||
<Add option="-Wl,--gc-sections" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
|
@ -92,7 +92,6 @@
|
|||
<Add option="-u _scanf_float" />
|
||||
<Add option="-eb_lib=n" />
|
||||
<Add option="-eb_start_files" />
|
||||
<Add option="-flto" />
|
||||
<Add option="-lm" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
|
@ -345,6 +344,14 @@
|
|||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\CRC\CRC.h" />
|
||||
<Unit filename="Libraries\EEPROM\M24C0X.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\EEPROM\M24C0X.h" />
|
||||
<Unit filename="Libraries\Encoder\Encoder.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\Encoder\Encoder.h" />
|
||||
<Unit filename="Libraries\Ethernet\Ethernet.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
|
@ -370,25 +377,48 @@
|
|||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\GrIP\GrIP.h" />
|
||||
<Unit filename="Libraries\Printf\Print.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Libraries\Printf\Print.h" />
|
||||
<Unit filename="main.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="README.md" />
|
||||
<Unit filename="Src\debug.h" />
|
||||
<Unit filename="Src\M24C0X.c">
|
||||
<Unit filename="Src\PID.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Src\M24C0X.h" />
|
||||
<Unit filename="Src\PID.h" />
|
||||
<Unit filename="Src\Platform.h" />
|
||||
<Unit filename="Src\Print.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="Src\Print.h" />
|
||||
<Unit filename="stm32f446re_flash.ld" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<debugger>
|
||||
<target_debugging_settings target="Debug" active_interface="ST-link">
|
||||
<debug_interface interface_id="EBlink" ip_address="localhost" ip_port="4242" path="C:\Program Files (x86)\EmBitz\1.11\share\EBlink" executable="eblink.exe" description="" dont_start_server="false" backoff_time="400" options="10" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<family_options family_id="STMicroelectronics">
|
||||
<option opt_id="ID_DEV_ADDR" opt_value="" />
|
||||
<option opt_id="ID_DEV_SPEED" opt_value="4000" />
|
||||
<option opt_id="ID_JTAG_SWD" opt_value="swd" />
|
||||
<option opt_id="ID_RESET_TYPE" opt_value="System" />
|
||||
<option opt_id="ID_DEVICE_SCRIPT_LIST" opt_value="stm32-auto" />
|
||||
<option opt_id="ID_VERBOSE_LEVEL" opt_value="" />
|
||||
<option opt_id="ID_VEC_TABLE" opt_value="1" />
|
||||
<option opt_id="ID_VECTOR_START" opt_value="0x08000000" />
|
||||
<option opt_id="ID_RAM_EXEC" opt_value="0" />
|
||||
<option opt_id="ID_LOAD_PROGRAM" opt_value="1" />
|
||||
<option opt_id="ID_HOTPLUG_CONNECT" opt_value="0" />
|
||||
<option opt_id="ID_SEMIHOST_CHECK" opt_value="1" />
|
||||
<option opt_id="ID_NO_FLASH_CACHE" opt_value="0" />
|
||||
<option opt_id="ID_NO_GUI_MSGBOX" opt_value="0" />
|
||||
<option opt_id="ID_SHUTDOWN_AFTER_DISCONNECT" opt_value="1" />
|
||||
<option opt_id="ID_EBLINK_CMD_LINE" opt_value="" />
|
||||
<option opt_id="ID_CMD_RESET" opt_value="" />
|
||||
<option opt_id="ID_BEFORE_CONNECT" opt_value="" />
|
||||
<option opt_id="ID_AFTER_CONNECT" opt_value="" />
|
||||
</family_options>
|
||||
</debug_interface>
|
||||
<debug_interface interface_id="ST-link" ip_address="localhost" ip_port="4242" path="${EMBITZ}\share\contrib" executable="STLinkGDB.exe" description="" dont_start_server="false" backoff_time="400" options="2" reg_filter="0" active_family="STMicroelectronics" gdb_before_conn="" gdb_after_conn="">
|
||||
<family_options family_id="STMicroelectronics">
|
||||
<option opt_id="ID_JTAG_SWD" opt_value="swd" />
|
||||
|
|
|
@ -112,12 +112,14 @@ static void GPIO_InitSpindle(void)
|
|||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* GPIO Configuration: */
|
||||
#if !defined(LATHE_MODE)
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
#endif
|
||||
|
||||
/* GPIO Configuration: PWM */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
||||
|
@ -133,17 +135,23 @@ static void GPIO_InitLimit(void)
|
|||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* GPIO Configuration: */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
||||
/* GPIO Configuration: */
|
||||
#if !defined(LATHE_MODE)
|
||||
// Y1
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
#endif
|
||||
|
||||
// X1 X2 Y2 Z2
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_5 | GPIO_Pin_6;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
// Z1
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
}
|
||||
|
|
|
@ -36,10 +36,14 @@
|
|||
#include "Settings.h"
|
||||
#include "Config.h"
|
||||
#include "MotionControl.h"
|
||||
#include "Encoder.h"
|
||||
#include "Platform.h"
|
||||
#include "TIM.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#define TIM3_RESET_VALUE 300
|
||||
#define RPM_FILTER_NUM 3
|
||||
|
||||
|
||||
/** @addtogroup Template_Project
|
||||
* @{
|
||||
|
@ -61,13 +65,11 @@ extern void System_PinChangeISR(void);
|
|||
// Counter for milliseconds
|
||||
static volatile uint32_t gMillis = 0;
|
||||
|
||||
// TIM3
|
||||
uint16_t uhIC3ReadValue1 = 0;
|
||||
uint16_t uhIC3ReadValue2 = 0;
|
||||
uint16_t uhCaptureNumber = 0;
|
||||
uint32_t uwCapture = 0;
|
||||
uint32_t uwTIM3Freq = 0;
|
||||
uint16_t TIM3_ResetCnt = TIM3_RESET_VALUE;
|
||||
uint32_t spindle_rpm = 0;
|
||||
uint16_t tim4_cnt_prev = 0;
|
||||
uint32_t rpm_arr[RPM_FILTER_NUM] = {0};
|
||||
uint8_t rpm_idx = 0;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M4 Processor Exceptions Handlers */
|
||||
|
@ -241,35 +243,76 @@ void SysTick_Handler(void)
|
|||
* enough for critical events. Debouncing pins is also implemented here.
|
||||
*/
|
||||
uint8_t limits = Limits_GetState();
|
||||
if(limits) {
|
||||
if(limits)
|
||||
{
|
||||
// X-Y-Z Limit
|
||||
if((DebounceCounterLimits == 0) && settings.system_flags & BITFLAG_ENABLE_LIMITS) {
|
||||
if((DebounceCounterLimits == 0) && (settings.system_flags & BITFLAG_ENABLE_LIMITS))
|
||||
{
|
||||
DebounceCounterLimits = 20;
|
||||
Limit_PinChangeISR();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t controls = System_GetControlState();
|
||||
if(controls) {
|
||||
if(controls)
|
||||
{
|
||||
// System control
|
||||
if(DebounceCounterControl == 0) {
|
||||
if(DebounceCounterControl == 0)
|
||||
{
|
||||
DebounceCounterControl = 20;
|
||||
System_PinChangeISR();
|
||||
}
|
||||
}
|
||||
|
||||
if(DebounceCounterLimits && !limits) {
|
||||
if(DebounceCounterLimits && !limits)
|
||||
{
|
||||
DebounceCounterLimits--;
|
||||
}
|
||||
if(DebounceCounterControl && !controls) {
|
||||
if(DebounceCounterControl && !controls)
|
||||
{
|
||||
DebounceCounterControl--;
|
||||
}
|
||||
|
||||
gMillis++;
|
||||
|
||||
if(--TIM3_ResetCnt == 0)
|
||||
if(gMillis%16 == 0)
|
||||
{
|
||||
// Update sync motion
|
||||
MC_UpdateSyncMove();
|
||||
}
|
||||
|
||||
if(gMillis%25 == 0)
|
||||
{
|
||||
uwTIM3Freq = 0;
|
||||
// 25ms Task (min 7 RPM)
|
||||
uint16_t cnt = (uint16_t)Encoder_GetValue();
|
||||
uint32_t cnt_diff = 0;
|
||||
|
||||
// Calculate ticks since last event
|
||||
if(cnt < tim4_cnt_prev)
|
||||
{
|
||||
// Ovf
|
||||
cnt_diff = (0xFFFF - tim4_cnt_prev) + cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt_diff = cnt - tim4_cnt_prev;
|
||||
}
|
||||
|
||||
// Calculate RPM and smooth it
|
||||
float rpm = ((cnt_diff * 40.0) / PULSES_PER_REV) * 60.0;
|
||||
rpm_arr[rpm_idx++] = (uint32_t)rpm;
|
||||
if(rpm_idx > (RPM_FILTER_NUM-1))
|
||||
{
|
||||
rpm_idx = 0;
|
||||
}
|
||||
|
||||
// Assign smoothed RPM
|
||||
spindle_rpm = (rpm_arr[0] + rpm_arr[1] + rpm_arr[2]) / RPM_FILTER_NUM;
|
||||
|
||||
tim4_cnt_prev = cnt;
|
||||
|
||||
// Update sync motion
|
||||
//MC_UpdateSyncMove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,13 +332,15 @@ void SysTick_Handler(void)
|
|||
void TIM1_BRK_TIM9_IRQHandler(void)
|
||||
{
|
||||
/* TIM9_CH1 */
|
||||
if(TIM_GetITStatus(TIM9, TIM_IT_CC1) != RESET) {
|
||||
if(TIM_GetITStatus(TIM9, TIM_IT_CC1) != RESET)
|
||||
{
|
||||
// OC
|
||||
Stepper_MainISR();
|
||||
|
||||
TIM_ClearITPendingBit(TIM9, TIM_IT_CC1);
|
||||
}
|
||||
else if(TIM_GetITStatus(TIM9, TIM_IT_Update) != RESET) {
|
||||
else if(TIM_GetITStatus(TIM9, TIM_IT_Update) != RESET)
|
||||
{
|
||||
// OVF
|
||||
Stepper_PortResetISR();
|
||||
|
||||
|
@ -310,41 +355,28 @@ void TIM3_IRQHandler(void)
|
|||
{
|
||||
/* Clear TIM3 Capture compare interrupt pending bit */
|
||||
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
|
||||
if(uhCaptureNumber == 0)
|
||||
{
|
||||
/* Get the Input Capture value */
|
||||
uhIC3ReadValue1 = TIM_GetCapture4(TIM3);
|
||||
uhCaptureNumber = 1;
|
||||
}
|
||||
else if(uhCaptureNumber == 1)
|
||||
{
|
||||
/* Get the Input Capture value */
|
||||
uhIC3ReadValue2 = TIM_GetCapture4(TIM3);
|
||||
|
||||
/* Capture computation */
|
||||
if (uhIC3ReadValue2 > uhIC3ReadValue1)
|
||||
{
|
||||
uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1);
|
||||
}
|
||||
else if (uhIC3ReadValue2 < uhIC3ReadValue1)
|
||||
{
|
||||
uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2);
|
||||
}
|
||||
else
|
||||
{
|
||||
uwCapture = 0;
|
||||
}
|
||||
|
||||
/* Frequency computation */
|
||||
uwTIM3Freq = (uint32_t) SystemCoreClock / uwCapture;
|
||||
uhCaptureNumber = 0;
|
||||
}
|
||||
|
||||
TIM3_ResetCnt = TIM3_RESET_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TIM4_IRQHandler(void)
|
||||
{
|
||||
if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
|
||||
{
|
||||
// OVF
|
||||
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
|
||||
|
||||
Encoder_OvfISR();
|
||||
|
||||
// Spindle at zero position
|
||||
if(sys.sync_move && sys.state == STATE_HOLD)
|
||||
{
|
||||
MC_LineSyncStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function handles External lines 9 to 5 interrupt request.
|
||||
* @param None
|
||||
|
|
|
@ -121,6 +121,7 @@ void TIM3_Init(void)
|
|||
TIM_ICInit(TIM3, &TIM_ICInitStructure);
|
||||
|
||||
/* Enable the CC2 Interrupt Request */
|
||||
TIM_ClearFlag(TIM3, TIM_FLAG_CC4);
|
||||
TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);
|
||||
|
||||
/* TIM enable counter */
|
||||
|
@ -128,6 +129,66 @@ void TIM3_Init(void)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Timer 4
|
||||
* Used for Encoder
|
||||
**/
|
||||
void TIM4_Init(uint16_t autoreload)
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_ICInitTypeDef TIM_ICInitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
|
||||
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);
|
||||
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = 0x03;
|
||||
TIM_TimeBaseStructure.TIM_Period = autoreload-1; // Set counter auto reload value
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // Select clock division: no division
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM counts up
|
||||
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
|
||||
|
||||
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI1, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
|
||||
TIM_ICStructInit(&TIM_ICInitStructure);
|
||||
TIM_ICInitStructure.TIM_ICFilter = 8;
|
||||
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
|
||||
TIM_ICInit(TIM4, &TIM_ICInitStructure);
|
||||
|
||||
/* Enable the TIM4 global Interrupt */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
|
||||
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
|
||||
|
||||
//Reset counter
|
||||
TIM_SetCounter(TIM4, 0);
|
||||
TIM_Cmd(TIM4, ENABLE);
|
||||
}
|
||||
|
||||
|
||||
inline uint16_t TIM4_CNT(void)
|
||||
{
|
||||
return TIM4->CNT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Timer 9
|
||||
* Base clock: 24 MHz
|
||||
|
|
|
@ -30,8 +30,11 @@ extern "C" {
|
|||
void TIM1_Init(void);
|
||||
void TIM2_Init(void);
|
||||
void TIM3_Init(void);
|
||||
void TIM4_Init(uint16_t autoreload);
|
||||
void TIM9_Init(void);
|
||||
|
||||
uint16_t TIM4_CNT(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Encoder.c - Encoder
|
||||
Part of Grbl-Advanced
|
||||
|
||||
Copyright (c) 2021 Patrick F.
|
||||
|
||||
Grbl-Advanced 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-Advanced 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-Advanced. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "Encoder.h"
|
||||
#include "TIM.h"
|
||||
|
||||
|
||||
static uint32_t OvfCnt = 0;
|
||||
static uint32_t CntValue = 0;
|
||||
|
||||
|
||||
void Encoder_Init(void)
|
||||
{
|
||||
TIM4_Init(PULSES_PER_REV);
|
||||
Encoder_Reset();
|
||||
}
|
||||
|
||||
|
||||
void Encoder_Reset(void)
|
||||
{
|
||||
OvfCnt = 0;
|
||||
CntValue = 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t Encoder_GetValue(void)
|
||||
{
|
||||
return CntValue + TIM4_CNT();
|
||||
}
|
||||
|
||||
|
||||
void Encoder_SetValue(uint32_t val)
|
||||
{
|
||||
CntValue = val - TIM4_CNT();
|
||||
}
|
||||
|
||||
|
||||
void Encoder_OvfISR(void)
|
||||
{
|
||||
OvfCnt++;
|
||||
CntValue += PULSES_PER_REV;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef ENCODER_H_INCLUDED
|
||||
#define ENCODER_H_INCLUDED
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define PULSES_PER_REV 360
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void Encoder_Init(void);
|
||||
void Encoder_Reset(void);
|
||||
|
||||
uint32_t Encoder_GetValue(void);
|
||||
void Encoder_SetValue(uint32_t val);
|
||||
|
||||
void Encoder_OvfISR(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* ENCODER_H_INCLUDED */
|
|
@ -6,7 +6,6 @@
|
|||
#include "Config.h"
|
||||
#include "Usart.h"
|
||||
#include "FIFO_USART.h"
|
||||
#include "Settings.h"
|
||||
#include "GrIP.h"
|
||||
#include "Platform.h"
|
||||
|
||||
|
@ -18,7 +17,7 @@ static char buf[512] = {0};
|
|||
static uint16_t buf_idx = 0;
|
||||
|
||||
|
||||
void Print_Init(void)
|
||||
void Printf_Init(void)
|
||||
{
|
||||
Usart_Init(STDOUT, BAUD_RATE);
|
||||
}
|
||||
|
@ -72,7 +71,7 @@ int Putc(const char c)
|
|||
}
|
||||
|
||||
|
||||
void Print_Flush(void)
|
||||
void Printf_Flush(void)
|
||||
{
|
||||
if(buf_idx == 0)
|
||||
{
|
||||
|
@ -100,9 +99,7 @@ void Print_Flush(void)
|
|||
// Convert float to string by immediately converting to a long integer, which contains
|
||||
// more digits than a float. Number of decimal places, which are tracked by a counter,
|
||||
// may be set by the user. The integer is then efficiently converted to a string.
|
||||
// NOTE: AVR '%' and '/' integer operations are very efficient. Bitshifting speed-up
|
||||
// techniques are actually just slightly slower. Found this out the hard way.
|
||||
void PrintFloat(float n, uint8_t decimal_places)
|
||||
void Printf_Float(float n, uint8_t decimal_places)
|
||||
{
|
||||
if(n < 0)
|
||||
{
|
||||
|
@ -155,33 +152,3 @@ void PrintFloat(float n, uint8_t decimal_places)
|
|||
Putc(buf[i-1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Floating value printing handlers for special variables types used in Grbl and are defined
|
||||
// in the config.h.
|
||||
// - CoordValue: Handles all position or coordinate values in inches or mm reporting.
|
||||
// - RateValue: Handles feed rate and current velocity in inches or mm reporting.
|
||||
void PrintFloat_CoordValue(float n)
|
||||
{
|
||||
if(BIT_IS_TRUE(settings.flags, BITFLAG_REPORT_INCHES))
|
||||
{
|
||||
PrintFloat(n*INCH_PER_MM,N_DECIMAL_COORDVALUE_INCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintFloat(n, N_DECIMAL_COORDVALUE_MM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PrintFloat_RateValue(float n)
|
||||
{
|
||||
if(BIT_IS_TRUE(settings.flags, BITFLAG_REPORT_INCHES))
|
||||
{
|
||||
PrintFloat(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintFloat(n, N_DECIMAL_RATEVALUE_MM);
|
||||
}
|
||||
}
|
|
@ -10,16 +10,13 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
|
||||
void Print_Init(void);
|
||||
void Printf_Init(void);
|
||||
int Printf(const char *str, ...);
|
||||
void PrintFloat(float n, uint8_t decimal_places);
|
||||
void Printf_Float(float n, uint8_t decimal_places);
|
||||
int8_t Getc(char *c);
|
||||
int Putc(const char c);
|
||||
|
||||
void Print_Flush(void);
|
||||
|
||||
void PrintFloat_CoordValue(float n);
|
||||
void PrintFloat_RateValue(float n);
|
||||
void Printf_Flush(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
9
Makefile
9
Makefile
|
@ -10,7 +10,7 @@
|
|||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
# Location of gcc-arm-none-eabi toolchain
|
||||
GCC_BASE = /opt/gcc-arm-none-eabi-8-2018-q4-major/bin
|
||||
GCC_BASE = /opt/gcc-arm-none-eabi-9-2020-q2-update/bin
|
||||
|
||||
CC = ${GCC_BASE}/arm-none-eabi-gcc
|
||||
CXX = ${GCC_BASE}/arm-none-eabi-g++
|
||||
|
@ -26,7 +26,9 @@ OBJDUMP = ${GCC_BASE}/arm-none-eabi-objdump
|
|||
#---------------------------------------------------------------------------------
|
||||
TARGET := GRBL_Advanced
|
||||
BUILD := build
|
||||
SOURCES := ./ ARM/cmsis/ grbl/ HAL/ HAL/EXTI HAL/FLASH HAL/GPIO HAL/I2C HAL/SPI HAL/STM32 HAL/TIM HAL/USART ARM/SPL/src Src/ Libraries/GrIP Libraries/CRC Libraries/Ethernet Libraries/Ethernet/utility
|
||||
SOURCES := ./ ARM/cmsis/ grbl/ HAL/ HAL/EXTI HAL/FLASH HAL/GPIO HAL/I2C HAL/SPI HAL/STM32 \
|
||||
HAL/TIM HAL/USART ARM/SPL/src Src/ Libraries/GrIP Libraries/CRC Libraries/Ethernet \
|
||||
Libraries/Ethernet/utility Libraries/Encoder Libraries/EEPROM Libraries/Printf
|
||||
|
||||
INCLUDES := $(SOURCES) ARM/SPL/inc
|
||||
|
||||
|
@ -40,7 +42,8 @@ DEFINES = -DSTM32F411xE -DSTM32F411RE
|
|||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
FLAGS := -mfloat-abi=hard -mcpu=cortex-m4 -gdwarf-2 -mfpu=fpv4-sp-d16 -mthumb -Wno-misleading-indentation
|
||||
CFLAGS := -O2 -g1 -std=c11 -Wall -Wextra $(INCLUDE) -fno-common -fsingle-precision-constant -fdata-sections -ffunction-sections -fomit-frame-pointer -mlittle-endian -DUSE_STDPERIPH_DRIVER -D__FPU_USED -DARM_MATH_CM4 -Wimplicit-fallthrough=0
|
||||
CFLAGS := -O2 -g1 -std=c11 -Wall -Wextra $(INCLUDE) -fno-common -fsingle-precision-constant -fdata-sections \
|
||||
-ffunction-sections -fomit-frame-pointer -mlittle-endian -DUSE_STDPERIPH_DRIVER -D__FPU_USED -DARM_MATH_CM4 -Wimplicit-fallthrough=0
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
|
||||
LDFLAGS := -lm -flto -Wl,--gc-sections -Wl,-M=$(OUTPUT).map --specs=nosys.specs -nostartfiles --specs=nano.specs -u _scanf_float
|
||||
|
|
|
@ -100,7 +100,7 @@ make all flash
|
|||
```
|
||||
List of Supported G-Codes in Grbl-Advanced:
|
||||
- Non-Modal Commands: G4, G10L2, G10L20, G28, G30, G28.1, G30.1, G53, G92, G92.1
|
||||
- Motion Modes: G0, G1, G2, G3, G38.2, G38.3, G38.4, G38.5, G80
|
||||
- Motion Modes: G0, G1, G2, G3, G33, G38.2, G38.3, G38.4, G38.5, G76 G80
|
||||
- Canned Cycles: G81, G82, G83
|
||||
- Feed Rate Modes: G93, G94
|
||||
- Unit Modes: G20, G21
|
||||
|
@ -108,12 +108,14 @@ List of Supported G-Codes in Grbl-Advanced:
|
|||
- Retract Modes: G98, G99
|
||||
- Arc IJK Distance Modes: G91.1
|
||||
- Plane Select Modes: G17, G18, G19
|
||||
- Tool Length Offset Modes: G43.1, G49
|
||||
- Tool Length Offset Modes: G43, G43.1, G49
|
||||
- Cutter Compensation Modes: G40
|
||||
- Coordinate System Modes: G54, G55, G56, G57, G58, G59
|
||||
- Control Modes: G61
|
||||
- Lathe Modes: G7, G8
|
||||
- Spindle Speed Mode: G96, G97
|
||||
- Program Flow: M0, M1, M2, M30*
|
||||
- Coolant Control: M7*, M8, M9
|
||||
- Spindle Control: M3, M4, M5
|
||||
- Valid Non-Command Words: F, I, J, K, L, N, P, R, S, T, X, Y, Z
|
||||
- Valid Non-Command Words: A, B, D, E, F, H, I, J, K, L, N, P, Q, R, S, T, X, Y, Z
|
||||
```
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
#include "PID.h"
|
||||
#include "System32.h"
|
||||
|
||||
#define TICK_SECOND 1000
|
||||
|
||||
|
||||
extern uint32_t millis(void);
|
||||
|
||||
|
||||
PID_t *PID_Create(PID_t *pid, float* in, float* out, float* set, float kp, float ki, float kd)
|
||||
{
|
||||
pid->input = in;
|
||||
pid->output = out;
|
||||
pid->setpoint = set;
|
||||
pid->automode = false;
|
||||
|
||||
PID_Limits(pid, -255, 255);
|
||||
|
||||
// Set default sample time to 25 ms
|
||||
pid->sampletime = 16 * (TICK_SECOND / 1000);
|
||||
|
||||
PID_Direction(pid, E_PID_DIRECT);
|
||||
PID_Tune(pid, kp, ki, kd);
|
||||
|
||||
pid->lasttime = millis() - pid->sampletime;
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
||||
void PID_Compute(PID_t *pid)
|
||||
{
|
||||
// Check if control is enabled
|
||||
if (!pid->automode)
|
||||
return;
|
||||
|
||||
float in = *(pid->input);
|
||||
|
||||
// Compute error
|
||||
float error = (*(pid->setpoint)) - in;
|
||||
|
||||
// Compute integral
|
||||
pid->iterm += (pid->Ki * error);
|
||||
if (pid->iterm > pid->omax)
|
||||
pid->iterm = pid->omax;
|
||||
else if (pid->iterm < pid->omin)
|
||||
pid->iterm = pid->omin;
|
||||
|
||||
// Compute differential on input
|
||||
float dinput = in - pid->lastin;
|
||||
|
||||
// Compute PID output
|
||||
float out = pid->Kp * error + pid->iterm - pid->Kd * dinput;
|
||||
|
||||
// Apply limit to output value
|
||||
if (out > pid->omax)
|
||||
out = pid->omax;
|
||||
else if (out < pid->omin)
|
||||
out = pid->omin;
|
||||
|
||||
// Output to pointed variable
|
||||
(*pid->output) = out;
|
||||
|
||||
// Keep track of some variables for next execution
|
||||
pid->lastin = in;
|
||||
pid->lasttime = millis();;
|
||||
}
|
||||
|
||||
|
||||
void PID_Tune(PID_t *pid, float kp, float ki, float kd)
|
||||
{
|
||||
// Check for validity
|
||||
if (kp < 0 || ki < 0 || kd < 0)
|
||||
return;
|
||||
|
||||
//Compute sample time in seconds
|
||||
float ssec = ((float) pid->sampletime) / ((float) TICK_SECOND);
|
||||
|
||||
pid->Kp = kp;
|
||||
pid->Ki = ki * ssec;
|
||||
pid->Kd = kd / ssec;
|
||||
|
||||
if (pid->direction == E_PID_REVERSE)
|
||||
{
|
||||
pid->Kp = 0 - pid->Kp;
|
||||
pid->Ki = 0 - pid->Ki;
|
||||
pid->Kd = 0 - pid->Kd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PID_SampleTime(PID_t *pid, uint32_t time)
|
||||
{
|
||||
if (time > 0)
|
||||
{
|
||||
float ratio = (float) (time * (TICK_SECOND / 1000)) / (float) pid->sampletime;
|
||||
pid->Ki *= ratio;
|
||||
pid->Kd /= ratio;
|
||||
pid->sampletime = time * (TICK_SECOND / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PID_Limits(PID_t *pid, float min, float max)
|
||||
{
|
||||
if (min >= max)
|
||||
return;
|
||||
|
||||
pid->omin = min;
|
||||
pid->omax = max;
|
||||
|
||||
//Adjust output to new limits
|
||||
if (pid->automode)
|
||||
{
|
||||
if (*(pid->output) > pid->omax)
|
||||
*(pid->output) = pid->omax;
|
||||
else if (*(pid->output) < pid->omin)
|
||||
*(pid->output) = pid->omin;
|
||||
|
||||
if (pid->iterm > pid->omax)
|
||||
pid->iterm = pid->omax;
|
||||
else if (pid->iterm < pid->omin)
|
||||
pid->iterm = pid->omin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PID_EnableAuto(PID_t *pid)
|
||||
{
|
||||
// If going from manual to auto
|
||||
if (!pid->automode)
|
||||
{
|
||||
pid->iterm = *(pid->output);
|
||||
pid->lastin = *(pid->input);
|
||||
|
||||
if (pid->iterm > pid->omax)
|
||||
pid->iterm = pid->omax;
|
||||
else if (pid->iterm < pid->omin)
|
||||
pid->iterm = pid->omin;
|
||||
|
||||
pid->automode = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PID_Manual(PID_t *pid)
|
||||
{
|
||||
pid->automode = false;
|
||||
}
|
||||
|
||||
|
||||
void PID_Direction(PID_t *pid, enum pid_control_directions dir)
|
||||
{
|
||||
if (pid->automode && pid->direction != dir)
|
||||
{
|
||||
pid->Kp = (0 - pid->Kp);
|
||||
pid->Ki = (0 - pid->Ki);
|
||||
pid->Kd = (0 - pid->Kd);
|
||||
}
|
||||
pid->direction = dir;
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
// Original implementation: https://github.com/geekfactory/PID
|
||||
#ifndef PID_H_INCLUDED
|
||||
#define PID_H_INCLUDED
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* Defines if the controler is direct or reverse
|
||||
*/
|
||||
enum pid_control_directions
|
||||
{
|
||||
E_PID_DIRECT,
|
||||
E_PID_REVERSE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure that holds PID all the PID controller data, multiple instances are
|
||||
* posible using different structures for each controller
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
// Input, output and setpoint
|
||||
float *input; //!< Current Process Value
|
||||
float *output; //!< Corrective Output from PID Controller
|
||||
float *setpoint; //!< Controller Setpoint
|
||||
|
||||
// Tuning parameters
|
||||
float Kp; //!< Stores the gain for the Proportional term
|
||||
float Ki; //!< Stores the gain for the Integral term
|
||||
float Kd; //!< Stores the gain for the Derivative term
|
||||
|
||||
// Output minimum and maximum values
|
||||
float omin; //!< Maximum value allowed at the output
|
||||
float omax; //!< Minimum value allowed at the output
|
||||
|
||||
// Variables for PID algorithm
|
||||
float iterm; //!< Accumulator for integral term
|
||||
float lastin; //!< Last input value for differential term
|
||||
|
||||
// Time related
|
||||
uint32_t lasttime; //!< Stores the time when the control loop ran last time
|
||||
uint32_t sampletime; //!< Defines the PID sample time
|
||||
|
||||
// Operation mode
|
||||
uint8_t automode; //!< Defines if the PID controller is enabled or disabled
|
||||
enum pid_control_directions direction;
|
||||
} PID_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new PID controller
|
||||
*
|
||||
* Creates a new pid controller and initializes it<EFBFBD>s input, output and internal
|
||||
* variables. Also we set the tuning parameters
|
||||
*
|
||||
* @param pid A pointer to a pid_controller structure
|
||||
* @param in Pointer to float value for the process input
|
||||
* @param out Poiter to put the controller output value
|
||||
* @param set Pointer float with the process setpoint value
|
||||
* @param kp Proportional gain
|
||||
* @param ki Integral gain
|
||||
* @param kd Diferential gain
|
||||
*
|
||||
* @return returns a pid_t controller handle
|
||||
*/
|
||||
PID_t *PID_Create(PID_t *pid, float* in, float* out, float* set, float kp, float ki, float kd);
|
||||
|
||||
/**
|
||||
* @brief Computes the output of the PID control
|
||||
*
|
||||
* This function computes the PID output based on the parameters, setpoint and
|
||||
* current system input.
|
||||
*
|
||||
* @param pid The PID controller instance which will be used for computation
|
||||
*/
|
||||
void PID_Compute(PID_t *pid);
|
||||
|
||||
/**
|
||||
* @brief Sets new PID tuning parameters
|
||||
*
|
||||
* Sets the gain for the Proportional (Kp), Integral (Ki) and Derivative (Kd)
|
||||
* terms.
|
||||
*
|
||||
* @param pid The PID controller instance to modify
|
||||
* @param kp Proportional gain
|
||||
* @param ki Integral gain
|
||||
* @param kd Derivative gain
|
||||
*/
|
||||
void PID_Tune(PID_t *pid, float kp, float ki, float kd);
|
||||
|
||||
/**
|
||||
* @brief Sets the pid algorithm period
|
||||
*
|
||||
* Changes the between PID control loop computations.
|
||||
*
|
||||
* @param pid The PID controller instance to modify
|
||||
* @param time The time in milliseconds between computations
|
||||
*/
|
||||
void PID_SampleTime(PID_t *pid, uint32_t time);
|
||||
|
||||
/**
|
||||
* @brief Sets the limits for the PID controller output
|
||||
*
|
||||
* @param pid The PID controller instance to modify
|
||||
* @param min The minimum output value for the PID controller
|
||||
* @param max The maximum output value for the PID controller
|
||||
*/
|
||||
void PID_Limits(PID_t *pid, float min, float max);
|
||||
|
||||
/**
|
||||
* @brief Enables automatic control using PID
|
||||
*
|
||||
* Enables the PID control loop. If manual output adjustment is needed you can
|
||||
* disable the PID control loop using pid_manual(). This function enables PID
|
||||
* automatic control at program start or after calling pid_manual()
|
||||
*
|
||||
* @param pid The PID controller instance to enable
|
||||
*/
|
||||
void PID_EnableAuto(PID_t *pid);
|
||||
|
||||
/**
|
||||
* @brief Disables automatic process control
|
||||
*
|
||||
* Disables the PID control loop. User can modify the value of the output
|
||||
* variable and the controller will not overwrite it.
|
||||
*
|
||||
* @param pid The PID controller instance to disable
|
||||
*/
|
||||
void PID_Manual(PID_t *pid);
|
||||
|
||||
/**
|
||||
* @brief Configures the PID controller direction
|
||||
*
|
||||
* Sets the direction of the PID controller. The direction is "DIRECT" when a
|
||||
* increase of the output will cause a increase on the measured value and
|
||||
* "REVERSE" when a increase on the controller output will cause a decrease on
|
||||
* the measured value.
|
||||
*
|
||||
* @param pid The PID controller instance to modify
|
||||
* @param direction The new direction of the PID controller
|
||||
*/
|
||||
void PID_Direction(PID_t *pid, enum pid_control_directions dir);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PID_H_INCLUDED */
|
|
@ -49,6 +49,9 @@
|
|||
// Uncomment to use 4th/5th axis
|
||||
//#define USE_MULTI_AXIS
|
||||
|
||||
// Uncomment for lathe mode
|
||||
//#define LATHE_MODE
|
||||
|
||||
|
||||
// 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
|
||||
|
@ -293,10 +296,10 @@
|
|||
// refreshes more often when its not doing anything important. With a good GUI, this data doesn't need
|
||||
// to be refreshed very often, on the order of a several seconds.
|
||||
// NOTE: WCO refresh must be 2 or greater. OVR refresh must be 1 or greater.
|
||||
#define REPORT_OVR_REFRESH_BUSY_COUNT 20 // (1-255)
|
||||
#define REPORT_OVR_REFRESH_IDLE_COUNT 10 // (1-255) Must be less than or equal to the busy count
|
||||
#define REPORT_WCO_REFRESH_BUSY_COUNT 30 // (2-255)
|
||||
#define REPORT_WCO_REFRESH_IDLE_COUNT 10 // (2-255) Must be less than or equal to the busy count
|
||||
#define REPORT_OVR_REFRESH_BUSY_COUNT 15 // (1-255)
|
||||
#define REPORT_OVR_REFRESH_IDLE_COUNT 8 // (1-255) Must be less than or equal to the busy count
|
||||
#define REPORT_WCO_REFRESH_BUSY_COUNT 15 // (2-255)
|
||||
#define REPORT_WCO_REFRESH_IDLE_COUNT 8 // (2-255) Must be less than or equal to the busy count
|
||||
|
||||
|
||||
// The temporal resolution of the acceleration management subsystem. A higher number gives smoother
|
||||
|
|
380
grbl/GCode.c
380
grbl/GCode.c
|
@ -30,6 +30,7 @@
|
|||
#include "CoolantControl.h"
|
||||
#include "MotionControl.h"
|
||||
#include "Protocol.h"
|
||||
#include "SpindleControl.h"
|
||||
#include "util.h"
|
||||
#include "ToolChange.h"
|
||||
#include "GCode.h"
|
||||
|
@ -133,10 +134,10 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
uint8_t char_counter = 0;
|
||||
char letter = 0;
|
||||
float value = 0.0;
|
||||
uint8_t int_value = 0;
|
||||
uint16_t int_value = 0;
|
||||
uint16_t mantissa = 0;
|
||||
float old_xyz[N_AXIS] = {0.0};
|
||||
uint8_t change_tool = 0;
|
||||
uint8_t change_tool = 0, update_tooltable = 0;
|
||||
|
||||
memcpy(old_xyz, gc_state.position, N_AXIS*sizeof(float));
|
||||
|
||||
|
@ -279,7 +280,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
if(settings.flags2 & BITFLAG_LATHE_MODE)
|
||||
{
|
||||
word_bit = MODAL_GROUP_G14;
|
||||
gc_state.modal.spindle_mode = SPINDLE_SURFACE_MODE;
|
||||
gc_block.modal.spindle_mode = SPINDLE_SURFACE_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -292,7 +293,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
if(settings.flags2 & BITFLAG_LATHE_MODE)
|
||||
{
|
||||
word_bit = MODAL_GROUP_G14;
|
||||
gc_state.modal.spindle_mode = SPINDLE_RPM_MODE;
|
||||
gc_block.modal.spindle_mode = SPINDLE_RPM_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -413,6 +414,11 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
{
|
||||
gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
|
||||
}
|
||||
else if(mantissa < 0.001) // G43
|
||||
{
|
||||
update_tooltable = 1;
|
||||
gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// [Unsupported G43.x command]
|
||||
|
@ -582,7 +588,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
axis_words |= (1<<B_AXIS);
|
||||
break;
|
||||
#endif
|
||||
// case 'C': // Not supported
|
||||
// case 'C': // Not supported
|
||||
case 'D':
|
||||
word_bit = WORD_D;
|
||||
gc_block.values.d = int_value;
|
||||
|
@ -826,7 +832,19 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
// [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value.
|
||||
// bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking.
|
||||
|
||||
// [6. Change tool ]: N/A
|
||||
// [6. Change tool ]:
|
||||
if(update_tooltable == 1)
|
||||
{
|
||||
if(BIT_IS_TRUE(value_words, BIT(WORD_H)))
|
||||
{
|
||||
if(gc_block.values.h >= MAX_TOOL_NR)
|
||||
{
|
||||
return STATUS_GCODE_MAX_VALUE_EXCEEDED;
|
||||
}
|
||||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_H));
|
||||
}
|
||||
|
||||
// [7. Spindle control ]:
|
||||
if(BIT_IS_TRUE(command_words, BIT(MODAL_GROUP_G14)) && (gc_block.modal.motion == SPINDLE_SURFACE_MODE))
|
||||
{
|
||||
|
@ -844,6 +862,11 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
return STATUS_INVALID_STATEMENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset spindle limit if not specified (optional)
|
||||
gc_block.values.d = 0;
|
||||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_D));
|
||||
}
|
||||
|
||||
|
@ -954,7 +977,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
// NOTE: Although not explicitly stated so, G43.1 should be applied to only one valid
|
||||
// axis that is configured (in config.h). There should be an error if the configured axis
|
||||
// is absent or if any of the other axis words are present.
|
||||
if(axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) // Indicates called in block.
|
||||
if((axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET) && (update_tooltable == 0)) // Indicates called in block.
|
||||
{
|
||||
if(gc_block.modal.tool_length == TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC)
|
||||
{
|
||||
|
@ -1071,9 +1094,9 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
// L20: Update coordinate system axis at current position (with modifiers) with programmed value
|
||||
// WPos = MPos - WCS - G92 - TLO -> WCS = MPos - G92 - TLO - WPos
|
||||
gc_block.values.ijk[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx];
|
||||
if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
//if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
{
|
||||
gc_block.values.ijk[idx] -= gc_state.tool_length_offset;
|
||||
gc_block.values.ijk[idx] -= gc_state.tool_length_offset[idx];
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1101,9 +1124,9 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
{
|
||||
// WPos = MPos - WCS - G92 - TLO -> G92 = MPos - WCS - TLO - WPos
|
||||
gc_block.values.xyz[idx] = gc_state.position[idx] - block_coord_system[idx] - gc_block.values.xyz[idx];
|
||||
if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
//if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
{
|
||||
gc_block.values.xyz[idx] -= gc_state.tool_length_offset;
|
||||
gc_block.values.xyz[idx] -= gc_state.tool_length_offset[idx];
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1138,9 +1161,9 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
if(gc_block.modal.distance == DISTANCE_MODE_ABSOLUTE)
|
||||
{
|
||||
gc_block.values.xyz[idx] += block_coord_system[idx] + gc_state.coord_offset[idx];
|
||||
if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
//if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
{
|
||||
gc_block.values.xyz[idx] += gc_state.tool_length_offset;
|
||||
gc_block.values.xyz[idx] += gc_state.tool_length_offset[idx];
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1240,9 +1263,79 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
axis_command = AXIS_COMMAND_NONE;
|
||||
}
|
||||
|
||||
// All remaining motion modes (all but G0 and G80), require a valid feed rate value. In units per mm mode,
|
||||
// All remaining motion modes (all but G0, G80, G33 and G76), require a valid feed rate value. In units per mm mode,
|
||||
// the value must be positive. In inverse time mode, a positive value must be passed with each block.
|
||||
}
|
||||
else if((gc_block.modal.motion == MOTION_MODE_SPINDLE_SYNC) || (gc_block.modal.motion == MOTION_MODE_THREADING))
|
||||
{
|
||||
switch(gc_block.modal.motion)
|
||||
{
|
||||
case MOTION_MODE_SPINDLE_SYNC:
|
||||
if(BIT_IS_FALSE(value_words, BIT(WORD_K)))
|
||||
{
|
||||
// [K word missing]
|
||||
return STATUS_GCODE_VALUE_WORD_MISSING;
|
||||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_K));
|
||||
|
||||
if(BIT_IS_FALSE(value_words, (BIT(WORD_X) | BIT(WORD_Y) | BIT(WORD_Z))))
|
||||
{
|
||||
// [axis word missing]
|
||||
return STATUS_GCODE_NO_AXIS_WORDS;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MOTION_MODE_THREADING:
|
||||
if(BIT_IS_FALSE(value_words, BIT(WORD_P)))
|
||||
{
|
||||
// [P word missing]
|
||||
return STATUS_GCODE_VALUE_WORD_MISSING;
|
||||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_P));
|
||||
|
||||
if(BIT_IS_FALSE(value_words, BIT(WORD_Z)))
|
||||
{
|
||||
// [axis word missing]
|
||||
return STATUS_GCODE_NO_AXIS_WORDS;
|
||||
}
|
||||
|
||||
if(BIT_IS_FALSE(value_words, (BIT(WORD_I) | BIT(WORD_J) | BIT(WORD_K))))
|
||||
{
|
||||
// [IJK word missing]
|
||||
return STATUS_GCODE_VALUE_WORD_MISSING;
|
||||
}
|
||||
BIT_FALSE(value_words, (BIT(WORD_I) | BIT(WORD_J) | BIT(WORD_K)));
|
||||
|
||||
// [Optional]
|
||||
if(BIT_IS_TRUE(value_words, BIT(WORD_R)))
|
||||
{
|
||||
if(gc_block.values.r < 1.0)
|
||||
{
|
||||
return STATUS_BAD_NUMBER_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
if(BIT_IS_TRUE(value_words, BIT(WORD_L)))
|
||||
{
|
||||
if(gc_block.values.l > 3)
|
||||
{
|
||||
return STATUS_BAD_NUMBER_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
if(BIT_IS_TRUE(value_words, BIT(WORD_Q)))
|
||||
{
|
||||
if(gc_block.values.q < 0.0 || gc_block.values.q > 80)
|
||||
{
|
||||
return STATUS_BAD_NUMBER_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
BIT_FALSE(value_words, (BIT(WORD_R) | BIT(WORD_Q) | BIT(WORD_H) | BIT(WORD_E) | BIT(WORD_L)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if feed rate is defined for the motion modes that require it.
|
||||
|
@ -1484,63 +1577,6 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_L));
|
||||
break;
|
||||
|
||||
case MOTION_MODE_SPINDLE_SYNC:
|
||||
if(BIT_IS_FALSE(value_words, BIT(WORD_K)))
|
||||
{
|
||||
// [K word missing]
|
||||
return STATUS_GCODE_VALUE_WORD_MISSING;
|
||||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_K));
|
||||
|
||||
if(BIT_IS_FALSE(value_words, (BIT(WORD_X) | BIT(WORD_Y) | BIT(WORD_Z))))
|
||||
{
|
||||
// [axis word missing]
|
||||
return STATUS_GCODE_NO_AXIS_WORDS;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MOTION_MODE_THREADING:
|
||||
if(BIT_IS_FALSE(value_words, BIT(WORD_P)))
|
||||
{
|
||||
// [P word missing]
|
||||
return STATUS_GCODE_VALUE_WORD_MISSING;
|
||||
}
|
||||
BIT_FALSE(value_words, BIT(WORD_P));
|
||||
|
||||
if(BIT_IS_FALSE(value_words, BIT(WORD_Z)))
|
||||
{
|
||||
// [axis word missing]
|
||||
return STATUS_GCODE_NO_AXIS_WORDS;
|
||||
}
|
||||
|
||||
if(BIT_IS_FALSE(value_words, (BIT(WORD_I) | BIT(WORD_J) | BIT(WORD_K))))
|
||||
{
|
||||
// [IJK word missing]
|
||||
return STATUS_GCODE_VALUE_WORD_MISSING;
|
||||
}
|
||||
BIT_FALSE(value_words, (BIT(WORD_I) | BIT(WORD_J) | BIT(WORD_K)));
|
||||
|
||||
// [Optional]
|
||||
if(BIT_IS_TRUE(value_words, BIT(WORD_R)))
|
||||
{
|
||||
if(gc_block.values.r < 1.0)
|
||||
{
|
||||
return STATUS_BAD_NUMBER_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
if(BIT_IS_TRUE(value_words, BIT(WORD_L)))
|
||||
{
|
||||
if(gc_block.values.l > 3)
|
||||
{
|
||||
return STATUS_BAD_NUMBER_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
BIT_FALSE(value_words, (BIT(WORD_R) | BIT(WORD_Q) | BIT(WORD_H) | BIT(WORD_E) | BIT(WORD_L)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1584,7 +1620,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
|
||||
if((settings.flags2 & BITFLAG_LATHE_MODE) && gc_block.modal.lathe_mode == LATHE_DIAMETER_MODE)
|
||||
{
|
||||
gc_block.values.xyz[X_AXIS] /= 2;
|
||||
gc_block.values.xyz[X_AXIS] /= 2.0;
|
||||
}
|
||||
|
||||
// Intercept jog commands and complete error checking for valid jog commands and execute.
|
||||
|
@ -1678,7 +1714,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use.
|
||||
|
||||
// [4. Set spindle speed ]:
|
||||
if((gc_state.spindle_speed != gc_block.values.s) || BIT_IS_TRUE(gc_parser_flags,GC_PARSER_LASER_FORCE_SYNC))
|
||||
if((gc_block.modal.spindle_mode == SPINDLE_RPM_MODE) && ((gc_state.spindle_speed != gc_block.values.s) || BIT_IS_TRUE(gc_parser_flags,GC_PARSER_LASER_FORCE_SYNC)))
|
||||
{
|
||||
if(gc_state.modal.spindle != SPINDLE_DISABLE)
|
||||
{
|
||||
|
@ -1696,6 +1732,19 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
}
|
||||
|
||||
gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state.
|
||||
gc_state.modal.spindle_mode = SPINDLE_RPM_MODE;
|
||||
gc_state.spindle_limit = 0;
|
||||
}
|
||||
else if(gc_block.modal.spindle_mode == SPINDLE_SURFACE_MODE)
|
||||
{
|
||||
// Set spindle max rpm for G96
|
||||
gc_state.spindle_limit = gc_block.values.d;
|
||||
|
||||
// Set surface speed
|
||||
gc_state.spindle_speed = gc_block.values.s;
|
||||
|
||||
// Set mode
|
||||
gc_state.modal.spindle_mode = SPINDLE_SURFACE_MODE;
|
||||
}
|
||||
|
||||
// NOTE: Pass zero spindle speed for all restricted laser motions.
|
||||
|
@ -1705,10 +1754,10 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
}
|
||||
// else { pl_data->spindle_speed = 0.0; } // Initialized as zero already.
|
||||
|
||||
// [5. Select tool ]: NOT SUPPORTED. Only tracks tool value.
|
||||
// [5. Select tool ]: Only tracks tool value.
|
||||
gc_state.tool = gc_block.values.t;
|
||||
|
||||
// [6. Change tool ]:
|
||||
// [6. Change tool ]: M6
|
||||
if(change_tool && (settings.tool_change > 0))
|
||||
{
|
||||
if(sys.is_homed)
|
||||
|
@ -1778,12 +1827,17 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
{
|
||||
gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] = 0.0;
|
||||
}
|
||||
// else G43.1
|
||||
if(gc_state.tool_length_offset != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS])
|
||||
// G43.1
|
||||
if((update_tooltable == 0) && gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS] != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS])
|
||||
{
|
||||
gc_state.tool_length_offset = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS];
|
||||
gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS] = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS];
|
||||
System_FlagWcoChange();
|
||||
}
|
||||
// G43
|
||||
if(update_tooltable == 1)
|
||||
{
|
||||
TC_ApplyToolOffset();
|
||||
}
|
||||
}
|
||||
|
||||
// [15. Coordinate system selection ]:
|
||||
|
@ -1890,7 +1944,7 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
}
|
||||
else
|
||||
{
|
||||
clear_z += gc_state.tool_length_offset;
|
||||
clear_z += gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS];
|
||||
}
|
||||
|
||||
if(clear_z < gc_block.values.xyz[Z_AXIS])
|
||||
|
@ -2006,11 +2060,179 @@ uint8_t GC_ExecuteLine(char *line)
|
|||
}
|
||||
else if(gc_state.modal.motion == MOTION_MODE_SPINDLE_SYNC)
|
||||
{
|
||||
// Perform a small move towards target to trigger backlash compensation, because it could affect synchronized motion
|
||||
old_xyz[Z_AXIS] -= 0.001;
|
||||
MC_Line(old_xyz, pl_data);
|
||||
|
||||
// Wait till everything is finished
|
||||
Protocol_BufferSynchronize();
|
||||
|
||||
// Get current RPM
|
||||
uint16_t rpm = Spindle_GetRPM();
|
||||
pl_data->spindle_speed = rpm;
|
||||
if(rpm > 0)
|
||||
{
|
||||
// Calculate feed rate depending on current RPM along Z-axis
|
||||
pl_data->feed_rate = rpm * gc_block.values.ijk[Z_AXIS];
|
||||
|
||||
if(!isEqual_f(gc_block.values.xyz[X_AXIS], old_xyz[X_AXIS]))
|
||||
{
|
||||
// Also movement in X-axis
|
||||
float f = sqrt(pow(gc_block.values.xyz[X_AXIS], 2.0) + pow(gc_block.values.ijk[Z_AXIS], 2.0));
|
||||
|
||||
pl_data->feed_rate *= f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Spindle not moving
|
||||
return STATUS_IDLE_ERROR;
|
||||
}
|
||||
|
||||
// Sync move
|
||||
MC_LineSync(gc_block.values.xyz, pl_data, gc_block.values.ijk[Z_AXIS]);
|
||||
}
|
||||
else if(gc_state.modal.motion == MOTION_MODE_THREADING)
|
||||
{
|
||||
float pitch = gc_block.values.p;
|
||||
float peak = gc_block.values.ijk[X_AXIS];
|
||||
float doc = gc_block.values.ijk[Y_AXIS];
|
||||
float final_depth = gc_block.values.ijk[Z_AXIS];
|
||||
float regression = min(gc_block.values.r, 6.0);
|
||||
uint8_t spring_passes = gc_block.values.h;
|
||||
float angle = gc_block.values.q;
|
||||
//float taper_dist = gc_block.values.e;
|
||||
//uint8_t taper_type = gc_block.values.l;
|
||||
|
||||
float cur_xyz[N_AXIS];
|
||||
memcpy(cur_xyz, old_xyz, sizeof(cur_xyz));
|
||||
|
||||
float next_doc = 0.0;
|
||||
uint8_t leave = 0;
|
||||
uint16_t idx = 0;
|
||||
|
||||
// Calculate z offset for angled slide compensation
|
||||
float z_offset = doc * tan(angle*M_PI/180.0);
|
||||
|
||||
|
||||
// Wait till everything is finished
|
||||
Protocol_BufferSynchronize();
|
||||
|
||||
// Get current RPM
|
||||
uint16_t rpm = Spindle_GetRPM();
|
||||
pl_data->spindle_speed = rpm;
|
||||
if(rpm > 0)
|
||||
{
|
||||
// Calculate feed rate depending on current RPM along Z-axis
|
||||
pl_data->feed_rate = rpm * pitch;
|
||||
|
||||
if(!isEqual_f(gc_block.values.xyz[X_AXIS], old_xyz[X_AXIS]))
|
||||
{
|
||||
// Also movement in X-axis
|
||||
float f = sqrt(pow(gc_block.values.xyz[X_AXIS], 2.0) + pow(pitch, 2.0));
|
||||
|
||||
pl_data->feed_rate *= f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Spindle not moving
|
||||
return STATUS_IDLE_ERROR;
|
||||
}
|
||||
|
||||
while((leave == 0) || (spring_passes != 0))
|
||||
{
|
||||
if(leave == 0)
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
|
||||
if((leave == 1) && (spring_passes > 0))
|
||||
{
|
||||
// Thread cutting done, only spring passes left
|
||||
spring_passes--;
|
||||
}
|
||||
|
||||
// Perform a small move towards target to trigger backlash compensation, because it could affect synchronized motion
|
||||
old_xyz[Z_AXIS] -= 0.001;
|
||||
if(leave == 0)
|
||||
{
|
||||
// Add Z offset
|
||||
old_xyz[Z_AXIS] -= z_offset;
|
||||
}
|
||||
MC_Line(old_xyz, pl_data);
|
||||
old_xyz[Z_AXIS] += 0.001;
|
||||
|
||||
// Rapid from drive line to depth of cut
|
||||
pl_data->condition |= PL_COND_FLAG_RAPID_MOTION;
|
||||
if(peak < 0.0)
|
||||
{
|
||||
// External thread
|
||||
cur_xyz[X_AXIS] = old_xyz[X_AXIS] + peak - doc - next_doc;
|
||||
if(cur_xyz[X_AXIS] <= (old_xyz[X_AXIS] + peak - final_depth))
|
||||
{
|
||||
// Limit to final depth
|
||||
cur_xyz[X_AXIS] = old_xyz[X_AXIS] + peak - final_depth;
|
||||
leave = 1;
|
||||
}
|
||||
}
|
||||
else if(peak > 0.0)
|
||||
{
|
||||
// Internal thread
|
||||
cur_xyz[X_AXIS] = old_xyz[X_AXIS] + peak + doc + next_doc;
|
||||
if(cur_xyz[X_AXIS] <= (old_xyz[X_AXIS] + peak + final_depth))
|
||||
{
|
||||
// Limit to final depth
|
||||
cur_xyz[X_AXIS] = old_xyz[X_AXIS] + peak + final_depth;
|
||||
leave = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// peak is zero
|
||||
return STATUS_BAD_NUMBER_FORMAT;
|
||||
}
|
||||
MC_Line(cur_xyz, pl_data);
|
||||
|
||||
// Handle entry taper
|
||||
// ToDo
|
||||
|
||||
Protocol_BufferSynchronize();
|
||||
|
||||
// Actual synced move
|
||||
cur_xyz[Z_AXIS] = gc_block.values.xyz[Z_AXIS] - z_offset*(idx-1);
|
||||
pl_data->condition &= ~PL_COND_FLAG_RAPID_MOTION;
|
||||
// Sync move
|
||||
MC_LineSync(cur_xyz, pl_data, pitch);
|
||||
|
||||
// Handle exit taper
|
||||
// ToDo
|
||||
|
||||
// Rapid out to drive line
|
||||
pl_data->condition |= PL_COND_FLAG_RAPID_MOTION;
|
||||
cur_xyz[X_AXIS] = old_xyz[X_AXIS];
|
||||
MC_Line(cur_xyz, pl_data);
|
||||
|
||||
// Cycle ends at end of drive line
|
||||
if(leave == 0 || spring_passes != 0)
|
||||
{
|
||||
//Move back to start of drive line
|
||||
MC_Line(old_xyz, pl_data);
|
||||
cur_xyz[Z_AXIS] = old_xyz[Z_AXIS];
|
||||
}
|
||||
|
||||
// Calculate DOC of next move
|
||||
if(regression <= 1.0001)
|
||||
{
|
||||
// No regression defined
|
||||
next_doc += doc;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo
|
||||
next_doc += (1/idx) * doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -254,14 +254,16 @@ typedef struct
|
|||
float feed_rate; // Millimeters/min
|
||||
uint8_t tool; // Tracks tool number.
|
||||
int32_t line_number; // Last line number sent
|
||||
float spindle_limit;
|
||||
float spindle_limit; // Max RPM for G96
|
||||
|
||||
float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code
|
||||
float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine
|
||||
|
||||
// position in mm. Loaded from EEPROM when called.
|
||||
float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to
|
||||
|
||||
// machine zero in mm. Non-persistent. Cleared upon reset and boot.
|
||||
float tool_length_offset; // Tracks tool length offset value when enabled.
|
||||
float tool_length_offset[N_AXIS]; // Tracks tool length offset value when enabled.
|
||||
} Parser_State_t;
|
||||
|
||||
|
||||
|
|
|
@ -73,14 +73,26 @@ uint8_t Limits_GetState(void)
|
|||
uint8_t limit_state = 0;
|
||||
|
||||
limit_state = (GPIO_ReadInputDataBit(GPIO_LIM_X_PORT, GPIO_LIM_X_PIN)<<X1_LIMIT_BIT);
|
||||
#if !defined(LATHE_MODE)
|
||||
limit_state |= (GPIO_ReadInputDataBit(GPIO_LIM_Y_PORT, GPIO_LIM_Y_PIN)<<Y1_LIMIT_BIT);
|
||||
#endif
|
||||
limit_state |= (GPIO_ReadInputDataBit(GPIO_LIM_Z_PORT, GPIO_LIM_Z_PIN)<<Z1_LIMIT_BIT);
|
||||
|
||||
// Second limit
|
||||
limit_state |= (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8)<<X2_LIMIT_BIT);
|
||||
limit_state |= (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5)<<Y2_LIMIT_BIT);
|
||||
limit_state |= (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6)<<Z2_LIMIT_BIT);
|
||||
|
||||
if(BIT_IS_FALSE(settings.flags, BITFLAG_INVERT_LIMIT_PINS))
|
||||
{
|
||||
limit_state ^= LIMIT_MASK;
|
||||
}
|
||||
|
||||
#if defined(LATHE_MODE)
|
||||
// Clear Y-Limits in lathe mode
|
||||
limit_state &= ~(1<<Y1_LIMIT_BIT | 1<<Y2_LIMIT_BIT);
|
||||
#endif
|
||||
|
||||
return limit_state;
|
||||
}
|
||||
|
||||
|
@ -109,8 +121,10 @@ void Limit_PinChangeISR(void) // DEFAULT: Limit pin change interrupt process.
|
|||
{
|
||||
if(settings.system_flags & BITFLAG_FORCE_HARD_LIMIT_CHECK)
|
||||
{
|
||||
uint8_t lim = Limits_GetState();
|
||||
|
||||
// Check limit pin state.
|
||||
if(Limits_GetState())
|
||||
if(lim)
|
||||
{
|
||||
MC_Reset(); // Initiate system kill.
|
||||
System_SetExecAlarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "GCode.h"
|
||||
#include "Probe.h"
|
||||
#include "Limits.h"
|
||||
#include "System32.h"
|
||||
#include "Protocol.h"
|
||||
#include "SpindleControl.h"
|
||||
#include "Stepper.h"
|
||||
|
@ -33,16 +34,30 @@
|
|||
#include "CoolantControl.h"
|
||||
#include "MotionControl.h"
|
||||
#include "defaults.h"
|
||||
#include "PID.h"
|
||||
#include "Encoder.h"
|
||||
|
||||
|
||||
#define DIR_POSITIV 0
|
||||
#define DIR_NEGATIV 1
|
||||
|
||||
|
||||
// Backlash compensation
|
||||
static float target_prev[N_AXIS] = {0.0};
|
||||
static uint8_t dir_negative[N_AXIS] = {DIR_NEGATIV};
|
||||
static uint8_t backlash_enable = 0;
|
||||
|
||||
// Sync move
|
||||
int32_t pos_z = 0;
|
||||
static volatile uint8_t wait_spindle = 0;
|
||||
static uint8_t start_sync = 0;
|
||||
static uint16_t enc_cnt_prev = 0;
|
||||
static uint32_t EncValue = 0;
|
||||
static float sync_pitch = 0.0;
|
||||
|
||||
float in = 0.0, out = 0.0, set = 0.0;
|
||||
PID_t pid;
|
||||
|
||||
|
||||
void MC_Init(void)
|
||||
{
|
||||
|
@ -61,6 +76,17 @@ void MC_Init(void)
|
|||
backlash_enable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
PID_Create(&pid, &in, &out, &set, 1.8, 22, 0.08);
|
||||
PID_Limits(&pid, -0.4, 0.4);
|
||||
PID_EnableAuto(&pid);
|
||||
|
||||
pos_z = 0;
|
||||
wait_spindle = 0;
|
||||
start_sync = 0;
|
||||
enc_cnt_prev = 0;
|
||||
sync_pitch = 0;
|
||||
EncValue = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -226,6 +252,157 @@ void MC_Line(float *target, Planner_LineData_t *pl_data)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void MC_LineSync(float *target, Planner_LineData_t *pl_data, float pitch)
|
||||
{
|
||||
uint8_t old_f_override = sys.f_override;
|
||||
|
||||
// Put in hold state - no moves will be started
|
||||
sys.state = STATE_HOLD;
|
||||
|
||||
sync_pitch = pitch;
|
||||
|
||||
if(pitch < 1.1)
|
||||
{
|
||||
PID_Tune(&pid, 1.8, 22, 0.08);
|
||||
}
|
||||
else if(pitch < 1.6)
|
||||
{
|
||||
PID_Tune(&pid, 1.6, 18, 0.06);
|
||||
}
|
||||
else
|
||||
{
|
||||
PID_Tune(&pid, 1.4, 15, 0.04);
|
||||
}
|
||||
|
||||
// Disable feed override
|
||||
sys.f_override = DEFAULT_FEED_OVERRIDE;
|
||||
sys.report_ovr_counter = 0; // Set to report change immediately
|
||||
|
||||
Planner_UpdateVelocityProfileParams();
|
||||
Planner_CycleReinitialize();
|
||||
|
||||
// Save current z position
|
||||
pos_z = sys_position[Z_AXIS];
|
||||
|
||||
// Calculate mm/s
|
||||
float feed = pl_data->feed_rate / 60.0;
|
||||
|
||||
// Calculate distance [mm] which is needed for acceleration; ToDo: Include x-axis
|
||||
float s_d = ((feed * feed) / ((settings.acceleration[Z_AXIS] / 3600) * 2));
|
||||
// Increase it by a small amount
|
||||
s_d += 0.05;
|
||||
|
||||
// Calculate position, when feedrate is reached
|
||||
pos_z -= (int32_t)(s_d * settings.steps_per_mm[Z_AXIS]);
|
||||
|
||||
MC_Line(target, pl_data);
|
||||
sys.sync_move = 1;
|
||||
|
||||
// Wait for spindle sync
|
||||
while(wait_spindle == 0)
|
||||
{
|
||||
Protocol_ExecuteRealtime(); // Check for any run-time commands
|
||||
|
||||
if(sys.abort)
|
||||
{
|
||||
// Bail, if system abort.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Set state back to idle - queued move will be started
|
||||
sys.state = STATE_IDLE;
|
||||
|
||||
// Trigger immediate start of cycle
|
||||
Protocol_AutoCycleStart();
|
||||
Protocol_ExecRtSystem();
|
||||
|
||||
// Wait till sync move is finished
|
||||
Protocol_BufferSynchronize();
|
||||
sys.sync_move = 0;
|
||||
start_sync = 0;
|
||||
wait_spindle = 0;
|
||||
Stepper_Ovr(0.0);
|
||||
|
||||
// Restore old override
|
||||
sys.f_override = old_f_override;
|
||||
sys.report_ovr_counter = 0; // Set to report change immediately
|
||||
|
||||
Planner_UpdateVelocityProfileParams();
|
||||
Planner_CycleReinitialize();
|
||||
}
|
||||
|
||||
|
||||
void MC_LineSyncStart(void)
|
||||
{
|
||||
wait_spindle = 1;
|
||||
}
|
||||
|
||||
|
||||
void MC_UpdateSyncMove(void)
|
||||
{
|
||||
if(sys.sync_move)
|
||||
{
|
||||
if(start_sync == 0)
|
||||
{
|
||||
if(sys_position[Z_AXIS] <= pos_z)
|
||||
{
|
||||
// Start sync
|
||||
start_sync = 1;
|
||||
|
||||
in = 0.0;
|
||||
PID_Compute(&pid);
|
||||
|
||||
// Save sys position at start
|
||||
pos_z = sys_position[Z_AXIS];
|
||||
// Reset encoder value
|
||||
EncValue = 0;
|
||||
enc_cnt_prev = (uint16_t)Encoder_GetValue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t cnt = (uint16_t)Encoder_GetValue();
|
||||
uint32_t cnt_diff = 0;
|
||||
|
||||
// Calculate ticks since last event
|
||||
if(cnt < enc_cnt_prev)
|
||||
{
|
||||
// Ovf
|
||||
cnt_diff = (0xFFFF - enc_cnt_prev) + cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt_diff = cnt - enc_cnt_prev;
|
||||
}
|
||||
enc_cnt_prev = cnt;
|
||||
EncValue += cnt_diff;
|
||||
|
||||
// Calculate revolutions since start
|
||||
float rev_actual = (float)EncValue / PULSES_PER_REV;
|
||||
// Distance since start
|
||||
float dist_expected = rev_actual * sync_pitch;
|
||||
|
||||
// Expected distance since start
|
||||
float dist_act = ((sys_position[Z_AXIS] - pos_z) / settings.steps_per_mm[Z_AXIS]) * -1.0;
|
||||
|
||||
// Error
|
||||
in = dist_expected - dist_act;
|
||||
|
||||
// Compute
|
||||
PID_Compute(&pid);
|
||||
|
||||
// Apply
|
||||
Stepper_Ovr(out);
|
||||
|
||||
/*Printf("err %d\r\n", (int)(1000*in));
|
||||
Printf_Flush();*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Execute an arc in offset mode format. position == current xyz, target == target xyz,
|
||||
// offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is
|
||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||
|
|
|
@ -46,6 +46,12 @@ void MC_SyncBacklashPosition(void);
|
|||
// (1 minute)/feed_rate time.
|
||||
void MC_Line(float *target, Planner_LineData_t *pl_data);
|
||||
|
||||
void MC_LineSync(float *target, Planner_LineData_t *pl_data, float pitch);
|
||||
|
||||
void MC_LineSyncStart(void);
|
||||
|
||||
void MC_UpdateSyncMove(void);
|
||||
|
||||
// Execute an arc in offset mode format. position == current xyz, target == target xyz,
|
||||
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
|
||||
// the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used
|
||||
|
|
|
@ -584,7 +584,7 @@ void Protocol_ExecRtSystem(void)
|
|||
|
||||
// Execute overrides.
|
||||
rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override
|
||||
if(rt_exec)
|
||||
if(rt_exec && !sys.sync_move)
|
||||
{
|
||||
System_ClearExecMotionOverride(); // Clear all motion override flags.
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static void Report_LineFeed(void)
|
|||
{
|
||||
Putc('\r');
|
||||
Putc('\n');
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,7 +112,7 @@ static void report_util_uint8_setting(uint8_t n, int val)
|
|||
static void report_util_float_setting(uint8_t n, float val, uint8_t n_decimal)
|
||||
{
|
||||
Report_SettingPrefix(n);
|
||||
PrintFloat(val, n_decimal);
|
||||
Printf_Float(val, n_decimal);
|
||||
Report_LineFeed(); // report_util_setting_string(n);
|
||||
}
|
||||
|
||||
|
@ -129,13 +129,13 @@ void Report_StatusMessage(uint8_t status_code)
|
|||
{
|
||||
case STATUS_OK: // STATUS_OK
|
||||
Printf("ok\r\n");
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
Printf("error:");
|
||||
Printf("%d\r\n", status_code);
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ void Report_InitMessage(void)
|
|||
{
|
||||
//Printf("\r\nGRBL-Advanced %s ['$' for help]\r\n", GRBL_VERSION);
|
||||
Printf("\r\nGrbl %s [Advanced Edition | '$' for help]\r\n", GRBL_VERSION);
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
}
|
||||
|
||||
|
||||
|
@ -229,7 +229,7 @@ void Report_GrblHelp(void)
|
|||
{
|
||||
Printf("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n");
|
||||
Printf("[GRBL-Advanced by Schildkroet]\r\n");
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
}
|
||||
|
||||
|
||||
|
@ -303,7 +303,7 @@ void Report_GrblSettings(void)
|
|||
|
||||
val += AXIS_SETTINGS_INCREMENT;
|
||||
}
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
}
|
||||
|
||||
|
||||
|
@ -408,12 +408,19 @@ void Report_NgcParams(void)
|
|||
Report_AxisValue(gc_state.coord_offset);
|
||||
report_util_feedback_line_feed();
|
||||
Printf("[TLO:"); // Print tool length offset value
|
||||
PrintFloat_CoordValue(gc_state.tool_length_offset);
|
||||
for(uint8_t idx = 0; idx < N_AXIS; idx++)
|
||||
{
|
||||
PrintFloat_CoordValue(gc_state.tool_length_offset[idx]);
|
||||
if(idx < (N_AXIS-1))
|
||||
{
|
||||
Printf(",");
|
||||
}
|
||||
}
|
||||
report_util_feedback_line_feed();
|
||||
Report_ProbeParams(); // Print probe parameters. Not persistent in memory.
|
||||
Report_TLSParams(); // Print tls position. Persistent in memory.
|
||||
|
||||
Print_Flush();
|
||||
Printf_Flush();
|
||||
}
|
||||
|
||||
|
||||
|
@ -535,7 +542,7 @@ void Report_GCodeModes(void)
|
|||
PrintFloat_RateValue(gc_state.feed_rate);
|
||||
|
||||
Printf(" S");
|
||||
PrintFloat(gc_state.spindle_speed, N_DECIMAL_RPMVALUE);
|
||||
Printf_Float(gc_state.spindle_speed, N_DECIMAL_RPMVALUE);
|
||||
|
||||
report_util_feedback_line_feed();
|
||||
}
|
||||
|
@ -630,6 +637,9 @@ void Report_BuildInfo(char *line)
|
|||
#ifdef USE_MULTI_AXIS
|
||||
Putc('A');
|
||||
#endif
|
||||
#ifdef LATHE_MODE
|
||||
Putc('D');
|
||||
#endif
|
||||
|
||||
// NOTE: Compiled values, like override increments/max/min values, may be added at some point later.
|
||||
Putc(',');
|
||||
|
@ -751,15 +761,12 @@ void Report_RealtimeStatus(void)
|
|||
float wco[N_AXIS];
|
||||
if(BIT_IS_FALSE(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE) || (sys.report_wco_counter == 0) )
|
||||
{
|
||||
for (idx = 0; idx < N_AXIS; idx++)
|
||||
for (idx = 0; idx < N_AXIS; idx++)
|
||||
{
|
||||
// Apply work coordinate offsets and tool length offset to current position.
|
||||
wco[idx] = gc_state.coord_system[idx]+gc_state.coord_offset[idx];
|
||||
|
||||
if(idx == TOOL_LENGTH_OFFSET_AXIS)
|
||||
{
|
||||
wco[idx] += gc_state.tool_length_offset;
|
||||
}
|
||||
wco[idx] += gc_state.tool_length_offset[idx];
|
||||
|
||||
if(BIT_IS_FALSE(settings.status_report_mask, BITFLAG_RT_STATUS_POSITION_TYPE))
|
||||
{
|
||||
|
@ -811,7 +818,7 @@ void Report_RealtimeStatus(void)
|
|||
Printf("|FS:");
|
||||
PrintFloat_RateValue(Stepper_GetRealtimeRate());
|
||||
Putc(',');
|
||||
PrintFloat(sys.spindle_speed, N_DECIMAL_RPMVALUE);
|
||||
Printf_Float(sys.spindle_speed, N_DECIMAL_RPMVALUE);
|
||||
#endif
|
||||
|
||||
#ifdef REPORT_FIELD_PIN_STATE
|
||||
|
|
|
@ -92,7 +92,6 @@ void Settings_Restore(uint8_t restore_flag)
|
|||
if(restore_flag & SETTINGS_RESTORE_DEFAULTS)
|
||||
{
|
||||
settings.system_flags = DEFAULT_SYSTEM_INVERT_MASK;
|
||||
settings.flags2 = DEFAULT_LATHE_MODE;
|
||||
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
|
||||
settings.step_invert_mask = DEFAULT_STEPPING_INVERT_MASK;
|
||||
settings.dir_invert_mask = DEFAULT_DIRECTION_INVERT_MASK;
|
||||
|
@ -109,6 +108,7 @@ void Settings_Restore(uint8_t restore_flag)
|
|||
settings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY;
|
||||
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
|
||||
|
||||
// Flags
|
||||
settings.flags = 0;
|
||||
if(DEFAULT_REPORT_INCHES)
|
||||
{
|
||||
|
@ -143,6 +143,13 @@ void Settings_Restore(uint8_t restore_flag)
|
|||
settings.flags |= BITFLAG_INVERT_PROBE_PIN;
|
||||
}
|
||||
|
||||
// Flags2
|
||||
settings.flags2 = 0;
|
||||
if(DEFAULT_LATHE_MODE)
|
||||
{
|
||||
settings.flags2 |= BITFLAG_LATHE_MODE;
|
||||
}
|
||||
|
||||
settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM;
|
||||
settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM;
|
||||
settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM;
|
||||
|
|
|
@ -27,13 +27,14 @@
|
|||
#include "GCode.h"
|
||||
#include "SpindleControl.h"
|
||||
#include "Config.h"
|
||||
#include "Encoder.h"
|
||||
|
||||
|
||||
static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions.
|
||||
static uint8_t spindle_enabled = 0;
|
||||
static uint8_t spindle_dir_cw = 1;
|
||||
|
||||
extern uint32_t uwTIM3Freq;
|
||||
extern uint32_t spindle_rpm;
|
||||
|
||||
|
||||
void Spindle_Init(void)
|
||||
|
@ -43,6 +44,10 @@ void Spindle_Init(void)
|
|||
GPIO_InitGPIO(GPIO_SPINDLE);
|
||||
|
||||
TIM1_Init();
|
||||
//TIM3_Init();
|
||||
#if defined(LATHE_MODE)
|
||||
Encoder_Init();
|
||||
#endif
|
||||
|
||||
pwm_gradient = SPINDLE_PWM_RANGE/(settings.rpm_max-settings.rpm_min);
|
||||
spindle_dir_cw = 1;
|
||||
|
@ -122,10 +127,9 @@ void Spindle_SetSpeed(uint8_t pwm_value)
|
|||
}
|
||||
|
||||
|
||||
uint16_t Spindle_GetRPM(void)
|
||||
uint32_t Spindle_GetRPM(void)
|
||||
{
|
||||
// 4 impulses per revolution
|
||||
return (uint16_t)(uwTIM3Freq / 4);
|
||||
return spindle_rpm;
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,3 +237,27 @@ void Spindle_Sync(uint8_t state, float rpm)
|
|||
Spindle_SetState(state, rpm);
|
||||
}
|
||||
|
||||
|
||||
void Spindle_SetSurfaceSpeed(float x_pos)
|
||||
{
|
||||
if(isEqual_f(x_pos, 0.0))
|
||||
{
|
||||
x_pos = 0.5;
|
||||
}
|
||||
float u = (fabs(x_pos) * 2) * M_PI;
|
||||
float rpm = gc_state.spindle_speed / (u / 1000);
|
||||
|
||||
// Limit Max RPM
|
||||
if(gc_state.spindle_limit > 0)
|
||||
{
|
||||
rpm = min(rpm, gc_state.spindle_limit);
|
||||
}
|
||||
sys.spindle_speed = rpm;
|
||||
|
||||
if(sys.state == STATE_CHECK_MODE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Spindle_SetSpeed(Spindle_ComputePwmValue(rpm));
|
||||
}
|
||||
|
|
|
@ -62,8 +62,12 @@ void Spindle_SetState(uint8_t state, float rpm);
|
|||
// NOTE: 328p PWM register is 8-bit.
|
||||
void Spindle_SetSpeed(uint8_t pwm_value);
|
||||
|
||||
uint32_t Spindle_GetRPM(void);
|
||||
|
||||
// Computes 328p-specific PWM register value for the given RPM for quick updating.
|
||||
uint8_t Spindle_ComputePwmValue(float rpm);
|
||||
|
||||
void Spindle_SetSurfaceSpeed(float x_pos);
|
||||
|
||||
|
||||
#endif // SPINDLECONTROL_H
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Config.h"
|
||||
#include "Planner.h"
|
||||
#include "Probe.h"
|
||||
#include "GCode.h"
|
||||
#include "SpindleControl.h"
|
||||
#include "System.h"
|
||||
#include "Settings.h"
|
||||
|
@ -72,6 +73,8 @@
|
|||
#define STEP_TIMER_MIN (uint16_t)((F_TIMER_STEPPER / 120000))
|
||||
#endif
|
||||
|
||||
#define G96_UPDATE_CNT 20
|
||||
|
||||
|
||||
// Stores the planner block Bresenham algorithm execution data for the segments in the segment
|
||||
// buffer. Normally, this buffer is partially in-use, but, for the worst case scenario, it will
|
||||
|
@ -175,9 +178,11 @@ static uint8_t dir_port_invert_mask;
|
|||
static Planner_Block_t *pl_block; // Pointer to the planner block being prepped
|
||||
static Stepper_Block_t *st_prep_block; // Pointer to the stepper block data being prepped
|
||||
|
||||
|
||||
static Stepper_PrepData_t prep;
|
||||
|
||||
static float tim_ovr = 0;
|
||||
static uint8_t update_g96 = G96_UPDATE_CNT;
|
||||
|
||||
|
||||
/* BLOCK VELOCITY PROFILE DEFINITION
|
||||
__________________________
|
||||
|
@ -298,6 +303,12 @@ void Stepper_Disable(uint8_t ovr_disable)
|
|||
}
|
||||
|
||||
|
||||
void Stepper_Ovr(float ovr)
|
||||
{
|
||||
tim_ovr = ovr;
|
||||
}
|
||||
|
||||
|
||||
/* "The Stepper Driver Interrupt" - This timer interrupt is the workhorse of Grbl. Grbl employs
|
||||
the venerable Bresenham line algorithm to manage and exactly synchronize multi-axis moves.
|
||||
Unlike the popular DDA algorithm, the Bresenham algorithm is not susceptible to numerical
|
||||
|
@ -358,6 +369,7 @@ void Stepper_MainISR(void)
|
|||
GPIO_SetBits(GPIO_STEP_X_PORT, GPIO_STEP_X_PIN);
|
||||
}
|
||||
}
|
||||
#if !defined(LATHE_MODE)
|
||||
if(st.step_outbits & (1<<Y_STEP_BIT))
|
||||
{
|
||||
if(step_port_invert_mask & (1<<Y_STEP_BIT))
|
||||
|
@ -372,6 +384,7 @@ void Stepper_MainISR(void)
|
|||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
if(st.step_outbits & (1<<Z_STEP_BIT))
|
||||
{
|
||||
if(step_port_invert_mask & (1<<Z_STEP_BIT))
|
||||
|
@ -428,8 +441,26 @@ void Stepper_MainISR(void)
|
|||
st.exec_segment->cycles_per_tick = STEP_TIMER_MIN;
|
||||
}
|
||||
|
||||
TIM9->ARR = st.exec_segment->cycles_per_tick;
|
||||
TIM9->CCR1 = (uint16_t)(st.exec_segment->cycles_per_tick * 0.6);
|
||||
int32_t new_cycles_per_tick = st.exec_segment->cycles_per_tick;
|
||||
if(sys.sync_move == 1)
|
||||
{
|
||||
new_cycles_per_tick = st.exec_segment->cycles_per_tick * tim_ovr;
|
||||
new_cycles_per_tick = st.exec_segment->cycles_per_tick + new_cycles_per_tick;
|
||||
if(new_cycles_per_tick > 0xFFFF)
|
||||
{
|
||||
new_cycles_per_tick = 0xFFFF;
|
||||
}
|
||||
if(new_cycles_per_tick < STEP_TIMER_MIN-50)
|
||||
{
|
||||
new_cycles_per_tick = STEP_TIMER_MIN-50;
|
||||
}
|
||||
}
|
||||
|
||||
// Update TIM9 register for next interrupt
|
||||
//TIM9->ARR = st.exec_segment->cycles_per_tick;
|
||||
//TIM9->CCR1 = (uint16_t)(st.exec_segment->cycles_per_tick * 0.6);
|
||||
TIM9->ARR = (uint16_t)new_cycles_per_tick;
|
||||
TIM9->CCR1 = (uint16_t)(new_cycles_per_tick * 0.6);
|
||||
st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow.
|
||||
|
||||
// If the new segment starts a new planner block, initialize stepper variables and counters.
|
||||
|
@ -455,6 +486,7 @@ void Stepper_MainISR(void)
|
|||
{
|
||||
GPIO_ResetBits(GPIO_DIR_X_PORT, GPIO_DIR_X_PIN);
|
||||
}
|
||||
#if !defined(LATHE_MODE)
|
||||
if(st.dir_outbits & (1<<Y_DIRECTION_BIT))
|
||||
{
|
||||
GPIO_SetBits(GPIO_DIR_Y_PORT, GPIO_DIR_Y_PIN);
|
||||
|
@ -463,6 +495,7 @@ void Stepper_MainISR(void)
|
|||
{
|
||||
GPIO_ResetBits(GPIO_DIR_Y_PORT, GPIO_DIR_Y_PIN);
|
||||
}
|
||||
#endif
|
||||
if(st.dir_outbits & (1<<Z_DIRECTION_BIT))
|
||||
{
|
||||
GPIO_SetBits(GPIO_DIR_Z_PORT, GPIO_DIR_Z_PIN);
|
||||
|
@ -495,8 +528,20 @@ void Stepper_MainISR(void)
|
|||
st.steps[A_AXIS] = st.exec_block->steps[A_AXIS] >> st.exec_segment->amass_level;
|
||||
st.steps[B_AXIS] = st.exec_block->steps[B_AXIS] >> st.exec_segment->amass_level;
|
||||
|
||||
// Set real-time spindle output as segment is loaded, just prior to the first step.
|
||||
Spindle_SetSpeed(st.exec_segment->spindle_pwm);
|
||||
if(gc_state.modal.spindle_mode == SPINDLE_RPM_MODE)
|
||||
{
|
||||
// Set real-time spindle output as segment is loaded, just prior to the first step.
|
||||
Spindle_SetSpeed(st.exec_segment->spindle_pwm);
|
||||
}
|
||||
else if(st.exec_segment->spindle_pwm != SPINDLE_PWM_OFF_VALUE)
|
||||
{
|
||||
if(--update_g96 == 0)
|
||||
{
|
||||
sys.x_pos = (sys_position[X_AXIS] / settings.steps_per_mm[X_AXIS]) - (gc_state.coord_system[X_AXIS]+gc_state.coord_offset[X_AXIS]+gc_state.tool_length_offset[X_AXIS]);
|
||||
Spindle_SetSurfaceSpeed(sys.x_pos);
|
||||
update_g96 = G96_UPDATE_CNT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
|
@ -668,6 +713,7 @@ void Stepper_PortResetISR(void)
|
|||
}
|
||||
|
||||
// Y
|
||||
#if !defined(LATHE_MODE)
|
||||
if(step_port_invert_mask & (1<<Y_STEP_BIT))
|
||||
{
|
||||
GPIO_SetBits(GPIO_STEP_Y_PORT, GPIO_STEP_Y_PIN);
|
||||
|
@ -676,6 +722,7 @@ void Stepper_PortResetISR(void)
|
|||
{
|
||||
GPIO_ResetBits(GPIO_STEP_Y_PORT, GPIO_STEP_Y_PIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Z
|
||||
if(step_port_invert_mask & (1<<Z_STEP_BIT))
|
||||
|
@ -752,17 +799,15 @@ void Stepper_Reset(void)
|
|||
st.dir_outbits = dir_port_invert_mask; // Initialize direction bits to default.
|
||||
|
||||
// Initialize step and direction port pins.
|
||||
// TODO: Stepper invert mask
|
||||
// Reset Step Pins
|
||||
GPIO_ResetBits(GPIO_STEP_X_PORT, GPIO_STEP_X_PIN);
|
||||
GPIO_ResetBits(GPIO_STEP_Y_PORT, GPIO_STEP_Y_PIN);
|
||||
GPIO_ResetBits(GPIO_STEP_Z_PORT, GPIO_STEP_Z_PIN);
|
||||
GPIO_ResetBits(GPIO_STEP_A_PORT, GPIO_STEP_A_PIN);
|
||||
//GPIO_ResetBits(GPIO_STEP_B_PORT, GPIO_STEP_B_PIN);
|
||||
Stepper_PortResetISR();
|
||||
|
||||
// Reset Direction Pins
|
||||
// ToDo: Use invert mask?
|
||||
GPIO_ResetBits(GPIO_DIR_X_PORT, GPIO_DIR_X_PIN);
|
||||
#if !defined(LATHE_MODE)
|
||||
GPIO_ResetBits(GPIO_DIR_Y_PORT, GPIO_DIR_Y_PIN);
|
||||
#endif
|
||||
GPIO_ResetBits(GPIO_DIR_Z_PORT, GPIO_DIR_Z_PIN);
|
||||
GPIO_ResetBits(GPIO_DIR_A_PORT, GPIO_DIR_A_PIN);
|
||||
//GPIO_ResetBits(GPIO_DIR_B_PORT, GPIO_DIR_B_PIN);
|
||||
|
|
|
@ -59,5 +59,7 @@ void Stepper_UpdatePlannerBlockParams(void);
|
|||
// Called by realtime status reporting if realtime rate reporting is enabled in config.h.
|
||||
float Stepper_GetRealtimeRate(void);
|
||||
|
||||
void Stepper_Ovr(float ovr);
|
||||
|
||||
|
||||
#endif // STEPPER_H
|
||||
|
|
|
@ -148,10 +148,12 @@ typedef struct
|
|||
uint8_t report_ovr_counter; // Tracks when to add override data to status reports.
|
||||
uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports.
|
||||
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
|
||||
uint8_t override_ctrl; // Tracks override control states.
|
||||
uint8_t override_ctrl; // Tracks override control states.
|
||||
#endif
|
||||
float spindle_speed;
|
||||
uint8_t is_homed;
|
||||
uint8_t sync_move;
|
||||
float x_pos; // Current x-position of tool (for G96)
|
||||
} System_t;
|
||||
|
||||
extern System_t sys;
|
||||
|
|
|
@ -49,7 +49,11 @@ void TC_Init(void)
|
|||
memset(tc_pos, 0, sizeof(float)*N_AXIS);
|
||||
|
||||
gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL;
|
||||
gc_state.tool_length_offset = 0.0;
|
||||
|
||||
for(uint8_t i = 0; i < N_AXIS; i++)
|
||||
{
|
||||
gc_state.tool_length_offset[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,7 +93,17 @@ void TC_ChangeCurrentTool(void)
|
|||
Protocol_BufferSynchronize();
|
||||
|
||||
// Wait until move is finished
|
||||
while(sys.state != STATE_IDLE);
|
||||
while(sys.state != STATE_IDLE)
|
||||
{
|
||||
Protocol_ExecuteRealtime(); // Check for any run-time commands
|
||||
|
||||
if(sys.abort)
|
||||
{
|
||||
// Bail, if system abort.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sys.state = STATE_TOOL_CHANGE;
|
||||
|
||||
|
@ -131,7 +145,7 @@ void TC_ProbeTLS(void)
|
|||
Protocol_BufferSynchronize();
|
||||
|
||||
// Set up fast probing
|
||||
pl_data.feed_rate = 200.0;
|
||||
pl_data.feed_rate = 220.0;
|
||||
pl_data.condition = 0; // Reset rapid motion condition flag.
|
||||
|
||||
// Probe TLS fast
|
||||
|
@ -174,7 +188,7 @@ void TC_ProbeTLS(void)
|
|||
|
||||
// Apply offset as dynamic tool length offset
|
||||
gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
|
||||
gc_state.tool_length_offset = toolOffset / settings.steps_per_mm[TOOL_LENGTH_OFFSET_AXIS];
|
||||
gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS] = toolOffset / settings.steps_per_mm[TOOL_LENGTH_OFFSET_AXIS];
|
||||
}
|
||||
|
||||
Delay_ms(5);
|
||||
|
@ -204,23 +218,7 @@ void TC_ApplyToolOffset(void)
|
|||
// Apply offset as dynamic tool length offset
|
||||
gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
|
||||
|
||||
switch(TOOL_LENGTH_OFFSET_AXIS)
|
||||
{
|
||||
case X_AXIS:
|
||||
gc_state.tool_length_offset = params.x_offset;
|
||||
break;
|
||||
|
||||
case Y_AXIS:
|
||||
gc_state.tool_length_offset = params.y_offset;
|
||||
break;
|
||||
|
||||
case Z_AXIS:
|
||||
gc_state.tool_length_offset = params.z_offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Axis not valid
|
||||
gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL;
|
||||
break;
|
||||
}
|
||||
gc_state.tool_length_offset[X_AXIS] = params.x_offset;
|
||||
gc_state.tool_length_offset[Y_AXIS] = params.y_offset;
|
||||
gc_state.tool_length_offset[Z_AXIS] = params.z_offset;
|
||||
}
|
||||
|
|
34
grbl/util.c
34
grbl/util.c
|
@ -22,7 +22,9 @@
|
|||
#include <string.h>
|
||||
#include "Config.h"
|
||||
#include "Protocol.h"
|
||||
#include "Print.h"
|
||||
#include "System.h"
|
||||
#include "Settings.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "System32.h"
|
||||
|
@ -146,6 +148,7 @@ uint8_t Read_Float(char *line, uint8_t *char_counter, float *float_ptr)
|
|||
return(true);
|
||||
}
|
||||
|
||||
|
||||
// Search a float in a string and return it as string
|
||||
uint8_t ExtractFloat(char *line, int start_idx, char *float_char)
|
||||
{
|
||||
|
@ -179,6 +182,37 @@ uint8_t ExtractFloat(char *line, int start_idx, char *float_char)
|
|||
return i;
|
||||
}
|
||||
|
||||
|
||||
// Floating value printing handlers for special variables types used in Grbl and are defined
|
||||
// in the config.h.
|
||||
// - CoordValue: Handles all position or coordinate values in inches or mm reporting.
|
||||
// - RateValue: Handles feed rate and current velocity in inches or mm reporting.
|
||||
void PrintFloat_CoordValue(float n)
|
||||
{
|
||||
if(BIT_IS_TRUE(settings.flags, BITFLAG_REPORT_INCHES))
|
||||
{
|
||||
Printf_Float(n*INCH_PER_MM,N_DECIMAL_COORDVALUE_INCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf_Float(n, N_DECIMAL_COORDVALUE_MM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PrintFloat_RateValue(float n)
|
||||
{
|
||||
if(BIT_IS_TRUE(settings.flags, BITFLAG_REPORT_INCHES))
|
||||
{
|
||||
Printf_Float(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf_Float(n, N_DECIMAL_RATEVALUE_MM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Non-blocking delay function used for general operation and suspend features.
|
||||
void Delay_sec(float seconds, uint8_t mode)
|
||||
{
|
||||
|
|
|
@ -126,6 +126,10 @@ uint8_t Read_Float(char *line, uint8_t *char_counter, float *float_ptr);
|
|||
|
||||
uint8_t ExtractFloat(char *line, int start_idx, char *float_char);
|
||||
|
||||
void PrintFloat_CoordValue(float n);
|
||||
|
||||
void PrintFloat_RateValue(float n);
|
||||
|
||||
// Non-blocking delay function used for general operation and suspend features.
|
||||
void Delay_sec(float seconds, uint8_t mode);
|
||||
|
||||
|
|
2
main.c
2
main.c
|
@ -58,7 +58,7 @@ volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bit
|
|||
int main(void)
|
||||
{
|
||||
// Init formatted output
|
||||
Print_Init();
|
||||
Printf_Init();
|
||||
System_Init();
|
||||
Stepper_Init();
|
||||
Settings_Init();
|
||||
|
|
Ładowanie…
Reference in New Issue