Page 1 of 1

Using Packet Serial in .NET - RoboClaw 2x60a

Posted: Sat May 02, 2020 8:17 pm
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?

Re: Using Packet Serial in .NET - RoboClaw 2x60a

Posted: Mon May 04, 2020 8:15 am
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.

Re: Using Packet Serial in .NET - RoboClaw 2x60a

Posted: Mon May 04, 2020 11:58 am
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;
        }
    }
}


Re: Using Packet Serial in .NET - RoboClaw 2x60a

Posted: Tue May 05, 2020 8:02 am
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.