Servo Serial Bus (lx16a)
Each servo can set the ID number for the identification of the servo, the ID defaults to 1.
240 degree rotation. Controllable angle range from 0 to 240 degrees, Excellent linearity, precision control. Can be rotated within 360 degrees when power off.
Dual ball bearing: one is the driving shaft, one is the assistant shaft(support role)
Specifications:
Weight: 52g(1.8oz)
Dimension: 1.78*0.97*1.38inch
Speed: 0.18sec/60° 6V; 0.16sec/60°7.4V
Servo accuracy: 0.24°
Torque: 15 kg·cm (208 oz·in) 6.6V; 17 kg·cm (236 oz·in) 7.4V
Minimum working current: 1A
Servo ID: 0~253
Storage users' parameter setting after power off: support
Manual:
Dropbox documentation:
https://www.dropbox.com/sh/b3v81sb9nwir16q/AACkK-tg0q39fKJZcSl-YrqOa/LX-16A%20Bus%20Servo?dl=0
Arduino code:
#include <SoftwareSerial.h>
#define GET_LOW_BYTE(A) (uint8_t)((A))
//Macro function get lower 8 bits of A
#define GET_HIGH_BYTE(A) (uint8_t)((A) >> 8)
//Macro function get higher 8 bits of A
#define BYTE_TO_HW(A, B) ((((uint16_t)(A)) << 8) | (uint8_t)(B))
//Macro Function put A as higher 8 bits B as lower 8 bits which amalgamated into 16 bits integer
#define LOBOT_SERVO_FRAME_HEADER 0x55
#define LOBOT_SERVO_MOVE_TIME_WRITE 1
#define LOBOT_SERVO_MOVE_TIME_READ 2
#define LOBOT_SERVO_MOVE_TIME_WAIT_WRITE 7
#define LOBOT_SERVO_MOVE_TIME_WAIT_READ 8
#define LOBOT_SERVO_MOVE_START 11
#define LOBOT_SERVO_MOVE_STOP 12
#define LOBOT_SERVO_ID_WRITE 13
#define LOBOT_SERVO_ID_READ 14
#define LOBOT_SERVO_ANGLE_OFFSET_ADJUST 17
#define LOBOT_SERVO_ANGLE_OFFSET_WRITE 18
#define LOBOT_SERVO_ANGLE_OFFSET_READ 19
#define LOBOT_SERVO_ANGLE_LIMIT_WRITE 20
#define LOBOT_SERVO_ANGLE_LIMIT_READ 21
#define LOBOT_SERVO_VIN_LIMIT_WRITE 22
#define LOBOT_SERVO_VIN_LIMIT_READ 23
#define LOBOT_SERVO_TEMP_MAX_LIMIT_WRITE 24
#define LOBOT_SERVO_TEMP_MAX_LIMIT_READ 25
#define LOBOT_SERVO_TEMP_READ 26
#define LOBOT_SERVO_VIN_READ 27
#define LOBOT_SERVO_POS_READ 28
#define LOBOT_SERVO_OR_MOTOR_MODE_WRITE 29
#define LOBOT_SERVO_OR_MOTOR_MODE_READ 30
#define LOBOT_SERVO_LOAD_OR_UNLOAD_WRITE 31
#define LOBOT_SERVO_LOAD_OR_UNLOAD_READ 32
#define LOBOT_SERVO_LED_CTRL_WRITE 33
#define LOBOT_SERVO_LED_CTRL_READ 34
#define LOBOT_SERVO_LED_ERROR_WRITE 35
#define LOBOT_SERVO_LED_ERROR_READ 36
//#define LOBOT_DEBUG 1 /*Debug :print debug value*/
byte LobotCheckSum(byte buf[])
{
byte i;
uint16_t temp = 0;
for (i = 2; i < buf[3] + 2; i++) {
temp += buf[i];
}
temp = ~temp;
i = (byte)temp;
return i;
}
void LobotSerialServoMove(SoftwareSerial &SerialX, uint8_t id, int16_t position, uint16_t time)
{
byte buf[10];
/*if(position < 0)
position = 0;
if(position > 1000)
position = 1000;*/
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 7;
buf[4] = LOBOT_SERVO_MOVE_TIME_WRITE;
buf[5] = GET_LOW_BYTE(position);
buf[6] = GET_HIGH_BYTE(position);
buf[7] = GET_LOW_BYTE(time);
buf[8] = GET_HIGH_BYTE(time);
buf[9] = LobotCheckSum(buf);
SerialX.write(buf, 10);
}
void LobotSerialServoStopMove(SoftwareSerial &SerialX, uint8_t id)
{
byte buf[6];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 3;
buf[4] = LOBOT_SERVO_MOVE_STOP;
buf[5] = LobotCheckSum(buf);
SerialX.write(buf, 6);
}
void LobotSerialServoSetID(SoftwareSerial &SerialX, uint8_t oldID, uint8_t newID)
{
byte buf[7];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = oldID;
buf[3] = 4;
buf[4] = LOBOT_SERVO_ID_WRITE;
buf[5] = newID;
buf[6] = LobotCheckSum(buf);
SerialX.write(buf, 7);
#ifdef LOBOT_DEBUG
Serial.println("LOBOT SERVO ID WRITE");
int debug_value_i = 0;
for (debug_value_i = 0; debug_value_i < buf[3] + 3; debug_value_i++)
{
Serial.print(buf[debug_value_i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
}
void LobotSerialServoSetMode(SoftwareSerial &SerialX, uint8_t id, uint8_t Mode, int16_t Speed)
{
byte buf[10];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 7;
buf[4] = LOBOT_SERVO_OR_MOTOR_MODE_WRITE;
buf[5] = Mode;
buf[6] = 0;
buf[7] = GET_LOW_BYTE((uint16_t)Speed);
buf[8] = GET_HIGH_BYTE((uint16_t)Speed);
buf[9] = LobotCheckSum(buf);
#ifdef LOBOT_DEBUG
Serial.println("LOBOT SERVO Set Mode");
int debug_value_i = 0;
for (debug_value_i = 0; debug_value_i < buf[3] + 3; debug_value_i++)
{
Serial.print(buf[debug_value_i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
SerialX.write(buf, 10);
}
void LobotSerialServoLoad(SoftwareSerial &SerialX, uint8_t id)
{
byte buf[7];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 4;
buf[4] = LOBOT_SERVO_LOAD_OR_UNLOAD_WRITE;
buf[5] = 1;
buf[6] = LobotCheckSum(buf);
SerialX.write(buf, 7);
#ifdef LOBOT_DEBUG
Serial.println("LOBOT SERVO LOAD WRITE");
int debug_value_i = 0;
for (debug_value_i = 0; debug_value_i < buf[3] + 3; debug_value_i++)
{
Serial.print(buf[debug_value_i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
}
void LobotSerialServoUnload(SoftwareSerial &SerialX, uint8_t id)
{
byte buf[7];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 4;
buf[4] = LOBOT_SERVO_LOAD_OR_UNLOAD_WRITE;
buf[5] = 0;
buf[6] = LobotCheckSum(buf);
SerialX.write(buf, 7);
#ifdef LOBOT_DEBUG
Serial.println("LOBOT SERVO LOAD WRITE");
int debug_value_i = 0;
for (debug_value_i = 0; debug_value_i < buf[3] + 3; debug_value_i++)
{
Serial.print(buf[debug_value_i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
}
int LobotSerialServoReceiveHandle(SoftwareSerial &SerialX, byte *ret)
{
bool frameStarted = false;
bool receiveFinished = false;
byte frameCount = 0;
byte dataCount = 0;
byte dataLength = 2;
byte rxBuf;
byte recvBuf[32];
byte i;
while (SerialX.available()) {
rxBuf = SerialX.read();
delayMicroseconds(100);
if (!frameStarted) {
if (rxBuf == LOBOT_SERVO_FRAME_HEADER) {
frameCount++;
if (frameCount == 2) {
frameCount = 0;
frameStarted = true;
dataCount = 1;
}
}
else {
frameStarted = false;
dataCount = 0;
frameCount = 0;
}
}
if (frameStarted) {
recvBuf[dataCount] = (uint8_t)rxBuf;
if (dataCount == 3) {
dataLength = recvBuf[dataCount];
if (dataLength < 3 || dataCount > 7) {
dataLength = 2;
frameStarted = false;
}
}
dataCount++;
if (dataCount == dataLength + 3) {
#ifdef LOBOT_DEBUG
Serial.print("RECEIVE DATA:");
for (i = 0; i < dataCount; i++) {
Serial.print(recvBuf[i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
if (LobotCheckSum(recvBuf) == recvBuf[dataCount - 1]) {
#ifdef LOBOT_DEBUG
Serial.println("Check SUM OK!!");
Serial.println("");
#endif
frameStarted = false;
memcpy(ret, recvBuf + 4, dataLength);
return 1;
}
return -1;
}
}
}
}
int LobotSerialServoReadPosition(SoftwareSerial &SerialX, uint8_t id)
{
int count = 10000;
int ret;
byte buf[6];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 3;
buf[4] = LOBOT_SERVO_POS_READ;
buf[5] = LobotCheckSum(buf);
#ifdef LOBOT_DEBUG
Serial.println("LOBOT SERVO Pos READ");
int debug_value_i = 0;
for (debug_value_i = 0; debug_value_i < buf[3] + 3; debug_value_i++)
{
Serial.print(buf[debug_value_i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
while (SerialX.available())
SerialX.read();
SerialX.write(buf, 6);
while (!SerialX.available()) {
count -= 1;
if (count < 0)
return -1;
}
if (LobotSerialServoReceiveHandle(SerialX, buf) > 0)
ret = BYTE_TO_HW(buf[2], buf[1]);
else
ret = -1;
#ifdef LOBOT_DEBUG
Serial.println(ret);
#endif
return ret;
}
int LobotSerialServoReadVin(SoftwareSerial &SerialX, uint8_t id)
{
int count = 10000;
int ret;
byte buf[6];
buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
buf[2] = id;
buf[3] = 3;
buf[4] = LOBOT_SERVO_VIN_READ;
buf[5] = LobotCheckSum(buf);
#ifdef LOBOT_DEBUG
Serial.println("LOBOT SERVO VIN READ");
int debug_value_i = 0;
for (debug_value_i = 0; debug_value_i < buf[3] + 3; debug_value_i++)
{
Serial.print(buf[debug_value_i], HEX);
Serial.print(":");
}
Serial.println(" ");
#endif
while (SerialX.available())
SerialX.read();
SerialX.write(buf, 6);
while (!SerialX.available()) {
count -= 1;
if (count < 0)
return -2048;
}
if (LobotSerialServoReceiveHandle(SerialX, buf) > 0)
ret = (int16_t)BYTE_TO_HW(buf[2], buf[1]);
else
ret = -2048;
#ifdef LOBOT_DEBUG
Serial.println(ret);
#endif
return ret;
}
#define ID1 1
#define ID2 2
SoftwareSerial servoSerial(10, 11); // RX, TX
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
servoSerial.begin(115200);
delay(1000);
}
void loop() {
LobotSerialServoMove(servoSerial, ID1, 0, 500);
delay(3000);
LobotSerialServoMove(servoSerial, ID1, 1000, 500);
delay(3000);
}
Python
Download the files below and do:
Open runThisTest.py
Change the name of the serial port
run with python3 runThisTest.py
https://github.com/RoboLabHub/LewanSoul