2021-04-21 06:12 AM
Hi, first the good news: I have motor control up and working. And communication with the workbench works fine. Having read up on the ST motor control protocol, and watching serial comms with the HHD software device monitor app, I can see that commands are 4 to 6 bytes, and acknowledges about the same. I've extended the protocol (by subclassing MCP_Init), to add a custom command and acknowledge, that are each 10 or so bytes. And I was shocked to find that mostly, it works. Now the bad news, I get error acknowledges indicating 'overrun', when the motor is running. The help on this error is not much help :\ Can anyone shed some light on how to resolve? I have as one does, tried a bunch of things, all either destabilised motor control or didn't help. Very briefly 1) Experimenting with USART1 NVIC prio wrt TIM2. 2) Lowering or raising baud from the present 9600. 3) Inserting an inter-byte delay to the command and/or acknowledge. 4) In Cube, disabling overrun detect, however the overrun error seems to be something different. 5) Searching this forum, and consulting google. More details available, hopefully this suffices for an opener. Best regards, David
2021-05-25 02:24 AM
Dear @DKing.1
Welcome to the STM32 Community
Could you give more details to the STM32 Community about your setup -the material you use- ?
(HW and SW, CPU(s), tools and versions, board(s), motor(s) and so on)
And more especially did you use STM32 MC tools (such as MC_suite, STM32 MC Motor Profile, STM32 MC SDK, STM32 MC Workbench, and so on)?
Best regards
Laurent Ca...
2021-05-25 07:24 AM
Hi Laurent,
Sure sure, my setup details as below. Also, details of a solution that for ages, I've had on my todo list to post. And with the suggestion to ST, that the solution be incorporated into the workbench-generated code, to allow for faster USART communication than 9600 baud. mc_tasks.c code snippets are provided at the end of this reply. I've since concluded the client work contract.
HW comprises STEVAL-SPIN3201 board, ie STSPIN32F0A SiP based. Thence, client-derived motor controller circuit, with STSPIN32F0 SiP.
SW comprises ST Motor Control Workbench (MCW) 5.4.5.20506, for code generate/update, using MC Firmware Library 5.4.5. Keil MDK-ARM V5 targetted, with Low Level driver option. STM32CubeMX 6.2.1 use just for some non-MC related GPIO config.
Motors comprise Aikema 85SX/100SX 36VDC 250W. Motors characterised by connecting each in turn to an STEVAL-ESC001V1 board, as Motor Profiler 5.4.5 omits STEVAL-SPIN3201 support. Deduced characteristics differed marginally, in respect of Ke B-Emf constant only. Midpoint Ke value used.
About the solution, as ever there's something mystical afoot in how asking a question automagically reveals the answer! Here's the solution:
In the subclassed MCP_Init, have the FCP_SetClient call specify FCP_ReceivedFrameCallback_t MCP_ReceivedFrameEx. This derived from the standard MCP_ReceivedFrame. Have MCP_ReceivedFrameEx process custom command frame identifier 1F, and otherwise pass command to MCP_ReceivedFrame.
Raise STM32CubeMX NVIC USART1 preemption priority 3 to 2, to allow longer command and acknowledge without overrun acknowledge error at >9600 baud. Keep received data process and acknowledge send as preemption priority 2, delegating those actions to eg Delegate, called from the TSK_MediumFrequencyTaskM1 function trailing user code section. TSK_MediumFrequencyTaskM1 is called from the preemption priority 2 TIM2 interrupt 1ms Systick.
With the described solution, 3Mbit USART1 communication maximum achieved. 115200 baud used though, per requirements and the MCW dropdown maximum. Comspec N81.
Best regards,
David
#define MC_PROTOCOL_CUSTOM 0xBF // Custom command frame identifier
#define ERROR_CUSTOM1 0xFF // Custom command error 1
#define ERROR_CUSTOM2 0xFE // Custom command error 2
#define ERROR_CUSTOM3 0xFD // Custom command error 3
#define ACK_ERROR 0xFF // Error acknowledge frame ID
#define ACK_NOERROR 0xF0 // Data acknowledge frame ID
struct __packed // Packed for efficient USART1 transfer
{
uint8_t a0; // Data acknowledge byte 0
uint8_t a1; // Data acknowledge byte 1
uint8_t a2; // Data acknowledge byte 2
} Ack; // Acknowledge payload
struct
{
MCP_Handle_t *pHandle; // Motor Control Protocol component handle
uint8_t Code; // Received frame code
uint8_t *buffer; // Frame data buffer pointer
uint8_t Size; // Data frame size
} Rx; // Received data
/**
* @brief Function called from the TSK_MediumFrequencyTaskM1 function trailing
* user code section. TSK_MediumFrequencyTaskM1 is called from the
* preemption priority 2 TIM2 interrupt 1ms Systick.
*
*/
static void Delegate(void)
{
:
if (Rx.pHandle) // Received USART1 data
{
pHandle = Rx.pHandle; // Copy handle, so can clear on line below
// Instead retaining Rx.pHandle until last need, namely fFcpSend call to
// send data acknowledge, is not possible, because intervening execution
// takes in excess of 1ms, due to stretch by PWM interrupt servicing.
// Meaning Rx.pHandle would be still non-NULL on next check as above,
// resulting in double acknowledge send. This was seen, pre handle copy.
Rx.pHandle = NULL; // Flag to self that processing commenced
if (Rx.Code != MC_PROTOCOL_CUSTOM) MCP_ReceivedFrame(pHandle, Rx.Code,
Rx.buffer, Rx.Size); // If non-custom command, route to standard function
else // Custom command
{
if (0) bErrorCode = ERROR_CUSTOM1;
if (0) bErrorCode = ERROR_CUSTOM2;
if (0) bErrorCode = ERROR_CUSTOM3;
// If error condition, corresponding error code
if (bErrorCode) pHandle->fFcpSend(pHandle->pFCP, ACK_ERROR,
&bErrorCode, 1); // If error, send error acknowledge frame
else // No error
{
// :
// Populate data acknowledge
pHandle->fFcpSend(pHandle->pFCP, ACK_NOERROR, (uint8_t *)&Ack, 3);
// Send data acknowledge frame
}
}
}
}
/**
* @brief Function used to decode received data. Derived from ST standard
* MCP_ReceivedFrame function, to process added frame identifier 1F, and
* otherwise pass onto to standard function. Same parameters, as below.
* STM32CubeMX NVIC USART1 preemption priority 3 raised to 2, to allow
* longer command and acknowledge, without overrun acknowledge error, and
* at >9600 baud. Received data process, and acknowledge send, remain
* preemption priority 2, by delegating to function called from the
* TSK_MediumFrequencyTaskM1 function trailing user code section. With
* TSK_MediumFrequencyTaskM1 called from the preemption priority 2 TIM2
* interrupt 1ms Systick.
*
* @param pHandle Motor Control Protocol component handle
* @param Code Received frame code
* @param buffer Frame data buffer pointer
* @param Size Data frame size
*/
static void MCP_ReceivedFrameEx(MCP_Handle_t *pHandle, uint8_t Code,
uint8_t *buffer, uint8_t Size)
{
Rx.pHandle = pHandle; // Motor Control Protocol component handle
Rx.Code = Code; // Received frame code
Rx.buffer = buffer; // Frame data buffer pointer
Rx.Size = Size; // Data frame size
}
/**
* @brief Initializes MCP component parameters. Nonweak subclass of ST standard
* MCP_Init function for sent and received callback extend to support
* added frame ID 1F. And to delegate acknowledge issuing as described
* above. Parameters as below per standard MCP_Init.
*
* @param pHandle Pointer on the handle of the component to initialize
* @param pFCP Pointer on Frame communication protocol component's handle
* @param fFcpSend Pointer on FCP's send message function
* @param fFcpReceive Pointer on FCP's receive message function
* @param fFcpAbortReceive Pointer on FCP's abort receive message function
* @param s_fwVer Pointer on string containing FW release version
*/
void MCP_Init( MCP_Handle_t *pHandle,
FCP_Handle_t * pFCP,
FCP_SendFct_t fFcpSend,
FCP_ReceiveFct_t fFcpReceive,
FCP_AbortReceiveFct_t fFcpAbortReceive,
const char* s_fwVer )
{
pHandle->pFCP = pFCP;
pHandle->s_fwVer = s_fwVer;
FCP_SetClient( pFCP, pHandle,
(FCP_SentFrameCallback_t) & MCP_SentFrame,
(FCP_ReceivedFrameCallback_t) & MCP_ReceivedFrameEx,
(FCP_RxTimeoutCallback_t) & MCP_OnTimeOut );
pHandle->fFcpSend = fFcpSend;
pHandle->fFcpReceive = fFcpReceive;
pHandle->fFcpAbortReceive = fFcpAbortReceive;
MCP_WaitNextFrame(pHandle);
}