cancel
Showing results for 
Search instead for 
Did you mean: 

Could someone help with MCP overrun errors ?

DKing.1
Associate II

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

2 REPLIES 2
Laurent Ca...
Lead II

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

DKing.1
Associate II

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