Ich habe eine Frage wie ich einen Roboclaw Motorcontroller ansteuern kann, dass ich den Wert mit dem er die Geschwindigkeit steuert in zwei Bytes senden kann, die Prüfsumme aber korrekt berechnet wird?
Ich habe bisher folgenden Code benutzt, um einen Byte Wert zu senden. Wie muss ich diesen anpassen um nun zwei Bytes des Geschwindigkeitswertes zu übermitteln?
Aktuell wird der Wert Value zwischen 0 und 127 für die Geschwindigkeit übermittelt:
void command(const byte command, const byte value, const byte address){
data[0] = address; //write address in data array
data[1] = command; //write command for forward/reverse/left/right in data array
data[2] = value; //write movement speed in data array
for(byte index = 0; index < 3; index++){ //create the checksum for the array data[i] with 0 <= i <= 3
crc16(data[index]); //call the function crc16
}
data[3] = crc >> 8; //store checksum in data array
data[4] = crc;
Serial.write(data, sizeof(data)); //send the data array by serial
/*for(byte i = 0; i < 5; i++){
data[i] = '\0';
}*/
crc = 0; //clear the checksum
}
//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {
int i;
crc = crc ^ ((uint16_t)data << 8);
for (i=0; i<8; i++){
if (crc & 0x8000){
crc = (crc << 1) ^ 0x1021;
}
else{
crc <<= 1;
}
}
}
Wenn ich aber nun für Value einen Wert zwischen -32'767 und +32'767 senden möchte? Das müsste gemäss Handbuch als zwei Bytes übertragen werden. Dabei steht dann der negative Wert für die eine Richtung, der positive für die andere Richtung. Kann mir hier einer zeigen wie ich das anpassen muss?
32 - Drive M1 With Signed Duty Cycle
Drive M1 using a duty cycle value. The duty cycle is used to control the speed of the motor
without a quadrature encoder.
Send: [Address, 32, Duty(2 Bytes), CRC(2 bytes)]
Receive: [0xFF]
The duty value is signed and the range is -32767 to +32767 (eg. +-100% duty).
das?
hier aber was anderes:
0 - Drive Forward M1
Drive motor 1 forward. Valid data range is 0 - 127. A value of 127 = full speed forward, 64 =
about half speed forward and 0 = full stop.
Send: [Address, 0, Value, CRC(2 bytes)]
Receive: [0xFF]
Ja, könnte ich auch versuchen, das stimmt!
Der Hintergrund vielleicht: Es gab ein Update des Roboclaw und da funktionieren die Mixing Befehle nicht mehr so wie sie sollen. In manchen Fällen gibts Probleme. Jetzt war die Idee, per Duty Cycles was eine grössere Auflösung hätte zu versuchen. Um die "Mixing" Befehle zu bekommen muss ich sowieso immer M1 und M2 gleichzeitig ansteuern damit er vor/zurück/links/rechts dreht.
Ich versuchs sonst mal mit den normalen M1 und M2 Werten.
Wenn ich es so mit den Duty Werten machen möchte, ginge dies so?
void command(const byte command, const byte value, const byte address){
data[0] = address; //write address in data array
data[1] = command; //write command for forward/reverse/left/right in data array
data[2] = value >> 8; //write movement speed in data array
data[3] = value;
for(byte index = 0; index < 4; index++){ //create the checksum for the array data[i] with 0 <= i <= 4
crc16(data[index]); //call the function crc16
}
data[4] = crc >> 8; //store checksum in data array
data[5] = crc;
Serial.write(data, sizeof(data)); //send the data array by serial
/*for(byte i = 0; i < 6; i++){
data[i] = '\0';
}*/
crc = 0; //clear the checksum
}
//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {
int i;
crc = crc ^ ((uint16_t)data << 8);
for (i=0; i<8; i++){
if (crc & 0x8000){
crc = (crc << 1) ^ 0x1021;
}
else{
crc <<= 1;
}
}
}
Alternativ können auch mehrere Datentypen denselben Speicherbereich adressieren, siehe union mix_t.
Als Anregung ungetestet:
const uint8_t BYTEZAHL = 6;
union {
uint8_t data[BYTEZAHL];
struct {
uint8_t address;
uint8_t command;
uint16_t value;
uint16_t crc;
};
} mix;
void command(const byte command, const uint16_t value, const byte address) {
mix.address = address; //write address in data array
mix.command = command; //write command for forward/reverse/left/right in data array
mix.value = value; //write movement speed in data array
for (byte index = 0; index < 4; index++) { //create the checksum for the array data[i] with 0 <= i <= 4
crc16(mix.data[index]); //call the function crc16
}
mix.crc = crc; //store checksum in data array
Serial.write(mix.data, BYTEZAHL); //send the data array by serial
crc = 0; //clear the checksum
}
bei Adruino IDE (für AVR Boards) int und int16_t ist dasselbe. nicht bei ESPs und STM32. aber die sind nicht für Neulinge. aber ich finde auch vorteilhaft u/intXX_t zu schreiben.