Controlling GoPiGo with C/C++


#1

Hello GoPiGo-Team!
I bought the GoPiGo 1 mounth ago because I have to make a Software-Project with C/C++. And I love the GoPiGo-Project very much. With the Python examples the GoPiGo is working well.

I tried to control my GoPiGo in C++ language together with wiringPi library. From wiringPi library I use the I2C-part for communication with the GoPiGo-Board (ATmega328). I tried to handle the easy things like readout the firmware or readout the voltage. With “i2cdetect -y 1” I can see the GoPiGo-address “08”. But the software-examples in C++ are not working.

Do you know from some other people who try to program the GoPiGo with C/C++. Or because your firmware of the GoPiGo is written in a kind of “C”-language you can perhaps help me with my problem?

Best regards!

Gerhard


#2

Hi,
Right now the GoPiGo only supports Python but it should not be too hard to make a C/C++ port for it. The firmware is written in C/C++ but the software that interacts with the GoPiGo is written in Python. The interaction on the hardware takes place using I2C. There are I2C libraries available for C which can be used for using the GoPiGo. There has not been a lot of demand for the C library hence we have not built. Do let us know if you are interested in writing it.

Another thing that we can do is to make a TCP socket server in Python which could take the commands from a socket client and do the necessary actions on the GoPiGo. This should be easier to do since you wouldn’t have to write and code for I2C. Do let us know what works for you and we would be happy to help you in any way we can.

-Karan


#3

Hello Karan!
Yes I would like to write the C library using I2C for interacting on the hardware.

I tried to use the I2C library “wiringPi”: http://wiringpi.com/reference/i2c-library/

I wrote the following programm, to read out the firmware-version:

#include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define volt_cmd 118 // Read the voltage of the batteries

int main(int argc, char *argv [])
{
char a;
int test, b1, b2, ver, ver1;
int address=0x08;
test = wiringPiI2CSetup(address);
printf(“n I2C-Adresse: %f n”,test);
printf(“Cmd:”);
a=getchar();
if(a==‘f’)
{
wiringPiI2CWrite(address,20);
printf(“n I2C Befehl”);
delay(100);
ver=wiringPiI2CRead(address);
ver1=wiringPiI2CRead(address);
printf(“n Address00: %f”,ver);
printf(“n Address01 %f n”,ver1);
printf(“n ********************** n”);
wiringPiI2CWrite(address,0x14);
printf(“n I2C Befehl”);
delay(100);
b1=wiringPiI2CRead(address);
b2=wiringPiI2CRead(address);
printf(“n Address00: %f”,ver);
printf(“n Address01 %f n”,ver1);
}
else
printf(“Error”);
return 0;
}

After installing wiringPi on the Raspberry Pi I Change into the wiringPi-directory and type in:
gcc Test.cpp -o test -l wiringPi
sudo ./test

But it is not possible to read out the firmeware-version. I tried also to read out the voltage with the same result.

Do you know the mistake what I did?
Or do you have a hint for me, to use an other I2C library?

Best regards!

Gerhard


#4

Hey Gerhard,
I think you are on the right path. Just a few comments, if you have a look at the implementation here: https://github.com/DexterInd/GoPiGo/blob/dd3548bdd82cf90580a88e1880d78110c96314ef/Software/Python/gopigo.py#L230-L244 of the volt() function, we write 4 bytes [118,0,0,0] to the I2C device then wait or 100ms and then read back 2 bytes which we then convert to an integer. I think the low level operations are fine but you need to write 4 bytes and read back 2 bytes.

Do let me know if this helps.

-Karan


#5

Hi Karan!

I thought that’s the solution, but I think there is still a general problem:

The output of my code is always “I2C-Address: 0.000” but it should be “8”. What is the I2C-baudrate of the GoPiGo because i read in the firmware that it is reduced – do you think that can be the problem?

CODE OUTPUT:

pi@raspberrypi ~/wiringPi gcc Test.cpp -o test -l wiringPi pi@raspberrypi ~/wiringPi sudo ./test

I2C-Adresse: 0.000000
Cmd:v

I2C Befehl
Address00: %b
Address01 %b


I2C Befehl
Address00: -nan
Address01 -0.000007


