void ArduinoTalker::Serial_Class_for_Qt_5()

I have been learning Qt for a while now, and one its features is the very powerful concept of SIGNALS and SLOTS. I have become very dependent on the signal-slot mechanism and I use it liberally in the projects that I play around with.

Having experimented with the Arduino, and having gotten quite familiar with the basics, I needed a way to port Arduino data into the Qt environment so that I could do more complex stuff than the Arduino’s 32KB memory onboard memory would allow. Most examples of porting Arduino data to a PC are implemented with the processing programming language . Programming in processing is quite simple to learn, and easy to distribute when you’re done. But processing is doesn’t have a very well developed GUI and I needed a way to connect my Arduino into the Qt environment because I really like the signal-slot mechanism.

Right now I’m working with Qt 5 which includes the serialport class. With this as the basis, I wrote my own Arduinotalker class that can receive and send data from and to an Arduino device. Since most of the data I intend to transfer consists of floating point numbers, usually representing sensor data (from the Arduino) or command signals (to the Arduino), I had to parse the data (which is sent as strings over the serial line) into numbers and vice-versa.

My communication protocol is very simple:-

Connecting to an Arduino

Connection to an Arduino is effected by creating an instance of the Arduinotalker class and connecting to it using


mega1 = new ArduinoTalker(this);

mega1->ConnectToArduino("/dev/ttyACM0");

Once the connection is established, data transfer from the Arduino commences automatically and the signal NewDataArrivedFromArduino(QVector <double>*) is emitted every time fresh data is received and parsed correctly.

The port settings I used in the ArduinoTalker::ConnectToArduino(QString portName) function can be seen below:-


void ArduinoTalker::ConnectToArduino(QString portName)
{
arduino->setPortName(portName);

//open the port and set parameters

if(arduino->open(QIODevice::ReadWrite))
{
// Baud rate
arduino->setBaudRate(QSerialPort::Baud2400);
// 8bit mode
arduino->setDataBits(QSerialPort::Data8);
arduino->setParity(QSerialPort::NoParity);
arduino->setStopBits(QSerialPort::OneStop);
// Skipping hw/sw control
arduino->setFlowControl(QSerialPort::NoFlowControl);
}
}

Receiving Data From Arduino

1. All data from the Arduino must be numbers followed by a ‘,’. At the end of each sentence, a ‘&’ must be appended after the last ‘,’

This is achieved quite easily on the Arduino side, here is an example of how an Arduino is sending data (3 floating point numbers) from a ADXL345 accelerometer sensor:-


Serial.print(scaled.XAxis);
Serial.print(",");
Serial.print(scaled.YAxis);
Serial.print(",");
Serial.print(scaled.ZAxis);
Serial.print(",");
Serial.print("&");

2. On the receiver end, my Arduinotalker class parses the incoming data into an array of floating point numbers. The signal-slot mechanism is very useful here….as soon as data is sensed on the serial line, it is received, parsed and formed into a QVector<double> and a signal emitted with the address of the QVector<double> in which the data is held. The data can now be interpreted by implementing a slot and processed within Qt until fresh data becomes available on the serial port.


mega1 = new ArduinoTalker(this);

mega1->ConnectToArduino("/dev/ttyACM0");

connect(mega1, SIGNAL(NewDataArrivedFromArduino(QVector<double>*)), this, SLOT(DoSomethingWithIncomingData(QVector<double>*)));

It is important to remember to clear the incoming buffer by calling ArduinoTalker::ClearArduinoIncomingVector() once data has been
interpreted. If this is not done, fresh data will be appended to the already existing inData QVector.

Sending Data to Arduino

3. To send data to the Arduino, it is first stored (by the parent program) in the QVector<double> outData member of the Arduinotalker class by calling the ArduinoTalker::AddDataToOutBuffer(double num) function. This function will append the value num to the QVector<double> outData member and must be invoked for each floating point value that needs to be sent to the Arduino. Whenever we are ready to send this data to the Arduino, the ArduinoTalker::SendDataToArduino() function is invoked which will parse all the numbers in the outData array into the correct string format and transmit these over the serial line to the Arduino.

It is important to remember to clear the out buffer by calling ArduinoTalker::ClearOutBuffer() once data has been sent.

4. On the Arduino end, the incoming data must be parsed into floating point numbers as follows:-


if(Serial.available())
{
for(currentIndex = 0; currentIndex < NUMBER_OF_FIELDS; currentIndex++)
{
dataIn[currentIndex] = Serial.parseFloat();
}

currentIndex = 0;

//now do something with the dataIn[] array....

}

My ArduinoTalker class is far from perfect and needs a lot of work before it becomes a fully functional serial interface to the Arduino. Some things I would like to implement:-

1. Change connection speeds (baud rates) without disconnecting and then re-connecting

2. Increase the baud rate…at present the best I can achieve is about 4800 bps. Beyond this, the data is garbled. I wonder if this has anything to do with Qt’s signal-slot mechanism.

3. Include an error checking mechanism, a simple parity check should be ok for starters

The screenshot below shows data that is sensed from an MPU6050 6-DOF accelerometer-gyro unit by an Arduino UNO and is being sent to a Qt
application via serial line using my ArduinoTalker class. In this application, I am just parsing the raw accelerometer data (in 3 axes) and the gyro-scope data(in 3 axes) and graphing them on the screen. Click on the image to zoom in.

Receiving data in Qt from an MPU-6050 6 DOF Accelerometer and Gyro sensor using the Arduinotalker class

Receiving data in Qt from an MPU-6050 6 DOF Accelerometer and Gyro sensor using the Arduinotalker class

[EDIT] I have upgraded the ArduinoTalker class. It now can handle data rates upto 115200 baud and includes a primitive error checking algorithm. More details, including the download link are here.

To use this class, just include it into your Qt 5 project, create an instance of the ArduinoTalker class using the correct port name and it should work automatically. Remember to edit your .pro file and add QT+= serialport

Advertisements

One thought on “void ArduinoTalker::Serial_Class_for_Qt_5()

  1. Pingback: Arduino Serial Communications with Qt: Better and Faster | Bayesian Adventures

Leave a Reply

Fill in your details below or click an icon to log in:

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