Hi All,
I've been programming on a Arduino Uno R3 for about 2 months (a few hours a week learning / researching and coding). I have a Nema 17 stepper motor that I can control well using an A4988 or TB6600 driver. I recently undertook a project to read and use the data from the stepper motor's absolute encoder. The encoder can communicate digitally via RS485 MODBUS with the following specs:
A | B | C | D | E | F | G | H | I | J | K |
---|---|---|---|---|---|---|---|---|---|---|
Word Address | Function | Word Length | Word 0 | Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 | Word 7 |
0000h | Encoder Data | 3 | Angle Data | Turn Count | Temperature | ---- | ---- | ---- | ---- | ---- |
1000h | Zero offset | 1 | 01/02 | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
Angle data
Ranges from 0-65535. Example: HEX: C000 = 49152 angle value
Zero Offset
When 1 is written in zero offset, it will change the current position to main data angle = muti turn count = 0
When 2 is written in zero offset, magnetic sensor will adjust zero point only with main shaft, therefore, main angle data = 0
UART Specification
Data bit length: 8 bit
Data Transfer Direction: LSB
Parity: None
Stop bit : 1 bit
Baud rate: 115200 bps
MODBUS Specification
NODE: 01 fixed
Communication Mode: ASCII
Half duplex transmit/receive switching time: Max 1ms
(1/115200[bps] * 10[bit] * 1000 *3.5[word] = 0.304ms, expect to have enough margin)
Endianness (word, double-word): Big endianness, but CRC is fixed with little endianess
Arduino Uno R3 with MAX485 hookup is as follows:
MAX485:
B-> RS485- from encoder
A-> RS485+ from encoder
VCC -> 5V on Arduino Uno
GND -> GND on Arduino Uno
DI -> 7 on Arduino Uno
DE: -> 5 on Arduino Uno
RE: -> 5 on Arduino Uno
RO: -> 6 on Arduino Uno.
Code
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
#define ENABLE485_RX 6 // EIA-485 serial receive pin
#define ENABLE485_TX 7 // EIA-485 serial transmit pin
#define MAX485_DE 5
// instantiate ModbusMaster object
ModbusMaster node;
SoftwareSerial RS485Serial(ENABLE485_RX, ENABLE485_TX); // RX, TX
void preTransmission()
{
digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
digitalWrite(MAX485_DE, 0);
}
void setup()
{
pinMode(MAX485_DE, OUTPUT);
digitalWrite(MAX485_DE, 0);
Serial.begin(9600);
RS485Serial.begin(115200);
node.begin(1, RS485Serial);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop()
{
uint8_t result;
uint16_t data[6];
// Read 02 registers starting at 03)
result = node.readHoldingRegisters(0x03,2);
Serial.println(node.getResponseBuffer(0x00));
Serial.println(node.getResponseBuffer(0x01));
}
Through a COM port sniffer, the encoder's output looks like this:
Modbus Request (COM3)
Address: 1
Function: 3 (0x03) - Read Holding Registers
Starting Address: 0
Quantity: 3
Checksum: 0x00f9 - OK
Modbus Response (COM3)
Address: 1
Function: 3 (0x03) - Read Holding Registers
Byte Count: 6
Values: ff 54 03 e7 00 ef
Register0: 65364
Register1: 999
Register2: 239
Checksum: 0x00ca - OK
Register 0 = Word0 angle data
Register1 = Word1 turn count data
Register2 = Word2 temperature data
I can read and understand the encoder data via a RS485 to USB converter cable. I am trying to have the Arduino read the same encoder RS485 data through a MAX485 board (Amazon.com) so that I can use the encoder rotational information when controlling the Nema 17 stepper motor. I have been researching for more than a week and tried numerous test codes but have not read the encoder data correctly yet.
I would greatly appreciate your guidance.
Thank you,
Robert