commit fb94f7981b4f8422f6000e460e462908ba1c6c3c Author: Samuel Date: Sun Aug 10 16:32:27 2025 +0200 Ping et lecture des registres lorsqu'un servo avec l'ID 1 est trouvé diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..e69de29 diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..6f10430 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,7 @@ +[env] +platform = raspberrypi +framework = arduino + +[env:pico] +board = pico + diff --git a/src/HLSCL.cpp b/src/HLSCL.cpp new file mode 100644 index 0000000..fe8230a --- /dev/null +++ b/src/HLSCL.cpp @@ -0,0 +1,260 @@ +/* + * HLSCL.cpp + * 飞特HTS/HLS系列串行舵机应用层程序 + * 日期: 2024.11.21 + * 作者: txl + */ + +#include "HLSCL.h" + +HLSCL::HLSCL() +{ + End = 0; +} + +HLSCL::HLSCL(u8 End):SCSerial(End) +{ +} + +HLSCL::HLSCL(u8 End, u8 Level):SCSerial(End, Level) +{ +} + +int HLSCL::WritePosEx(u8 ID, s16 Position, u16 Speed, u8 ACC, u16 Torque) +{ + if(Position<0){ + Position = -Position; + Position |= (1<<15); + } + u8 bBuf[7]; + bBuf[0] = ACC; + Host2SCS(bBuf+1, bBuf+2, Position); + Host2SCS(bBuf+3, bBuf+4, Torque); + Host2SCS(bBuf+5, bBuf+6, Speed); + + return genWrite(ID, HLSCL_ACC, bBuf, 7); +} + +int HLSCL::RegWritePosEx(u8 ID, s16 Position, u16 Speed, u8 ACC, u16 Torque) +{ + if(Position<0){ + Position = -Position; + Position |= (1<<15); + } + u8 bBuf[7]; + bBuf[0] = ACC; + Host2SCS(bBuf+1, bBuf+2, Position); + Host2SCS(bBuf+3, bBuf+4, Torque); + Host2SCS(bBuf+5, bBuf+6, Speed); + + return regWrite(ID, HLSCL_ACC, bBuf, 7); +} + +void HLSCL::SyncWritePosEx(u8 ID[], u8 IDN, s16 Position[], u16 Speed[], u8 ACC[], u16 Torque[]) +{ + u8 offbuf[7*IDN]; + for(u8 i = 0; i +#include "SCS.h" + +SCS::SCS() +{ + Level = 1;//除广播指令所有指令返回应答 + u8Status = 0; +} + +SCS::SCS(u8 End) +{ + Level = 1; + this->End = End; + u8Status = 0; +} + +SCS::SCS(u8 End, u8 Level) +{ + this->Level = Level; + this->End = End; + u8Status = 0; +} + +//1个16位数拆分为2个8位数 +//DataL为低位,DataH为高位 +void SCS::Host2SCS(u8 *DataL, u8* DataH, u16 Data) +{ + if(End){ + *DataL = (Data>>8); + *DataH = (Data&0xff); + }else{ + *DataH = (Data>>8); + *DataL = (Data&0xff); + } +} + +//2个8位数组合为1个16位数 +//DataL为低位,DataH为高位 +u16 SCS::SCS2Host(u8 DataL, u8 DataH) +{ + u16 Data; + if(End){ + Data = DataL; + Data<<=8; + Data |= DataH; + }else{ + Data = DataH; + Data<<=8; + Data |= DataL; + } + return Data; +} + +void SCS::writeBuf(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen, u8 Fun) +{ + u8 msgLen = 2; + u8 bBuf[6]; + u8 CheckSum = 0; + bBuf[0] = 0xff; + bBuf[1] = 0xff; + bBuf[2] = ID; + bBuf[4] = Fun; + if(nDat){ + msgLen += nLen + 1; + bBuf[3] = msgLen; + bBuf[5] = MemAddr; + writeSCS(bBuf, 6); + + }else{ + bBuf[3] = msgLen; + writeSCS(bBuf, 5); + } + CheckSum = ID + msgLen + Fun + MemAddr; + u8 i = 0; + if(nDat){ + for(i=0; i10){ + return 0; + } + } + return 1; +} + +int SCS::Ack(u8 ID) +{ + u8Error = 0; + if(ID!=0xfe && Level){ + if(!checkHead()){ + u8Error = ERR_NO_REPLY; + return 0; + } + u8Status = 0; + u8 bBuf[4]; + if(readSCS(bBuf, 4)!=4){ + u8Error = ERR_NO_REPLY; + return 0; + } + if(bBuf[0]!=ID){ + u8Error = ERR_SLAVE_ID; + return 0; + } + if(bBuf[1]!=2){ + u8Error = ERR_BUFF_LEN; + return 0; + } + u8 calSum = ~(bBuf[0]+bBuf[1]+bBuf[2]); + if(calSum!=bBuf[3]){ + u8Error = ERR_CRC_CMP; + return 0; + } + u8Status = bBuf[2]; + } + return 1; +} + +int SCS::syncReadPacketTx(u8 ID[], u8 IDN, u8 MemAddr, u8 nLen) +{ + rFlushSCS(); + syncReadRxPacketLen = nLen; + u8 checkSum = (4+0xfe) + IDN + MemAddr + nLen + INST_SYNC_READ; + u8 i; + writeSCS(0xff); + writeSCS(0xff); + writeSCS(0xfe); + writeSCS(IDN+4); + writeSCS(INST_SYNC_READ); + writeSCS(MemAddr); + writeSCS(nLen); + for(i=0; i=syncReadRxPacketLen){ + u8Error = ERR_BUFF_LEN; + return -1; + } + return syncReadRxPacket[syncReadRxPacketIndex++]; +} + +int SCS::syncReadRxPacketToWrod(u8 negBit) +{ + if((syncReadRxPacketIndex+1)>=syncReadRxPacketLen){ + u8Error = ERR_BUFF_LEN; + return -1; + } + int Word = SCS2Host(syncReadRxPacket[syncReadRxPacketIndex], syncReadRxPacket[syncReadRxPacketIndex+1]); + syncReadRxPacketIndex += 2; + if(negBit){ + if(Word&(1<read(); + if(ComData!=-1){ + if(nDat){ + nDat[Size] = ComData; + } + Size++; + } + if(Size>=nLen){ + break; + } + t_user = millis() - t_begin; + if(t_user>TimeOut){ + break; + } + } + return Size; +} + +int SCSerial::readSCS(unsigned char *nDat, int nLen) +{ + int Size = 0; + int ComData; + unsigned long t_begin = millis(); + unsigned long t_user; + while(1){ + ComData = pSerial->read(); + if(ComData!=-1){ + if(nDat){ + nDat[Size] = ComData; + } + Size++; + t_begin = millis(); + } + if(Size>=nLen){ + break; + } + t_user = millis() - t_begin; + if(t_user>IOTimeOut){ + break; + } + } + return Size; +} + +int SCSerial::writeSCS(unsigned char *nDat, int nLen) +{ + if(nDat==NULL){ + return 0; + } + return pSerial->write(nDat, nLen); +} + +int SCSerial::writeSCS(unsigned char bDat) +{ + return pSerial->write(&bDat, 1); +} + +void SCSerial::rFlushSCS() +{ + while(pSerial->read()!=-1); +} + +void SCSerial::wFlushSCS() +{ +} \ No newline at end of file diff --git a/src/SCSerial.h b/src/SCSerial.h new file mode 100644 index 0000000..402b262 --- /dev/null +++ b/src/SCSerial.h @@ -0,0 +1,38 @@ +/* + * SCSerial.h + * 飞特串行舵机硬件接口层程序 + * 日期: 2024.11.22 + * 作者: txl + */ + +#ifndef _SCSERIAL_H +#define _SCSERIAL_H + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#include "SCS.h" + +class SCSerial : public SCS +{ +public: + SCSerial(); + SCSerial(u8 End); + SCSerial(u8 End, u8 Level); + +protected: + int writeSCS(unsigned char *nDat, int nLen);//输出nLen字节 + int readSCS(unsigned char *nDat, int nLen);//输入nLen字节 + int readSCS(unsigned char *nDat, int nLen, unsigned long TimeOut); + int writeSCS(unsigned char bDat);//输出1字节 + void rFlushSCS();// + void wFlushSCS();// +public: + unsigned long IOTimeOut;//输入输出超时 + HardwareSerial *pSerial;//串口指针 +}; + +#endif \ No newline at end of file diff --git a/src/SCServo.h b/src/SCServo.h new file mode 100644 index 0000000..090dea6 --- /dev/null +++ b/src/SCServo.h @@ -0,0 +1,15 @@ +/* + * SCServo.h + * 飞特串行舵机接口 + * 日期: 2024.11.24 + * 作者: txl + */ + +#ifndef _SCSERVO_H +#define _SCSERVO_H + +#include "SCSCL.h" +#include "SMS_STS.h" +#include "HLSCL.h" + +#endif \ No newline at end of file diff --git a/src/SMS_STS.cpp b/src/SMS_STS.cpp new file mode 100644 index 0000000..d79e919 --- /dev/null +++ b/src/SMS_STS.cpp @@ -0,0 +1,249 @@ +/* + * SMS_STS.cpp + * 飞特SMS_STS系列串行舵机应用层程序 + * 日期: 2024.11.21 + * 作者: txl + */ + +#include "SMS_STS.h" + +SMS_STS::SMS_STS() +{ + End = 0; +} + +SMS_STS::SMS_STS(u8 End):SCSerial(End) +{ +} + +SMS_STS::SMS_STS(u8 End, u8 Level):SCSerial(End, Level) +{ +} + +int SMS_STS::WritePosEx(u8 ID, s16 Position, u16 Speed, u8 ACC) +{ + if(Position<0){ + Position = -Position; + Position |= (1<<15); + } + u8 bBuf[7]; + bBuf[0] = ACC; + Host2SCS(bBuf+1, bBuf+2, Position); + Host2SCS(bBuf+3, bBuf+4, 0); + Host2SCS(bBuf+5, bBuf+6, Speed); + + return genWrite(ID, SMS_STS_ACC, bBuf, 7); +} + +int SMS_STS::RegWritePosEx(u8 ID, s16 Position, u16 Speed, u8 ACC) +{ + if(Position<0){ + Position = -Position; + Position |= (1<<15); + } + u8 bBuf[7]; + bBuf[0] = ACC; + Host2SCS(bBuf+1, bBuf+2, Position); + Host2SCS(bBuf+3, bBuf+4, 0); + Host2SCS(bBuf+5, bBuf+6, Speed); + + return regWrite(ID, SMS_STS_ACC, bBuf, 7); +} + +void SMS_STS::SyncWritePosEx(u8 ID[], u8 IDN, s16 Position[], u16 Speed[], u8 ACC[]) +{ + u8 offbuf[7*IDN]; + for(u8 i = 0; i +#include "SCServo.h" + +SMS_STS sms_sts; + +void test_ping(); +void lire_tous_les_registres(int servo_id); + + +char registre_description[70][100]={ + "Version majeure du firmware", + "Version mineure du firmware", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +// the setup routine runs once when you press reset: +void setup() { + // initialize the digital pin as an output. + pinMode(LED_BUILTIN, OUTPUT); + Serial.begin(115200);//sts舵机波特率1000000 + Serial1.begin(1000000);//sts舵机波特率1000000 + sms_sts.pSerial = &Serial1; + +} + +// the loop routine runs over and over again forever: +void loop() { + digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) + test_ping(); + digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW + test_ping(); +} + +void test_ping() +{ + int ID = sms_sts.Ping(1); + static int found = 0; + if(ID!=-1){ + Serial.print("Servo ID:"); + Serial.println(ID); + if(found == 0){ + found = 1; + lire_tous_les_registres(ID); + } + delay(100); + }else{ + Serial.print("Ping servo ID error!\n"); + found = 0; + delay(2000); + } +} + +int lire_registre(int servo_id, int registre_adresse){ + return sms_sts.readByte(servo_id, registre_adresse); // Resolution à 1 +} + +void lire_tous_les_registres(int servo_id){ + char message[200]=""; + for (int i=0; i<0x46; i++){ + sprintf(message, "registre 0x%x: %d\t\t%s\n", i, lire_registre(servo_id, i), registre_description[i]); + Serial.print(message); + } + +}