Using Packet Serial in .NET - RoboClaw 2x60a

General discussion of using Roboclaw motor controllers
Post Reply
kirklynk
Posts: 4
Joined: Sat May 02, 2020 4:30 pm
Using Packet Serial in .NET - RoboClaw 2x60a

Post by kirklynk »

Hello,

Sorry if this question have been asked and answered before, but I am having a tremendously communicating with RoboClaw 2x60a, purchased through ServoCity, using the packetized serial protocol from a .NET based program. Standard serial seems to work, but I am looking to send more advanced commands to control drive and turn. To test, I have an OSEPP FTDI adapter connected to my Windows computer which shows it as COM Port 12 in Device Manager. FTDI TX goes RoboClaw RX, and RX goes to RoboClaw transmit.

Here's my sample test harness:

Code: Select all

using System;
using System.IO.Ports;
using System.Threading;

namespace RC_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort port = new SerialPort("COM12", 115200, Parity.None, 8, StopBits.One);
            port.Open();
            Console.WriteLine("Hello World!");
            byte address = 128;
            byte command = 12;
            while (true)
            {
                byte valueToWrite = 32;
                ushort crc = 0;
                CalculateChecksum(address, ref crc);
                CalculateChecksum(command, ref crc);
                CalculateChecksum(valueToWrite, ref crc);
                byte msb = (byte)(crc >> 8);
                byte lsb = (byte)(crc);
                byte[] buffer = new byte[] { address, command, valueToWrite, msb, lsb };
                port.Write(buffer, 0, buffer.Length);
                Thread.Sleep(10);
            }
        }

        private static void CalculateChecksum(byte data, ref ushort crc)
        {
            int i;
            crc = (ushort)(crc ^ ((ushort)data << 8));
            for (i = 0; i < 8; i++)
            {
                if ((crc & 0x8000) != 0)
                    crc = (ushort)((crc << 1) ^ 0x1021);
                else
                    crc <<= 1;
            }
            //return crc;
        }
    }
}

This code does not seems to work. What could I be missing?
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Using Packet Serial in .NET - RoboClaw 2x60a

Post by Basicmicro Support »

1. you should read back a byte after sending the command packet. If you get a return value then the packet was valid. If you dont get a byte within 10ms the crc was wrong. Set a 10ms timeout for the read command. then if you get a byte continue and if you get a timeout instead you can handle the error.

2. I would also set your loop delay to something more reasonable, 100ms or 1 second instead of 10ms.
kirklynk
Posts: 4
Joined: Sat May 02, 2020 4:30 pm
Re: Using Packet Serial in .NET - RoboClaw 2x60a

Post by kirklynk »

Thanks for this response. As it turns out, based on the documentation and a post I stumbled upon here, the RoboClaw needs to commands a drive and a turn command before it will start moving :oops: . In my previous post, I was sending the mixed ForwardBackward command without any turn command. I refactored and added the turn command and Eureka, it works like a charm.

Here is the modified code:

Code: Select all

using System;
using System.IO.Ports;
using System.Threading;

namespace RC_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            SerialPort port = new SerialPort("COM12", 115200, Parity.None, 8, StopBits.One);
            port.DataReceived += Port_DataReceived;
            port.Open();

            byte address = 128;
            byte mixedForwardBackward = 12;
            byte mixedTurnLeftRight = 13;
            while (true)
            {
                byte driveValue = 20;
                byte turnValue = 64;

                byte[] buffer = CalculateChecksumArray(new byte[] { address, mixedForwardBackward, driveValue });
                port.Write(buffer, 0, buffer.Length);
                Thread.Sleep(10);

                buffer = CalculateChecksumArray(new byte[] { address, mixedTurnLeftRight, turnValue });
                port.Write(buffer, 0, buffer.Length);
                Thread.Sleep(10);

            }
        }

        private static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //read inbound here

        }

        private static byte[] CalculateChecksumArray(byte[] inbound)
        {
            ushort crc = 0;
            var outbound = new byte[inbound.Length + 2];
            Array.Copy(inbound, outbound, inbound.Length);

            //Calcalute CRC for the inbound array
            for (int idx = 0; idx < inbound.Length; idx++)
            {
                var data = outbound[idx];
                crc = (ushort)(crc ^ ((ushort)data << 8));
                for (int i = 0; i < 8; i++)
                {
                    if ((crc & 0x8000) != 0)
                        crc = (ushort)((crc << 1) ^ 0x1021);
                    else
                        crc <<= 1;
                }
            }
            outbound[inbound.Length] = (byte)(crc >> 8);
            outbound[inbound.Length + 1] = (byte)crc;
            return outbound;
        }
    }
}

User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Using Packet Serial in .NET - RoboClaw 2x60a

Post by Basicmicro Support »

Ah, yes. That as well. I didnt look up the command number to see which command you were using. The mixed compatibility commands need both to start. Once started either can be used to change the movement.

Post Reply