Category Archives: Physical Computing

Arduino, Raspberry-Pi, ROS

Arduino Code for determining QPPS setting for RoboClaw Motor Controller

If you use the RoboClaw Motor Controller, at some point you’ll need to determine the QPPS if you’re using wheel encoders. QPPS stands for “quadrature pulses per second” and is used in the motor controller for establish the maximum speed the motor can be driven at and is also used in the calculation of all the speed, distance, and position commands that are part of the Arduino Library.

While you can mathematically calculate it based on your particular motors and encoders, the ideal result will probably not match the actual results. Thus, we need to write some code that will run the motors at full speed and display the experimental results.

For example, I’m using Pololu 6V 75:1 ratio motors with 48 cpr encoders. This motor is specced at 130 RPM with a 75:1 reduction and the encoders count 48 clicks per revolution. Thus (130 rpm * 75 * 48)/(60 seconds per minute) = 7800 qpps in theory.

I’ve found however when I drive the motor controller a full speed, I  don’t get a full 6V into each motor, I’m getting about 5.82v which means my qpps is not going to match the theoretical.

So, basically, we want to run the motors at ‘full speed’ using the ForwardM1 and ForwardM2 motor commands and then read back the Speed using the ReadSpeedM1 and ReadSpeedM2 commands. These will report back the speed in QPPS.

This code uses a single pole filter to essentially average out the results. Because of this, you need to let the motors run a bit to get to a converged value. At some point, the speed will stop going up and will then fluctuate around a value, going up and down slightly. I interpret this as my maximum experimental QPPS to use with the RoboClaw motor controller.


#include "BMSerial.h"
#include "RoboClaw.h"

// Roboclaw is set to Serial Packet Mode
#define address 0x80

BMSerial terminal(0,1);      // this is usb cable from Arduino to computer
RoboClaw roboclaw(11,10);    // serial connection to RoboClaw
long avgSpeedM1, avgSpeedM2;
// alpha is used to filter the results
float alpha = .10; // .1 = data smoothing single pole filter setting.

void setup() {
    terminal.begin(9600);
    roboclaw.begin(38400);
}

void displayspeed(void) {
    uint8_t status;
    bool valid;

    long enc1= roboclaw.ReadEncM1(address, &status, &valid);
    if(valid){
        terminal.print("Encoder1:");
        terminal.print(enc1,DEC);
        terminal.print(" ");
    }
    long enc2 = roboclaw.ReadEncM2(address, &status, &valid);
    if(valid){
        terminal.print("Encoder2:");
        terminal.print(enc2,DEC);
        terminal.print(" ");
    }
    long speed1 = roboclaw.ReadSpeedM1(address, &status, &valid);
    // filter the speed. You'll need to run the motors for a bit
    // in order to get the filtered values to 'settle down'
    // after about 20 seconds of my motors at full speed I got
    // converged results.
    avgSpeedM1 = avgSpeedM1 * (1-alpha) + speed1 * alpha;

    if(valid){
        terminal.print("Avg Speed1:");
        terminal.print(avgSpeedM1,DEC);
        terminal.print(" ");
    }

    long speed2 = roboclaw.ReadSpeedM2(address, &status, &valid);
    avgSpeedM2 = avgSpeedM2 * (1-alpha) + speed2 * alpha;

    if(valid){
        terminal.print("Avg Speed2:");
        terminal.print(avgSpeedM2,DEC);
        terminal.print(" ");
    }
    terminal.println();
}

void loop() {
    // run both motors at 'full speed'
    roboclaw.ForwardM1(address,127);
    roboclaw.ForwardM2(address,127);
    displayspeed();
}