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 #54
pull/89/head
Patrick Felixberger 2021-02-07 13:47:16 +01:00
rodzic e50fcc46d0
commit 880b4d86c7
34 zmienionych plików z 1369 dodań i 271 usunięć

Wyświetl plik

@ -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" />

Wyświetl plik

@ -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" />

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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
}

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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 */

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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
```

161
Src/PID.c 100644
Wyświetl plik

@ -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;
}

158
Src/PID.h 100644
Wyświetl plik

@ -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 */

Wyświetl plik

@ -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

Wyświetl plik

@ -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
{

Wyświetl plik

@ -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;

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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.

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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));
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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);

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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
Wyświetl plik

@ -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();