Reading Currents from my Roboclaw Motor Controller

Related to another post I got a question about communicating with my 2x30A Roboclaw Motor controller.
Initial Post
Datasheet
I decided to face the problems with the Bluefruit device later and came upon another problem I desperatly need help with.
I am using a Mega2560 and the Roboclaw 2x30A Motor Controller. My Sketch includes the Roboclaw.h and the BMSerial.h library. Both to be found as an attachement to my Inital post.

I'm currently communicating with the roboclaw via Packetserial and sending comands to the Controller works just fine. There seems to be a way to get the currents from the motors. I read through the data sheet multiple times and used google but for me as a beginner I couldn't really figure out how to do it exactly.
This is what the data sheet says about getting the currents in Packet Serial mode:

49 - Read Motor Currents
Read the current draw from each motor in 10ma increments. Command syntax:
Send: [Address, 49]
Receive: [M1Cur.Byte1, M1Cur.Byte0, M2Cur.Byte1, M2Cur.Byte0, Checksum]
The command will return 5 bytes. Bytes 1 and 2 combine to represent the current in 10ma increments
of motor1. Bytes 3 and 4 combine to represent the current in 10ma increments of motor2 . Byte 5 is
the checksum

Could someone provide me an example how to exactly send the command and store what I received in two variables?

Thanks!

I decided to face the problems with the Bluefruit device later

So, you dumped a library, to resolve conflicts, which means that you must have revised your code. And, yet you don't think we want to see it?

The RoboClaw library contains:

	bool ReadCurrents(uint8_t address, uint8_t &current1, uint8_t &current2);

Why isn't calling that function sufficient?

I choose not to use bluetooth for now.

I know that there is this function, my question is how to call it and store the received values in variables. I know it's a rather simple question to answer for you guys, unfortunately it's not for me.. :slight_smile:

my question is how to call it and store the received values in variables.

If you have an instance of the RoboClaw class called grabby,

uint8_t currentFromMotorOne;
uint8_t currentFromMotorTwo;

   bool gotIt = grabby.ReadCurrents(address, currentFromMotorOne, currentFromMotorTwo);
   if(gotIt)
   {
      Serial.print("Hot diggity damn, we got the current data...");
      Serial.print("Motor 1 is sucking up ");
      Serial.print(currentFromMotorOne);
      Serial.println(" amp, or maybe that's milliamps...");
      Serial.print("Motor 2 is sucking up ");
      Serial.print(currentFromMotorTwo);
      Serial.println(" amp, or maybe that's milliamps...");
   }

Thanks Paul.

So I got a an instance called roboclaw1 and roboclaw2 an I'm trying to read the current of rc1 while pressing the down button. The bool never gets true and if I remove the if clause its printing the lines but the currents read 0.

RoboClaw roboclaw1(14,15);
RoboClaw roboclaw2(17,19);
  uint8_t RC2currentFromMotorOne;
uint8_t RC2currentFromMotorTwo;
  uint8_t RC1currentFromMotorOne;
uint8_t RC1currentFromMotorTwo;
roboclaw1.begin(9600);
roboclaw2.begin(9600);

Serial.begin(9600);

.
.
.
.
.
this is in the void loop:

 while(down==LOW)
{  down=digitalRead(Bdown);
  roboclaw1.ForwardM2(address,64);
roboclaw2.ForwardM1(address,64);
digitalWrite(38,HIGH); //led1
digitalWrite(39,HIGH); //led2
Stop=1;  

 bool gotIt = roboclaw1.ReadCurrents(address, RC1currentFromMotorOne, RC1currentFromMotorTwo);
   if(gotIt)
   {
      Serial.print("Hot diggity damn, we got the current data...");
      Serial.print("Motor 1 is sucking up ");
      Serial.print(RC1currentFromMotorOne);
      Serial.println(" amp, or maybe that's milliamps...");
      Serial.print("Motor 2 is sucking up ");
      Serial.print(RC1currentFromMotorTwo);
      Serial.println(" amp, or maybe that's milliamps...");
   }
}

I looked at the source file. If the return value is false, the arguments are not populated with data. I have no clue why the library is not getting valid data.

The two uint8_t arguments are stupid. The values are the high and low order bytes of an int. Much smarter to make the function return the int.

Do the other functions in the class, like reading battery voltage, and making the motors move, actually work?

commands like

roboclaw1.ForwardM2(address,64);
roboclaw2.ForwardM1(address,64);

do work just fine. I was not able to read anything from the roboclaw yet cause I'm all confused on how to write the code for that..

So I found that code in the Roboclaw library folder:

PacketSerialEncoderSpeedAccelDistance

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

#define address 0x80


#define Kp 0x00010000
#define Ki 0x00008000
#define Kd 0x00004000
#define qpps 44000

BMSerial terminal(0,1);

//Arduino Mega and Leonardo chips only support some pins for receiving data back from the RoboClaw
//This is because only some pins of these boards support PCINT interrupts or are UART receivers.
//Mega: 0,10,11,12,13,14,15,17,19,50,51,52,53,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15
//Leonardo: 0,8,9,10,11

//Arduino Due currently does not support SoftwareSerial. Only hardware uarts can be used, pins 0/1, 14/15, 16/17 or 18/19.

RoboClaw roboclaw(10,11);

void setup() {
  terminal.begin(9600);
  roboclaw.begin(38400);
  
  roboclaw.SetM1Constants(address,Kd,Kp,Ki,qpps);
  roboclaw.SetM2Constants(address,Kd,Kp,Ki,qpps);  
}

void displayspeed(void)
{
  uint8_t status;
  bool valid;
  
  uint32_t enc1= roboclaw.ReadEncM1(address, &status, &valid);
  if(valid){
    terminal.print("Encoder1:");
    terminal.print(enc1,DEC);
    terminal.print(" ");
    terminal.print(status,HEX);
    terminal.print(" ");
  }
  uint32_t enc2 = roboclaw.ReadEncM2(address, &status, &valid);
  if(valid){
    terminal.print("Encoder2:");
    terminal.print(enc2,DEC);
    terminal.print(" ");
    terminal.print(status,HEX);
    terminal.print(" ");
  }
  uint32_t speed1 = roboclaw.ReadSpeedM1(address, &status, &valid);
  if(valid){
    terminal.print("Speed1:");
    terminal.print(speed1,DEC);
    terminal.print(" ");
  }
  uint32_t speed2 = roboclaw.ReadSpeedM2(address, &status, &valid);
  if(valid){
    terminal.print("Speed2:");
    terminal.print(speed2,DEC);
    terminal.print(" ");
  }
  terminal.println();
}

void loop() {
  roboclaw.SpeedAccelDistanceM1(address,12000,12000,48000);
  uint8_t depth1,depth2;
  do{
    displayspeed();
    roboclaw.ReadBuffers(address,depth1,depth2);
  }while(depth1);
  roboclaw.SpeedAccelDistanceM1(address,12000,-12000,48000);
  do{
    displayspeed();
    roboclaw.ReadBuffers(address,depth1,depth2);
  }while(depth1);
  
}

I wonder if this helps (you) somehow to understand how the whole reading back from the controller process works?

Solved!

Roboclaw recently updated the their libraries. There's still a declaration you have to change from uint16 to 32 in line 380 in the roboclaw.cpp, but then it should work fine.