Replies: 7 comments 11 replies
-
I thought that stm32 driver has fixed pin for spindle pwm output(A8, IIRC). Has it changed now? |
Beta Was this translation helpful? Give feedback.
-
Good to know that, thank you! |
Beta Was this translation helpful? Give feedback.
-
Terje,
This is awesome. I would be happy to test this and I think I can test with a variety of different pins. Unfortunately, I am about to head off on family vacation and won’t be able to look at anything for 2 weeks.
Thanks!
…Sent from my iPad
On Aug 19, 2021, at 12:44 AM, Terje Io ***@***.***> wrote:
I have been sleeping on this and after checking the datasheets and STM code files I found by switching to defining the PWM port by its base address and some fancy token pasting it is possible to select predefined pins (in driver.h) for PWM output. TIM2 and TIM3 is currently used by PPI and spindle sync so can be used for PWM if not enabled. Here is part of the new code:
#ifdef SPINDLE_PWM_PORT_BASE
#if SPINDLE_PWM_PORT_BASE == GPIOA_BASE
#if SPINDLE_PWM_PIN == 7 // PA7 - TIM1_CH1N
#define SPINDLE_PWM_TIMER_N 1
#define SPINDLE_PWM_TIMER_CH 1
#define SPINDLE_PWM_TIMER_INV 1
#define SPINDLE_PWM_TIMER_AF 1
#elif SPINDLE_PWM_PIN == 8 // PA8 - TIM1_CH1
#define SPINDLE_PWM_TIMER_N 1
#define SPINDLE_PWM_TIMER_CH 1
#define SPINDLE_PWM_TIMER_INV 0
#define SPINDLE_PWM_TIMER_AF 1
#endif
#elif SPINDLE_PWM_PORT_BASE == GPIOB_BASE
#if SPINDLE_PWM_PIN == 0 // PB0 - TIM1_CH2N
#define SPINDLE_PWM_TIMER_N 1
#define SPINDLE_PWM_TIMER_CH 2
#define SPINDLE_PWM_TIMER_INV 1
#define SPINDLE_PWM_TIMER_AF 1
#elif SPINDLE_PWM_PIN == 3 // PB3 - TIM2_CH2
#define SPINDLE_PWM_TIMER_N 2
#define SPINDLE_PWM_TIMER_CH 2
#define SPINDLE_PWM_TIMER_INV 0
#define SPINDLE_PWM_TIMER_AF 1
#elif SPINDLE_PWM_PIN == 4 // PB4 - TIM2_CH2
#define SPINDLE_PWM_TIMER_N 3
#define SPINDLE_PWM_TIMER_CH 1
#define SPINDLE_PWM_TIMER_INV 0
#define SPINDLE_PWM_TIMER_AF 2
#endif
#endif
#if SPINDLE_PWM_TIMER_CH == 1 || SPINDLE_PWM_TIMER_CH == 2
#define SPINDLE_PWM_CCR 1
#else
#define SPINDLE_PWM_CCR 2
#endif
#define SPINDLE_PWM_TIMER timer(SPINDLE_PWM_TIMER_N)
#define SPINDLE_PWM_TIMER_CCR timerCCR(SPINDLE_PWM_TIMER_N, SPINDLE_PWM_TIMER_CH)
#define SPINDLE_PWM_TIMER_CCMR timerCCMR(SPINDLE_PWM_TIMER_N, SPINDLE_PWM_CCR)
#define SPINDLE_PWM_CCMR_OCM_SET timerOCM(SPINDLE_PWM_CCR, SPINDLE_PWM_TIMER_CH)
#define SPINDLE_PWM_CCMR_OCM_CLR timerOCMC(SPINDLE_PWM_CCR, SPINDLE_PWM_TIMER_CH)
#if SPINDLE_PWM_TIMER_INV
#define SPINDLE_PWM_CCER_EN timerCCEN(SPINDLE_PWM_TIMER_CH, N)
#define SPINDLE_PWM_CCER_POL timerCCP(SPINDLE_PWM_TIMER_CH, N)
#define SPINDLE_PWM_CR2_OIS timerCR2OIS(SPINDLE_PWM_TIMER_CH, N)
#else
#define SPINDLE_PWM_CCER_EN timerCCEN(SPINDLE_PWM_TIMER_CH, )
#define SPINDLE_PWM_CCER_POL timerCCP(SPINDLE_PWM_TIMER_CH, )
#define SPINDLE_PWM_CR2_OIS timerCR2OIS(SPINDLE_PWM_TIMER_CH, )
#endif
#define SPINDLE_PWM_PORT ((GPIO_TypeDef *)SPINDLE_PWM_PORT_BASE)
#define SPINDLE_PWM_AF timerAF(SPINDLE_PWM_TIMER_N, SPINDLE_PWM_TIMER_AF)
#endif // SPINDLE_PWM_PORT_BASE
#if defined(SPINDLE_PWM_PIN) && !defined(SPINDLE_PWM_TIMER_N)
#ifdef SPINDLE_PWM_PORT
#error Map spindle port by defining SPINDLE_PWM_PORT_BASE in the map file!
#else
#error Spindle PWM not supported on mapped pin!
#endif
#endif
The new code is tested with the STM4xx driver, I believe the new code can be used "as-is" or with little modification for other STM32 drivers as well. Note that adding a new PWM pin in driver.h does not require any changes to driver.c. - only testing is required.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
|
Beta Was this translation helpful? Give feedback.
-
Terje,
Thanks for the quick update. I though this was a pretty good fix, but I
cannot get it to work. When using pwm on PB0 (uses Timer 1), what used to
be 5KHz is now 10KHz. When using pwm on PB3 (uses Timer 2) I still get
2.5KHz.
I think I know what is going on, but cannot find where to fix it.
In the original code, the frequency passed to
spindle_precompute_pwm_values() was 168MHz. For Timer 1, the period
calculated to be 33600 and with the clock frequency for timer 1 of 84MHz,
this generated a pwm frequency of 5KHz as it is supposed to.
With the new code and pin PB0 (uses Timer 1) the frequency passed to
spindle_precompute_pwm_values() is 84MHz and the period calculated is 16800.
Since Timer 1 still has the same clock, a period of half the size results in
double the frequency or 10KHz. It seems to me that passing a frequency of
84MHz is correct, the previous code passing 168MHz is not correct.
Somewhere I cannot find is a scaling by 2 that fixed the old code and breaks
the new.
When I use PB3 (this uses Timer 2) both old and new code pass the same
frequency of 168MHz and as you would expect, it outputs the same pwm
frequency in both cases. However, it is 2.5KHz and not the desired default
5KHz.
I will continue to debug this. If I find the issue, I will post again.
Bill
From: Terje Io ***@***.***>
Sent: Tuesday, August 31, 2021 1:26 PM
To: grblHAL/core ***@***.***>
Cc: fitch22 ***@***.***>; Author ***@***.***>
Subject: Re: [grblHAL/core] Choosing pins for spindle control (#59)
Try by replacing this code in driver.c
<https://github.com/grblHAL/STM32F4xx/blob/master/Src/driver.c> (line
1271+):
uint32_t prescaler = settings->spindle.pwm_freq > 4000.0f ? 1 :
(settings->spindle.pwm_freq > 200.0f ? 12 : 25);
spindle_precompute_pwm_values(&spindle_pwm, SystemCoreClock /
prescaler);
with this:
RCC_ClkInitTypeDef clock;
uint32_t latency, prescaler = settings->spindle.pwm_freq >
4000.0f ? 1 : (settings->spindle.pwm_freq > 200.0f ? 12 : 25);
HAL_RCC_GetClockConfig(&clock, &latency);
#if SPINDLE_PWM_TIMER_N == 1
spindle_precompute_pwm_values(&spindle_pwm,
(HAL_RCC_GetPCLK1Freq() * (clock.APB1CLKDivider == 0 ? 1 : 2)) / prescaler);
#else
spindle_precompute_pwm_values(&spindle_pwm,
(HAL_RCC_GetPCLK2Freq() * (clock.APB2CLKDivider == 0 ? 1 : 2)) / prescaler);
#endif
as a temporary workaround.
It would be better to determine the prescaler value, and possibly the clock
divison value, from the actual timer clock frequency to cover a large range
of PWM frequencies (50Hz - 20kHz). For later...
-
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#59 (reply in thread)> ,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACQUGIX57HGI4MILSXURMSTT7
U3GBANCNFSM5CIH2EYA> .
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&m
t=8&pt=524675> or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=u
tm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>
.
<https://github.com/notifications/beacon/ACQUGIT6J62FSJQWYFBQXNLT7U3GBA5CNFS
M5CIH2EYKYY3PNVWWK3TUL52HS4DFWFCGS43DOVZXG2LPNZBW63LNMVXHJKTDN5WW2ZLOORPWSZG
OAAJUDEQ.gif>
|
Beta Was this translation helpful? Give feedback.
-
Doh! I should have seen this. Thanks for your help, this is great.
Bill
…Sent from my iPad
On Aug 31, 2021, at 10:10 PM, Terje Io ***@***.***> wrote:
I think I know what is going on, but cannot find where to fix it.
I finally found the correct clock routing in the RCC register documentation, Timer 1 runs off APB2, 2-5 off APB1 clock. So the code should be:
#if SPINDLE_PWM_TIMER_N == 1
spindle_precompute_pwm_values(&spindle_pwm, (HAL_RCC_GetPCLK2Freq() * (clock.APB2CLKDivider == 0 ? 1 : 2)) / prescaler);
#else
spindle_precompute_pwm_values(&spindle_pwm, (HAL_RCC_GetPCLK1Freq() * (clock.APB1CLKDivider == 0 ? 1 : 2)) / prescaler);
#endif
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
|
Beta Was this translation helpful? Give feedback.
-
Terje,
Everything now works great. Thank you again.
Here is a question for you. One of my cnc machines is a little 3018. It came with a Arduino based controller board that has connections for both a spindle and a laser. On this board, the same pwm output from the MCU feeds both the spindle driver (24V) and the laser (5V). Since my SKR-2 does not have similar circuitry, if one wanted to use a spindle, they would choose a pwm pin such as PB3 since it can switch 24V, and if one wanted to use a laser they would choose a pwm pin such as PB0 since it is just standard TTL. However, it would be really nice for those that have both a spindle and a laser to be able to switch those pins without recompiling. One idea is that when switching modes from spindle (Mode_Standard) to laser (Mode_Laser) the pwm pin could be switched. The 2 pwm pins could be defined slightly differently in the map file, e.g. SPINDLE_PWM_PIN and LASER_PWM_PIN.
Would something like this be of general interest to the GRBL community? What issues would this present to Lathe mode, or would Lathe mode want a LATHE_PWM_PIN as well? I would be happy to make this change if there is any use for it besides me.
Bill
From: Terje Io ***@***.***>
Sent: Tuesday, August 31, 2021 10:11 PM
To: grblHAL/core ***@***.***>
Cc: fitch22 ***@***.***>; Author ***@***.***>
Subject: Re: [grblHAL/core] Choosing pins for spindle control (#59)
I think I know what is going on, but cannot find where to fix it.
I finally found the correct clock routing in the RCC register documentation, Timer 1 runs off APB2, 2-5 off APB1 clock. So the code should be:
#if SPINDLE_PWM_TIMER_N == 1
spindle_precompute_pwm_values(&spindle_pwm, (HAL_RCC_GetPCLK2Freq() * (clock.APB2CLKDivider == 0 ? 1 : 2)) / prescaler);
#else
spindle_precompute_pwm_values(&spindle_pwm, (HAL_RCC_GetPCLK1Freq() * (clock.APB1CLKDivider == 0 ? 1 : 2)) / prescaler);
#endif
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#59 (reply in thread)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ACQUGIWRLNN746S7ER4AXZ3T7WYVRANCNFSM5CIH2EYA> .
Triage notifications on the go with GitHub Mobile for iOS <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub> . <https://github.com/notifications/beacon/ACQUGIWRFAZFSELBJ7IFZQ3T7WYVRA5CNFSM5CIH2EYKYY3PNVWWK3TUL52HS4DFWFCGS43DOVZXG2LPNZBW63LNMVXHJKTDN5WW2ZLOORPWSZGOAAJUM4A.gif>
|
Beta Was this translation helpful? Give feedback.
-
I do that in the huanyang spindle plugin by "hooking into" the
Could be, but making it a generic feature will be harder - not all drivers/boards have the pins needed for a secondary PWM output. Some could just reroute the PWM signal with a relay or other signal switch controlled by a GPIO/ioport output?
I do not think so, but can of course be done in a similar way as done by the huanyang code.
Add it in the board support code for now? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
While configuring a map file for the BTT SKR-2 board, I have defined pins for spindle enable, direction and pwm. I chose pins designed for fans for enable and direction that can output 24V and both are PWM capable. I chose a standard IO pin for the spindle pwm since I think a 5V signal is more typical here but I do have another fan output same as for enable and direction so I could use that instead. I will also mention, that these fan outputs actually switch the GND side, not the + side, so if necessary it would be easy to use them with 5V or 12V just by feeding a different + side. Also, these are easy connections to make to the board as they all have their own connectors.
What would be the best choice for the type of driving pin? Is a pin capable of 24V appropriate, or would essentially everyone have to feed different voltage?
Also, for my 3018 CNC, the spindle speed is varied using pwm on the 24V fed to it. Should I use SPINDLE_ENABLE_PIN or SPINDLE_PWM_PIN to feed the spindle? I don't fully understand the use cases for enable vs pwm.
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions