Introduction: Arduino and Matlab: Let Them Talk Using Serial Communication!
since when I've started playing with Arduino, I have always been wandering how I could make it talk and interact with the Matlab environment in an easy and effective way. I bumped into many Instructables and tutorials dealing with Arduino libraries and Matlab script files to get them talking one to each other. What I've never been able to find, though, was a straightforward tutorial that could teach me how to understand the core of the serial communication with an external hardware.
Here's an Instructable that will guide you throughout the essential steps you will be in need of, if you want to acquire data from the external world using the Arduino interface without giving up using the powerful data visualization and elaboration engine given by Matlab! It is extremely easy to understand it! I know the struggle one can go through facing for the first time this kind of things!
I'll be go through few steps in which I'll be illustrating the basis of a serial communication established between Arduino (our external physical interface) and our PC (the data collector and elaborator). Everything will be referred to a very simple case study of a temperature/humidity sensor (DHT_22) wired up to Arduino, and that will act as the data source. The fun thing is that this Instructable applies quite unchanged to almost all tipe of sensors you want to get and visualize data from! So temperature, humidity as well as light, proximity sensors or 3-axis gyroscopes....The core is really the same!
Hope it will be helpful to all of you interested!!
Step 1: Getting the Concept.
The general idea one should keep in mind when it comes to wire up Arduino to Matlab is that they shall communicate using the same language and protocol. That is the serial communication via USB port. Both In Arduino and Matlab coding environment we have specific commands that enables the serial communication, but the core behind its operation is built on the same few principles:
- Arduino and Matlab should both know the rate (BAUD RATE) at which they share infos and the physical serial port they are talking through, otherwise they are not going to understand each other;
- They both have commands to send (WRITE) data to the other part through the serial port;
- ...and of course commands to receive and READ data from the serial buffer, which is a temporary storage space in which written data are kept waiting to be picked up and removed (READ).
What we are going to do, after wiring up the temperature sensor as illustrated in the Fritzing scheme, is writing the code that will run on Arduino, and a Matlab script with a bunch of functions, that will allow us to query Arduino for the temperature readings.
Before illustrating the codes in detail, let's fix the concept by schematizing the whole thing:
on the Arduino board we will upload a program that, when asked by a serial command (serial means that passes through the serial port!), will make the board retrieve the temperature reading from the sensor, and subsequently copy it in the serial buffer, ready to be picked up by Matlab!
Matlab, on the other side, will do the rest of the job: a script will be run, and at a fixed frequency, will send the Temperature reading request string to Arduino, and will read back the temperature value sent to the serial buffer plotting it in a real time graph Temperature vs Time.
That's it! Now let's start moving a little bit further....
Step 2: The Arduino Code!
Attached here, you will find the .ino file with the script you will have to upload on your board, but since I said that this want to be a tutorial whose main aim is to lead you directly to the core of the versatile serial communication between Arduino and Matlab, let me comment it! (you may want to open the .ino file in the Arduino IDE and follow the following comments in parallel, trust me it will help you). I really don't like to fill the script itself with comments, since it result in a messy look!
Skip the following lines if you are using a different sensor, or your purpose for using the serial communication with Matlab is different! The script start with the inclusion of the DHT library you will find attached as well (copy the .cpp and .h files in a folder called DHTlib inside the libraries folder related to Arduino in your PC, you aren't going to need anything else) and defining a couple of useful variables: temp, to store the temperature value, and val, assigned to the characters sent by Matlab.
In the setup area we have to include the real player of the game: serial communication initializer. more info here>> Arduino Serial. So we write Serial.begin(9600), where 9600 is the baud rate, namely the velocity at which we would like the two guys to talk to each other (we will set the same rate when we will take care of the Matlab serial object). The few code lines that follow are just a simple handshake to know if the serial communication has started flawlessly. Actually you can exclude it! Just not to leave anything unclear, with the handshake, Arduino send the character 'a' to the serial buffer, and when Matlab will read it visualizing an "ok message" we will know that they are talking to each other properly.
Now let's come to the main loop. Arduino always has to keep an eye wide open on what it's happening in the serial port! So with the line
if (Serial.available() > 0)
we are asking him to check as fast as he can, if something has been put in the famous serial buffer by Matlab, and if it is the case, to store the value in the variable val!
With the further if loop:
if (val == 'R')
we check if the command sent through the serial port, coincide with the one we assigned to the sensor reading. If even this condition is fulfilled, the reading function getTemperature() is launched, and the correlated temperature value is sent back to the serial buffer with the Serial.println(val) function.
We are done here with Arduino. You can upload the sketch, and leave the Arduino connected through the serial port (USB) to the computer. One last important thing: make sure you know the name of the port Arduino is connected to. You can check it by going to "instrument" in the Arduino IDE, and checking which port is ticked in the top down menu named "port". Write down the name, we will use it later! If you are a Windows user, it will be something like "COM1" or "COM2" ecc., if you are using MAC, it will be something like "/dev/tty.KeySerial1".
Step 3: Matlab: Let's Tame the Beast!
Here I assume that you are familiar with the Matlab environment, at least with the basis. If my assumption is not correct, don't panic, and have a look here: Matlab for beginners!
I'll tackle the Matlab side in the following way: I will create a single script .m file that will include all the functions we are going to use. In this way, once you'll get the grasp on each section of the script (MainScript), all you have to do is launch it by writing its name in the workspace, and suddenly you will have Arduino and your PC exchanging data nicely and easily! Make sure you save all the three documents I've attached here inside the same folder that has to be selected as the current folder in the "Current Folder" window in the Matlab main view! As a general rule you must remember that Matlab has to access easily the function you are citing inside the main script, otherwise you are getting an error signal of a function not declared!
We will start the script with saving the serial port name in the variable comPort. As I told you before, make sure you know the exact name of the port Arduino is connected to. With the new section, we take care of the serial communication initialization. We are going to write a function file named setupSerial, which accept as input the serial port header, and gives back the serial object arduino and the "serialFlag" value that tells us that the serial object has been created.
useful tip: if you need some help with the syntax function or with any other Matlab command, don't hesitate to ask Matlab! You have just to type in in the Matab command window, "help" followed by the topic you want to know more about. If the topic exists, Matlab will give you a short answer directly in the command widow, otherwise you can navigate the "help browser" by typing "doc" in the workspace and click enter.
Let's move on! I'll will end analyzing the MainScript before taking in consideration the other functions.
It comes the section devoted to the graphic visualization of the data: a figure h is created, and a system of an x and y axis and a line, that will help us visualizing the data we are getting from the sensor., are created as well Keep in mind that every time you create an object, whatever its type might be (serial objects, a figure, a GUI object...ecc) you create also a series of properties associated to it. You can use those properties to call functions or to create condition for loops (while, for, if...ecc). Does the "if(~exist('h','var'))..." command make more sense now?? NO? Listen: we want to check if the property var of the object h is equal to zero! if it is the case we have to create the figure object, since a 0 in the var property, means that the figure does not exist yet!!
Now let's come to the last section of the script. Here you have few lines that act as the core of the whole program: with the "while" loop we are going to send to Arduino the "R" command, that stands for "Hey you, read the Temperature for me, and send me back the result of your reading!". You will notice that we have a new function inside the while loop that is readTemp, briefly, it will take care of the bureaucracy that lies behind the serial communication from the Matlab point of view. I will come back to it when I'll analyze the two functions of the script. One piece of information is missing: the sampling rate, at which we would like to get temperature readings. It is expressed by the "pause" command at the end of the while loop! If you want to pick a temperature value every hour, you have to write pause(3600) (pause command accept the parameter in seconds).
Ok, now let's analyze the two functions:
setupSerial: this creates the serial object Arduino connected to the serial port comPort. The command to create the serial object is simply name-of-the-object = serial(name-of-the-port). As simple as that! Note that, as one of the property of the serial object, we are setting (using the set command, followed by the property whose value we want to set) the baudrate of 9600 equal to the one set on the Arduino.
readTemp: Few more things you need to now: remember the commands we used on Arduino to WRITE into and READ from the serial buffer, Serial.println and Serial.read? Here are replaced by fprintf and fscanf respectively. That's it. The syntax is easy and you can check it in Matlab help browser. fprintf requires, as the first entry, the serial object we want to write to, and as the second piece of information the character we would like to send (in our case "R" which means for us "Read"). fscanf wants the serial object as well, and the format we want the data to be visualized, in our case a floating point number indicated with the simbol "%f" (DHT 22 temperature values are resolved down to one tenth of celsius degree).
Note that, the amount of readings that are going to be saved will be equal to the value of the variable "buf_len" (the default value in the script is 30, change it at your own whim!). After the 30th reading, the new one will be overwritten on the first reading stored in the "tcdata" array, which will contain all the temperature values in a chronological order.
Step 4: Summing Up...
An here you real time Temperature reading!
To conlude: remember that you should be careful when you are using the serial communication. You may not want to create conflicts by sending commands through the serial port, while it is in unse by some other serial object! For this reason make sure that, after you are satisfied with your measurement, you close the serial object by typing in the Matlab workspace fclose(arduino). You have to close the figure h as well! (you can save it wherever you want though) using the command close(h). If you need the read data, keep in mind that they are all stored in the "tcdata" variable, so nothing has gone lost!
I personally believe that this set up is one of the most effective to enable the communication between the two part. It doesn't clog you PC with useless libraries and leaves you free to intervene in slender scripts personalizing them as much as you want, keeping constant a bunch of core commands. The possibilities at this point are endless!
Hope it has bee somewhat helpful to you, and please, if you have some comments or wise advices, don't hesitate to contact me, with a message down below! I'm a beginner too!!
Thanks, and enjoy this powerful tool!