Simple C or C++ example for Raspberry?

General discussion of using Roboclaw motor controllers
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Simple C or C++ example for Raspberry?

Post by Basicmicro Support »

So I edited your post to add the BBCode. This displays the text in a code block which is much easier to read.

I see two problem.

1. The Peek command is trying to open the port again. I dont think its being used so it probably doesnt matter but thought I better point it out.

2. It looks like you are sending decimal 80 for the Roboclaw address instead of 0x80(eg hexidecimal). Also the ReadVersion command is hexidecimal 0x15 not decimal 15(its decimal 21). This is probably the main problem with your program.
ecorrales
Posts: 33
Joined: Sun May 06, 2018 5:06 am
Re: Simple C or C++ example for Raspberry?

Post by ecorrales »

cool.. btw - whenever I have tried to wrap anything with the formatting tags (like the code tags), when I do a preview or a submit, I get back a blank editor box saying 'too few characters'. I remove the tags, and it all shows up again.

the peek() - yeah, I had thought at first it was the cause of the 'device temp busy' but it doesnt seem to be - but if it's not being used, all the better.

Question, though: how would be a good way to do a peek? Related - should the port read() be blocking or non-blocking... ? I guess that's why I thought the peek() was necessary. (well there IS the available() )

I will change over to hex (sorry I should have seen that).

thanks
ecorrales
Posts: 33
Joined: Sun May 06, 2018 5:06 am
Re: Simple C or C++ example for Raspberry?

Post by ecorrales »

Hi,
I don't think it's the issue of hex vs decimal. see below.

Could it be I need to set start/stop bits, parity..etc.. I was confused in the manual.. because it talks about serial and packet serial...

Here is test output:

Code: Select all

RoboClaw::RoboClaw()
RoboClaw::begin()
HardwareSerial::hwSerialBegin(9600)
inSpeed : 13
outSpeed : 13
inSpeed : 13
outSpeed : 13
RoboClaw::ReadVersion()
RoboClaw::flush()
HardwareSerial::hwSerialFlush()
RoboClaw::crc_clear()
RoboClaw::write()
HardwareSerial::hwSerialWrite(%x=80 %d=128)
RoboClaw::crc_update()
RoboClaw::write()
HardwareSerial::hwSerialWrite(%x=15 %d=21)
RoboClaw::crc_update()
	RoboClaw::ReadVersion():for loop(0)
		RoboClaw::ReadVersion():gna read()...
RoboClaw::read( timeout)
		RoboClaw::ReadVersion():read():data = %x= ff %d=255
RoboClaw::crc_update()
	RoboClaw::ReadVersion():for loop(1)
		RoboClaw::ReadVersion():gna read()...
RoboClaw::read( timeout)
		RoboClaw::ReadVersion():read():data = %x= ff %d=255
RoboClaw::crc_update()

Hopefully these links to code will now work:

complete test output (not much diff from above):
https://github.com/elicorrales/roboclaw ... boclaw.log

main():
https://github.com/elicorrales/roboclaw ... c/main.cpp

RoboClaw:
https://github.com/elicorrales/roboclaw ... boClaw.cpp

HardwareSerial:
https://github.com/elicorrales/roboclaw ... Serial.cpp
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Simple C or C++ example for Raspberry?

Post by Basicmicro Support »

Virtual serial ports(eg ttyACM0) do not need baudrate settings or format usually. If you are concerned that is the case set 8N1 and whatever baudrate you set using Ion Studio, Roboclaw defaults to 38400). Note that some computers Virtual serial ports may not work correctly if you dont set the baudrate to something(eg non-zero).

I recommend you back up and write a simple test program that sends 0x80, 0x15 and reads back any bytes that come in to see if you can figure if its a serial port problem.

Something is definitely wrong with your code but I cant see what. You are apparently receiving actual 0xFF bytes or your PC is lying to you and you are not receiving any data back and its just returning 0xFF from the hwSerialRead no matter what the state of the serial buffer is.
ecorrales
Posts: 33
Joined: Sun May 06, 2018 5:06 am
Re: Simple C or C++ example for Raspberry?

