Hey all, I’ve been banging my head against this for awhile now and I’ve gotten to the point where I need assistance from more experienced developers.
I’m currently using an MKS XDrive Mini, a MAX485, and an AR49-M25S using RS485 for communication. Here’s what I have so far:
#include <SimpleFOC.h>
#define RS485_RO PA1
#define RS485_RE PA2
#define RS485_DE PA3
#define RS485_DI PA0
#define AR49_READ 0x02
#define AR49_ZERO_RST 0xC2
HardwareSerial Serial4(RS485_RO, RS485_DI);
char buffer[10];
void PrintBits(char c)
{
for(int i = 7; i >= 0; i--)
{
Serial.print(bitRead(c,i));
}
}
float OnReadEncoder()
{
digitalWrite(RS485_RE, HIGH);
digitalWrite(RS485_DE, HIGH);
delayMicroseconds(2);
Serial4.write(AR49_READ);
Serial4.flush();
delayMicroseconds(5);
digitalWrite(RS485_RE, LOW);
digitalWrite(RS485_DE, LOW);
delayMicroseconds(20);
Serial.print("Response from encoder:");
int bytesReceived = Serial4.available();
if (bytesReceived > 0)
{
Serial4.readBytes(buffer, bytesReceived);
for (int i = 0; i < bytesReceived; i++)
{
Serial.print(' ');
PrintBits(buffer[i]);
if (buffer[i] == AR49_READ)
{
Serial.print(" (Read cofirmed!) ");
}
}
}
Serial.println("");
return 0;
}
void OnInitEncoder()
{
}
GenericSensor encoder = GenericSensor(OnReadEncoder, OnInitEncoder);
void setup()
{
pinMode(RS485_RE, OUTPUT);
pinMode(RS485_DE, OUTPUT);
Serial4.begin(2500000, SERIAL_8N1);
encoder.init();
Serial.begin(115200);
delay(1000);
}
void loop()
{
encoder.update();
delay(1000);
}
Unfortunately what I’m getting back from the encoder doesn’t seem to make any sense nor conform to what I should expect to be getting back. Here’s the documentation for the encoder https://docs.broadcom.com/doc/AR49-Series-AN starts on Page 39.
Here’s a sample of what I’m getting back:
Response from encoder: 00010000 01101111 11111110
Response from encoder: 00110000 10111111 11111011 10011100
Response from encoder: 00110000 11111000 11111011 11111111
Response from encoder: 00110000 11100000 11111011 11110111
Response from encoder: 00010000 01101111 11111110
Response from encoder: 00010000 11100011 11111011 11110110
Response from encoder: 00110000 11100110 11111011 11110011
Response from encoder: 00110000 11100111 11111011 11110000
Any ideas or suggestions would be greatly appreciated.
I’ve adjusted some of the timings and removed the Serial4.flush() and am now getting consistent values in the first two bytes but they still don’t make any sense to me. According to the documentation the first byte should be the requested command, which in this case should be 0x02. Here’s what I’m getting now.
Response from encoder: 10000011 10000000 01111111 11111011
83 80 7F FB
Response from encoder: 10000011 10000000 11111111 01111111 00111110 11111111
83 80 FF 7F 3E FF
Response from encoder: 10000011 10000000 01111111 11111111
83 80 7F FF
Response from encoder: 10000011 10000000 11111111 01111111 11111110 11111110
83 80 FF 7F FE FE
Response from encoder: 10000011 10000000 01111111 11111110
83 80 7F FE
Response from encoder: 10000011 10000000 01111111 11111000
83 80 7F F8
Response from encoder: 10000011 10000000 11111111 01111111 11111110 11111111
83 80 FF 7F FE FF
Response from encoder: 10000011 10000000 11111011 01111111 11111110 11111110
83 80 FB 7F FE FE
Still chipping away at this. I purchased a logic analyzer so I could verify the signals going back and forth and captured this.
So it seems I’m sending the correct byte 0x02, and the encoder is acknowledging the request along with sending the expect response. At this point I’m trying to figure out why I’m unable to read back the response from the Serial4 object.
With the help of a friend I managed to get this working. The main issue was the 2.5Mbps baud rate. It seems UART4 (PA0, PA1) cannot reliably receive at that speed. Switching to USART2 (PA1, PA2) made it possible to read the encoders response. For good measure I also added a SystemClock_config to match what the original firmware had setup.
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
Error_Handler();
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}
Hopefully that helps others who might run into the same issue.