Packet Serial without library

General discussion of using Roboclaw motor controllers
Post Reply
stef308
Posts: 10
Joined: Sat Jul 10, 2021 7:40 am
Packet Serial without library

Post by stef308 »

I have tried to write the code for sending commands with an Arduino Uno over packet serial with the checksum without the library. The reason for that is, because I have tried to use the example and copied the same commands into my code to get it working. The example seems to work, but with the same commands in my code it does not. Also I would like to understand the code I make. With a library it is not really visible what the code really makes. Perhaps someone could help me to get my code working with the Roboclaw 2x60?
Here I will post the parts of the code how I send and make the checksum, but as I have said, somewhere is an issue and need some help to fix it:

const unsigned long Baudrate = 38400;
const byte SpeedFDLR = 100;

#define RoboclawRXpin 6
#define RoboclawTXpin 5

byte mapFDLR = 0;
byte data[5];
uint16_t crc = 0;

#include <SoftwareSerial.h>

#define address 0x80

SoftwareSerial serial2(RoboclawRXpin, RoboclawTXpin);


void setup() {

pinMode(RoboclawRXpin, INPUT);
pinMode(RoboclawTXpin, OUTPUT);

serial2.begin(Baudrate);
}


void loop() {

if(FDLR != lastFDLR && joybut == HIGH){
if(0 <= FDLR && FDLR < 87){
mapFDLR = map(FDLR, 90, 0, 0, SpeedFDLR);
Serial.println(mapFDLR);
data[0] = address;
data[1] = 10;
data[2] = mapFDLR;
for(byte index = 0; index <= 3; index++){
crc16(data[index]);
}
crc = getCRC();
data[3] = crc >> 8;
data[4] = crc;
serial2.write(data, sizeof(data));
}
lastFDLR = FDLR;
crc = 0;
}
}

//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;
}
}
}

uint16_t getCRC() {
return crc;
}

Every help and ideas are appreciated!

Regards

Stef
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Packet Serial without library

Post by Basicmicro Support »

I have allowed your post, but support will not be able to help you with your code. We specifically provide the library(with source code) because this is a non-trivial thing to do.

Instead of trying to write your own code, I recommend you walk through our library. The code to handle actually communications is a small part of the whole library(at the top of the file).
stef308
Posts: 10
Joined: Sat Jul 10, 2021 7:40 am
Re: Packet Serial without library

Post by stef308 »

I have got it working. Since around three months it works perfectly and is a lot smaller in its size as the whole library. The issue was, to declare at the beginning in the setup a forward/backward and right/left command to initialize the motors. I have made it a bit shorter and now that is the working code for me:

Code: Select all

 /**SETTINGS**/
const unsigned long Baudrate = 38400;    //starts serial port for Roboclaw

const byte addressFD = 0x80;             //address for Roboclaw from motors, address 128

const byte SpeedFDLR = 50;               //set the maximum, normal speed for foot drive left/right (0=stop, 127=full speed, 0-127 slower to faster)
const byte SpeedFDUD = 50;               //set the maximum, normal speed for foot drive forward/backward (0=stop, 127=full speed, 0-127 slower to faster)

const byte SpeedFDLRfast = 75;           //set the maximum, fast speed for foot drive left/right (if joystick is pressed down) (0=stop, 127=full speed, 0-127 slower to faster)
const byte SpeedFDUDfast = 75;           //set the maximum, fast speed for foot drive forward/backward (if joystick is pressed down) (0=stop, 127=full speed, 0-127 slower to faster)

 //Definition of designations for reading signals (signals to be received)
byte FDLR = 0;   //Foot drive left/right
byte FDUD = 0;   //Foot drive forward/backward
byte joybut = 1; //Foot drive joystick-button

 //Definition of designations for storing signals (cache)
byte data[5];        //create array for packet serial (motors)
uint16_t crc = 0;    //checksum crc

byte lastFDLR = 0;   //last status from foot drive, left/right
byte lastFDUD = 0;   //last status from foot drive, forward/backward
byte mapFDLR = 0;    //converted value FDLR (foot drive left/right) for the dc motor
byte mapFDUD = 0;    //converted value FDUD (foot drive forward/backward)( for the dc motor

unsigned long interval = 0;        //waiting period in milliseconds for data to send to the Roboclaw
unsigned long previousMillis = 0;  //stores past time


void setup() {

  Serial.begin(Baudrate);       //starts serial port with a baudrate by "Baudrate" (b/s)
  
  //initialization of the feet motors on startup
  command(10,0, addressFD);   //command for turn right in mix mode, stop movement, address
  command(8,0, addressFD);    //command for forward in mix mode, stop movement, address
  
}

void loop() {

//Foot drive
  if(FDLR != lastFDLR && joybut == HIGH && millis() - previousMillis >= interval){                 //if FDLR (foot drive left/right) not equal to lastFDLR and joybut is equal to HIGH (not pressed), then make...
    if(FDLR < 87){                                        //if FDLR is between 0 and 90, then make...
      mapFDLR = map(FDLR, 90, 0, 0, SpeedFDLR);           //read value from FDLR, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedFDLR and store it to mapFDLR
      command(10,mapFDLR, addressFD);                     //command for turn right in mix mode, movement mapFDLR, address
    }
    else if(180 >= FDLR && FDLR > 93){                    //if FDLR is between 90 and 180, then make...
      mapFDLR = map(FDLR, 90, 180, 0, SpeedFDLR);         //read value from FDLR, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedFDLR and store it to mapFDLR
      command(11,mapFDLR, addressFD);                     //command for turn left in mix mode, movement mapFDLR, address
    }
    else if(87 <= FDLR && FDLR <= 93){                    //if FDLR is 90, then make...
      command(10,0, addressFD);                           //command for turn right in mix mode, stop movement, address
    }
    lastFDLR = FDLR;                                      //stores FDLR on lastFDLR
  }
  

  if(FDUD != lastFDUD && joybut == HIGH && millis() - previousMillis >= interval){                 //if FDUD (foot drive forward/backward) not equal to lastFDUD and joybut is equal to HIGH (not pressed), then make...
    if(FDUD < 87){                                        //if FDUD is between 0 and 90, then make...
      mapFDUD = map(FDUD, 90, 0, 0, SpeedFDUD);           //read value from FDUD, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedFDUD and store it to mapFDUD
      command(8,mapFDUD, addressFD);                      //command for forward in mix mode, movement mapFDUD, address
    }
    else if(180 >= FDUD && FDUD > 93){                    //if FDUD is between 90 and 180, then make...
      mapFDUD = map(FDUD, 90, 180, 0, SpeedFDUD);         //read value from FDUD, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedFDUD and store it to mapFDUD
      command(9,mapFDUD, addressFD);                      //command for backward in mix mode, movement mapFDUD, address
    }
    else if(87 <= FDUD && FDUD <= 93){                    //if FDUD is 90, then make...
      command(8,0, addressFD);                            //command for forward in mix mode, stop movement, address
    }
    lastFDUD = FDUD;                                      //stores FDUD on lastFDUD
  }

}


//Function for driving the motors over serial
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
    previousMillis = millis();
  /*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;
    }
  }
}
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Packet Serial without library

Post by Basicmicro Support »

One suggestion. I'd recommend people modify the library if they are size constrained rather than write something from scratch. There is a lot of error handling code in the libraries we write for a reason. You can easily remove all the unused commands but I'd recommend keeping the underlying functions that handle communications.

Post Reply