Post by ecorrales »

ok, learned a bit more.

program output:

Code: Select all

hwSerialBegin(9600)
inSpeed : 1
outSpeed : 1
inSpeed : 13
outSpeed : 13
Writing  0x80......
Writing  0x15......
doing read loop......
	 seeing if bytes available......
. 	 seeing if bytes available......
. 	 seeing if bytes available......
. 	 seeing if bytes available......
. 	 seeing if bytes available......
Code at bottom, but essential, I don't think it's reading anything.
I did set the baud to 9600 via Ion Studio.

I also did an stty at Raspberry terminal, here's the results:

Code: Select all

sudo stty -F /dev/ttyACM0 
speed 9600 baud; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = ^\; eof = M-H; eol = M-^T; eol2 = 1; start = @; stop = M-}; susp = v; rprnt = M-F; werase = ~; lnext = M-h; discard = M-=; min = 126; time = 189;
-cread
-brkint -icrnl ixoff -imaxbel
-opost ocrnl ofill ofdel cr3 vt1
-isig -icanon -echo noflsh echoprt -echoke flusho
Here's the code, all in a single file:

Code: Select all

#include <iomanip>
#include <termios.h>
#include <iostream>
#include <sstream>
#include <errno.h>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <wiringPi.h>
#include <iomanip>
#include <termios.h>

using namespace std;

const string _serialDeviceName = "/dev/ttyACM0";

void hwSerialHandleError(const string& message, int errnum) {

	ostringstream msgstream("");

	msgstream << message <<  " : " << _serialDeviceName << " : ";
       	if (errnum) {
			msgstream <<  "errno is [ " << errnum << "]  :  " << strerror(errnum);
		}
	msgstream << '\n';

	cerr << msgstream.str();

	exit(1);
}

int main(int argc, char** argv) {


	int _fd = open(_serialDeviceName.c_str(),O_RDWR | O_NOCTTY );

	if (1 > _fd or 0 != errno) {

		hwSerialHandleError("Error opening",errno);
	}

	int speed = 9600;

	cout << "hwSerialBegin(" << speed << ")\n";

	struct termios _settings;

	speed_t inSpeed = cfgetispeed(&_settings);
	speed_t outSpeed = cfgetospeed(&_settings);

	cout << "inSpeed : " << inSpeed << '\n';
	cout << "outSpeed : " << outSpeed << '\n';

	switch (speed) {
		case 4800:
			cfsetispeed(&_settings,B4800);
			cfsetospeed(&_settings,B4800);
			break;
		case 9600:
			cfsetispeed(&_settings,B9600);
			cfsetospeed(&_settings,B9600);
			break;
		case 19200:
			cfsetispeed(&_settings,B19200);
			cfsetospeed(&_settings,B19200);
			break;
		case 38400:
			cfsetispeed(&_settings,B38400);
			cfsetospeed(&_settings,B38400);
			break;
		case 115200:
			cfsetispeed(&_settings,B115200);
			cfsetospeed(&_settings,B115200);
			break;
	}

	tcsetattr(_fd,TCSANOW,&_settings);

	delay(200);

	inSpeed = cfgetispeed(&_settings);
	outSpeed = cfgetospeed(&_settings);

	cout << "inSpeed : " << inSpeed << '\n';
	cout << "outSpeed : " << outSpeed << '\n';

	cout << "Writing  0x80......\n";

	uint8_t byte = 0x80;
	errno = 0;
	int bytesWritten = write(_fd,&byte,sizeof(byte));
	if (1>bytesWritten) {

		hwSerialHandleError("Error writing 0x80",errno);
	}


	delay(10);

	cout << "Writing  0x15......\n";

	byte = 0x15;
	errno = 0;
	bytesWritten = write(_fd,&byte,sizeof(byte));
	if (1>bytesWritten) {

		hwSerialHandleError("Error writing 0x15",errno);
	}


	cout << "doing read loop......\n";

	for (int i=0;i<1000;i++) {

		delay(10);

		cout << "\t seeing if bytes available......\n";

		errno = 0;
		uint8_t bytes = 0;
		int rtn = ioctl(_fd,FIONREAD, &bytes);
		if (0 < rtn and 0 == errno and bytes > 0) {


			cout << "\t\t there is, lets get it......\n";

			int byte = 0;
			errno = 0;
			int bytesRead = read(_fd,&byte,sizeof(byte));
			if (0 > bytesRead or 0 != errno) {
		
				hwSerialHandleError("Error Reading Byte",errno);

			}

			cout << "[" << byte << "]";

		} else {
			cout << ". ";
		}

	}

	cout << '\n';

	return 0;
}
ecorrales
Posts: 33
Joined: Sun May 06, 2018 5:06 am
Re: Simple C or C++ example for Raspberry?