I tried so many different things with my code. But nothing helps:

#include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define volt_cmd 118 // Read the voltage of the batteries

int main(int argc, char *argv [])
{
char a;
int test, b1, b2, ver, ver1;
int address=0x08;
test = wiringPiI2CSetup(address);
printf(“n I2C-Adresse: %f n”,test);
printf(“Cmd:”);
a=getchar();
if(a==‘v’)
{
wiringPiI2CWriteReg16(118,0,0);
printf(“n I2C Befehl”);
delay(100);
ver=wiringPiI2CReadReg16(118,0);
ver1=wiringPiI2CReadReg16(118,0);
printf(“n Address00: %f”,ver);
printf(“n Address01 %f n”,ver1);
printf(“n ********************** n”);
wiringPiI2CWriteReg8(118,0,0);
printf(“n I2C Befehl”);
delay(100);
b1=wiringPiI2CReadReg8(118,0);
b2=wiringPiI2CReadReg8(118,0);
printf(“n Address00: %f”,ver);
printf(“n Address01 %f n”,ver1);
printf(“n ********************** n”);
}

if(a=='f')
	{
		wiringPiI2CWriteReg16(test,20,0);
		printf("n I2C Befehl");
		delay(100);
		ver=wiringPiI2CReadReg16(test,20);
		ver1=wiringPiI2CReadReg16(test,20);
		printf("n Address00: %f",ver);
		printf("n Address01 %f n",ver1);
		printf("n ********************** n");
		wiringPiI2CWriteReg8(test,0x14,0);
		printf("n I2C Befehl");
		delay(100);
		b1=wiringPiI2CReadReg8(test,0x14);
		b2=wiringPiI2CReadReg8(test,0x14);
		printf("n Address00: %f",ver);
		printf("n Address01 %f n",ver1);
		printf("n ********************** n");
		wiringPiI2CWriteReg8(address,20,0);
		printf("n I2C Befehl");
		delay(100);
		b1=wiringPiI2CReadReg8(address,20);
		b2=wiringPiI2CReadReg8(address,20);
		printf("n Address00: %f",ver);
		printf("n Address01 %f n",ver1);
		printf("n ********************** n");
		wiringPiI2CWriteReg16(address,20,0);
		printf("n I2C Befehl");
		delay(100);
		b1=wiringPiI2CReadReg16(address,20);
		b2=wiringPiI2CReadReg16(address,20);
		printf("n Address00: %f",ver);
		printf("n Address01 %f n",ver1);

	}
	else
		printf("Error");
return 0;

}

Best regards!

Gerhard


#6

Hey Gerhard,
Looks like you have tried a lot to get the I2C comms to work with C. I am also not sure what’s going wrong. I usually use a logic analyzer to check what is going on, on the bus and have seen the I2C misbehaving a lot.

There’s is something else that might be easier to use. We have this socket server-client example up on Github: https://github.com/DexterInd/GoPiGo/tree/master/Software/Client_Server . We made this very example so that it’s easier for other languages to communicate with the GoPiGo. One reason for the difficulty with the GoPiGo is that it communicates using I2C which might be a bit difficult to work with.

So the example there has a server written in Python that you run, and write a client library in a language of your choice. The client sends simple commands to the Server and the server does all the heavy-lifting. We have a client example also in there in python and I think you should try it out. It’s a pretty basic example and if works well, you can send us a pull request with the C code that you write.

-Karan


#7

Hello Karan!

Thank you a lot for socket server/client example. It was very easy for me to use the python code. But it takes one day of hard work to understand and write the client-code in C++. But now it works and I am so happy that I can controll my GoPiGo with C++ language.

Now I have to hurry up the next 2 until 3 weeks to finish my project. I am sure in some parts I will need your help again :wink:

Best regards!

Gerhard


#8

Hey Gerhard,
Can you share the C code with with, maybe here or a pull request on the Github library would be better, this way it would be useful to others too. Do let us know about any problems or challenges you had faced and anything we can do to make it easier to use.

Also, do share your project with us. We have an Instructables contest running too http://www.dexterindustries.com/forum/?topic=pie-day-contest, so you can post your project there and you might end up winning some awesome goodies.

