Beaglebone + thermal sensor with ROS

Robots self testing

As we build more complex robots we need more feedback from them to know what state they are in. In my case I want to know some temperature information about my rover. These things are the motors, the outside environment, and the battery temperature. For this purpose, I want to create an Arduino thermal sensor. Later it will be only an Atmel chip with the sensors but for prototyping and developing the Arduino is the best solution.
The central computer on the Rovers will be Beaglebone. So after I create the thermal sensor, I need to make the communication between these devices. If that is done, the only thing is left to make the ROS package. I have chosen ROS because in the near future I want to make more sensors and ROS is ideal for information distributing.

The Arduino thermal sensor

Six sensor will be needed (4 for motor, 1 for battery, 1 for outside env.). In the first version there will be only one. The thermal sensor is a MCP9700-E/TO. Here you can see the datasheet.
mcp9700-e_to
The thermal sensor is connected to the A0, 5v and a gnd.

I did the lazy dog version of the development, so I started to Googliing for some information and code instead of making it. I need a formula to convert the received data to Celsius. Here you can see it in Arduino code:

int sensorPin  = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;
int sensorPin4 = A4;
int sensorPin5 = A5;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  //For debugging
  //Serial.print("Readed data ");
  //Serial.println(analogRead(sensorPin));

  float temp = analogRead(sensorPin)*5/1024.0;
  temp = temp - 0.5;
  temp = temp / 0.01;
  Serial.print("Celsius: ");
  Serial.println(temp);
  delay(500);
}

The only problem with that code, the sensor is not that precise and sometimes it gives false value.
arduino serial console tempeture sample
Even it’s MCP9700-E/TO datasheet mentions that there can be +/-2 celsius error (1. page/2nd paragraph).
To solve this problem we have take more samples and make an average, and someone already did it here. Here is my version, that created from previously mentioned code:

int sensorPin = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;
int sensorPin4 = A4;
int sensorPin5 = A5;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
    float temperature = 0.0;   // stores the calculated temperature
    int sample;                // counts through ADC samples
    float ten_samples = 0.0;   // stores sum of 10 samples
    // take 10 samples from the MCP9700
    for (sample = 0; sample < 10; sample++) {
        // convert A0 value to temperature
        temperature = ((float)analogRead(A0) * 5.0 / 1024.0) - 0.5;
        temperature = temperature / 0.01;
        // sample every 0.1 seconds
        delay(100);
        // sum of all samples
        ten_samples = ten_samples + temperature;
    }
    // get the average value of 10 temperatures
    temperature = ten_samples / 10.0;
    // send temperature out of serial port
    Serial.print(temperature);
    Serial.println(" deg. C");
    ten_samples = 0.0;
}

arduino serial console tempeture sample with average
For now the part of the Arduino is done.

References:

http://arduino.cc/forum/index.php?topic=124817.0
http://startingelectronics.com/beginners/start-electronics-now/tut15-arduino-serial-thermometer/
http://starter-kit.nettigo.eu/2010/how-to-measure-temperature-with-arduino-and-mcp9700/
http://startingelectronics.com/beginners/start-electronics-now/tut14-arduino-LCD-thermometer/

The serial communication between the Beaglebone and Ardunio

I plugged in the Arduino through the usb, so there will be a serial connection (dev ttyUSB0). To check that everything works fine I want to see the data flowing between the devices.

cat /dev/ttyUSB0

arduino serial console tempeture sample on beaglebone

If everything works fine, time to get some C or C++ code. Again the lazy dog style. This is what I found, where the code can be see here. That is a serial console implementation and I only need it for incoming data. I made some modifications.
This is needed for running without failure in our case.
#131 const char *portStr = “ttyUSB0”;
The other changes can be seen here. To build it:

gcc -lpthread serial.c -o serial

Then run it:

chmod +x serial
./serial

If everything is fine you can see the Arduino’s message as above. I found also that. This is a library for rs232 (serial) communication, those who are not as lazy as me can implement their own version. It’s helpful understanding the serial communication in programming.

ROS package for Beaglebone

There are many tutorials how to make ROS packages. So I skip this part, I only show how to expand the serial.c into a ROS package. The main change is can be seen here:

    ros::init(argc, argv, "thermalsensor");
    ros::NodeHandle n;
    ros::Publisher pub = n.advertise("celsius", 100);
    thermalsensor::celsius msg;
	ros::Rate loop_rate(10);
	std::stringstream datastring;
	while(ros::ok())
    {
        char    ch;
        int     bytesRead;
        if (( bytesRead  = read( gPortFd, &ch, 1 )) < 0 )
        {
            fprintf( stderr, "Serial port read failed: %s\n", strerror( errno ));
            exit( 1 );
        }
        if ( gDebug )
        {
            if (( ch  '~' ))
            {
                fprintf( stderr, "Serial Read: 0x%02x '.'\n", ch );
            }
            else
            {
                fprintf( stderr, "Serial Read: 0x%02x '%c'\n", ch, ch );
            }
        }
	if ( ch == '\n' ){
		 std::cout << datastring.str() << std::endl;
		 datastring.str(std::string());
		 msg.value = atoi(datastring.str().c_str());
		 pub.publish(msg);
		 ros::spinOnce();
	}else {
		datastring << ch;	
	}
        loop_rate.sleep();
    }

This not the whole code, only the most necessary part. The whole code and package can be downloaded from here.

Here you can see it in run:
thermalsensorros

The first window shows the package running, it sends the Celsius to the console for debugging, it can be removed. The second shows the roscore running, the third when you listen to the topic.

The Beaglebone and the Arduino is connected via USB.

This was a very lazy project, next time I will have to make some improvements. These are:
-Atmega chip instead a full Arduino
-Uart Beaglebone and rx tx on the atmega for the communication.
-Update the ros package to work with the above mentioned improvements.
-Throw out the independent code parts.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s