Post by ecorrales »

I also tried this:

Code: Select all

	cout << "Writing  0x80,0x15......\n";

	uint8_t bytes[2] = { 0x80, 0x15 };
	errno = 0;
	int bytesWritten = write(_fd,&bytes,2*sizeof(uint8_t));
	if (1>bytesWritten) {

		hwSerialHandleError("Error writing 0x80",errno);
	}
same result
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Simple C or C++ example for Raspberry?

Post by Basicmicro Support »

1.Confirm the Roboclaw is working correctly with Ion Studio.
2.Confiurm you have the latest firmware(4.1.24)
3.Reset the Roboclaw to default settings using Ion Studio
4.Download and test reading the version using our Python library examples. This will confirm the RPi is able to talk to the Roboclaw and let us know the problem is in the serial port access in the C/C++ program.

Let me know the results.
ecorrales
Posts: 33
Joined: Sun May 06, 2018 5:06 am
Re: Simple C or C++ example for Raspberry?

Post by ecorrales »

Yes..
1) Roboclaw works with Ion Studio
2) Has latest firmware
3) will try the 'reset'
4) I'm also having Python issues - will tackle that part later, BUT - I already confirmed the Raspberry Pi + serial port does work by taking someone else's code. However, I don't want to use that code because it depends on Boost C++ and that's a really heavy / bloated library

So it has to be my code. :(

I will see what else I can figure out over the weekend

thanks for all the help...
ecorrales
Posts: 33
Joined: Sun May 06, 2018 5:06 am
Re: Simple C or C++ example for Raspberry?

Post by ecorrales »

Hi,

I tried the following, and it works, however it uses Boost. :(

Code: Select all

#include <iostream>
#include <boost/asio.hpp>

using namespace std;

string serialDev = "/dev/ttyACM0";
boost::asio::io_service io;
boost::asio::serial_port serial(io, serialDev);

string getVersion()
{
    uint8_t commands[] = { 0x80, 0x15 };
    write( serial, boost::asio::buffer(commands, 2));

    // read the result
    string ver = "";
    char c = 0;
    bool reading = true;
    while( reading )
    {
            boost::asio::read(serial,boost::asio::buffer(&c,1));
        switch(c)
        {
            case '\0':
                // also read the crc
                    boost::asio::read(serial,boost::asio::buffer(&c,1));
                    boost::asio::read(serial,boost::asio::buffer(&c,1));
                reading = false;
                break;
            default:
                ver+=c;
        }
    }

    return ver;
}

int main( int argc, char** argv )
{
        cout << "version        : " << getVersion() << endl;

        return 0;
}
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Simple C or C++ example for Raspberry?

Post by Basicmicro Support »

For now that may be your only option until we can get to writing our own C/C++ Linux library. Serial Port access is the sticking point with C/C++ since its not inherently built in.

Python at least has pyserial. Make sure you use Python 2.7 with our python library. It is not written for Python 3.

Post Reply