-Karan


#9

Hello Karan!
Sorry for the long delay of my answer, last week I was on a course. But now my programming deadline is 19th of March. I will try to learn Github-request but until now I don’t know how to do. Therefore I will publish the important part of my C-Code here.

Until now I know how to go forward, backward, left and right with my GoPiGo. I modified also the “Server.py” to increase and decrease the Speed. In General to read out the voltage and firmware-revision is working, only the return value is a strange sign and not the real value:

additional part of server.py:

elif data==‘v’:
gopigo.volt()
conn.send(“Voltage”)
elif data==‘w’:
gopigo.fw_ver()
conn.send(“Firmware Revision”)

important part of my C-Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

char sendv (char msg)
{
double TCP_IP = 0x7F000001; // IP-Address: 127.0.0.1
double TCP_PORT = 5005;
double BUFFER_SIZE = 1024;
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
char data;
char MESSAGE[2] = “v”;
printf(“Befehl: %c n”, msg);

//Create a socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf(“Socket: %fn”, sockfd);
//Connect to the server;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(TCP_PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
connect(sockfd,(struct sockaddr *) &serv_addr, sizeof
(serv_addr));
printf(“Connectedn”);
//Send the command;
write(sockfd, MESSAGE, strlen(MESSAGE));
printf(“Send data: %sn”,MESSAGE);
//Receive response back
data = read(sockfd, MESSAGE, BUFFER_SIZE);
printf(“Received data: %sn”, MESSAGE);
close(sockfd);
return data;
}
char sendw (char msg)
{
double TCP_IP = 0x7F000001; // IP-Address: 127.0.0.1
double TCP_PORT = 5005;
double BUFFER_SIZE = 1024;
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
char data;
char MESSAGE[2] = “w”;
printf(“Befehl: %c n”, msg);
//Create a socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf(“Socket: %fn”, sockfd);
//Connect to the server;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(TCP_PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
connect(sockfd,(struct sockaddr *) &serv_addr, sizeof
(serv_addr));
printf(“Connectedn”);
//Send the command;
write(sockfd, MESSAGE, strlen(MESSAGE));
printf(“Send data: %sn”,MESSAGE);
//Receive response back
data = read(sockfd, MESSAGE, BUFFER_SIZE);
printf(“Received data: %sn”, MESSAGE);
close(sockfd);
return data;
}

int main(int argc, char *argv [])
{
char msg;
printf(“Client startedn”);
for(;:wink:
{
printf(" <F>orwaertsn <B> Rueckwertsn <L>inks n
<R>echtsn <S>top ???");
msg = getchar();
switch(msg)
{
case ‘f’:
sendf(‘f’);
printf(“Forwaertsn”);
break;
case ‘b’:
sendb(‘b’);
break;
case ‘l’:
sendl(‘l’);
break;
case ‘r’:
sendr(‘r’);
break;
case ‘s’:
sends(‘s’);
break;
case ‘i’:
sendi(‘i’);
break;
case ‘d’:
sendd(‘d’);
break;
case ‘w’:
sendw(‘w’);
break;
case ‘v’:
sendv(‘v’);
break;
}
} //while((msg=getchar()) != ‘n’);
printf(“Client endn”);
// printf(“f %sn”, send(‘f’));
// usleep(2000000);
// printf(“b %sn”, send(‘b’));
// usleep(2000000);
// printf(“l %sn”, send(‘l’));
// usleep(2000000);
// printf(“r %sn”, send(‘r’));
// usleep(2000000);
// printf(“s %sn”, send(‘s’));

return 0;

}

Result of the C-Code (press ‘w’):

Client started
<F>orwaerts
<B> Rueckwerts
<L>inks
<R>echts
<S>top ???w
Befehl: w
Socket: 0.000000
Connected
Send data: w
Received data: Firmware Revision▒


#10

Hey Gerhard,
Thanks a lot for the code. I’ll merge it with the repo myself. If you need any help getting started with Github and contributing code, we have a guide here: http://www.dexterindustries.com/howto/raspberry-pi-tutorials/contribute-code-dexter-industries-projects/ .

Thanks again,
Karan