Introduction: Reading RPM From Arduino-based IR Tachometer With MATLAB GUI

Hello again, a couple days back I posted an instructable of infrared tachometer using arduino, then I realized that rather than reading the RPM value in the Arduino IDE serial monitor, presenting the RPM in a proper frame would look more hi-tech. So, I tried to make a small program with MATLAB GUI.

I know I can merge this project with my previous instructable, but I prefer to make a new one because maybe some people have already done their sensing and sending the data to the serial and only want to see how to make MATLAB retrieve and show that value sent through serial. Of course, this way I can have more instructables also :)

Therefore, I will just go directly to the MATLAB part because that is the main thing we are going to discuss here. Anything else beyond your computer's USB port please refer to my previous instructable: https://www.instructables.com/id/Infrared-Tachomete...

Step 1: Create GUI Layout in MATLAB

Open your MATLAB, then in type a command: "guide"

If everything is OK, a window will open for you to design the layout. If you cannot get that window, please check of you have that module in your MATLAB installation or not. My MATLAB version is R2012b installed with default settings & packages.

Let us assume that you get something good after typing "guide". Place window components as follows:

- 1 Toggle button

- 2 Static Texts

Arrange the layout as shown in the picture (actually the layout is up to you, as long as it is easy to use and read), change the text (anything you wish) in each object by modifying the "String" value in the Property Inspector (select object - right click - Property Inspector, or double click)

Then, save that gui fig file.

Step 2: Write the Code

ARDUINO CODE

The code for arduino is basically the same as you can find here: https://www.instructables.com/id/Infrared-Tachomete... but because here I only want to show the rpm value (not the rps value and all the "rps" and "rpm" text) so I edited some lines (those that have Serial.print(), because previously the program was designed to present the reading on notepad-style serial monitor but now we only need the rpm value to feed into the static text string). OK, to make it quick and easy I copy the code here, you can check by your self for comparison with the previous code. Remember that the main purpose of the arduino code is only to pass a value to serial comm, so this program is just as an example, if you have your own program that prints the value of any sensor reading to serial then ignore this go ahead to the MATLAB code.

int sensorvalue;<br>int state1 = HIGH;
int state2;
float rps;
float rpm;
long prevMillis = 0;
long interval = 100;
long currentTime;
long prevTime = 1;
long diffTime;
int sensorthreshold = 30;  // this value indicates the limit reading between dark and light,
                           // it has to be tested as it may change acording on the 
                           // distance the leds are placed.
                           // to see what number is good, check the sensorvalue variable value
                           // as printed out in the serial monitor</p><p>void setup()
{
  Serial.begin(9600);
  pinMode(13,OUTPUT);      // assign pin 13 led as indicator because we cannot se the IR light
}

void loop()
{
  sensorvalue = analogRead(0); // read from pin 0
  if(sensorvalue < sensorthreshold)
    state1 = HIGH;
   else
    state1 = LOW;
   digitalWrite(13,state1); // as iR light is invisible for us, the led on pin 13 
                            // indicate the state of the circuit.

   if(state2!=state1){      //counts when the state change, thats from (dark to light) or 
                            //from (light to dark), remember that IR light is invisible for us.
     if (state2>state1){
       currentTime = micros();   // Get the arduino time in microseconds
       diffTime = currentTime - prevTime;  // calculate the time difference from the last sensors meet-up
       rps = 1000000/diffTime;   // calculate how many rev per second - good to know
       rpm = 60000000/diffTime;  // calculate how many rev per minute
       
       unsigned long currentMillis = millis();
       
       // print to serial at every interval - defined at the variables declaration
       if(currentMillis - prevMillis > interval){ // see if now already an interval long
       prevMillis = currentMillis;       
       Serial.println(rpm); // this line is edited from the code in the prev instructable
       }
       
       prevTime = currentTime;
     }
     state2 = state1;
   }
 /* only for testing to determine the sensorthreshold value
 delay(500);
 Serial.println(sensorvalue);
 */

}

MATLAB CODE

In your MATLAB GUI layout design window, click View - Editor (or find in the toolbar a picture of paper and pencil without hand). An editor window will open with some codes written already, MATLAB wrote them for you no problem. Only write the callback function for the toggle button, the rest of the code can be left untouched. In my case, I named my toggle button OnOffToggle, so the function under which I wrote the code is function OnOffToggle_Callback(hObject, eventdata, handles).

Any data sent through the serial is retrieved here as a variable rpmdata, so we just want to print that rpm data to the screen, that's it. One more thing, verify that you are connecting your arduino to the correct COM port as you write in the code. In this code I wrote COM3 because I connected my arduino to COM3.

Then save your m-file.

Below is the full code (edit only the OnOffToggle_Callback function):

function varargout = gui(varargin)
% GUI MATLAB code for gui.fig
%      GUI, by itself, creates a new GUI or raises the existing
%      singleton*.
%
%      H = GUI returns the handle to a new GUI or the handle to
%      the existing singleton*.
%
%      GUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in GUI.M with the given input arguments.
%
%      GUI('Property','Value',...) creates a new GUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before gui_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to gui_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help gui
% Last Modified by GUIDE v2.5 14-Mar-2015 01:06:09</p><p>% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @gui_OpeningFcn, ...
                   'gui_OutputFcn',  @gui_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before gui is made visible.
function gui_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to gui (see VARARGIN)
% Choose default command line output for gui
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes gui wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = gui_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
function currentEdit_Callback(hObject, eventdata, handles)
function currentEdit_CreateFcn(hObject, eventdata, handles)
% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function OnOffToggle_Callback(hObject, eventdata, handles)
button_state = get(hObject,'Value');
if button_state == get(hObject,'Max')
    set(handles.OnOffToggle,'String','Stop');
    drawnow;
    i=2;
    while i > 1
        rpmdata = serial('COM3','BaudRate',9600); % this Baud rate should be the same as that in Arduino code
        fclose(instrfindall);
        fopen(rpmdata);
        b = fscanf(rpmdata);
        set(handles.textCurrent,'String',b);
        drawnow;
        delete(rpmdata)
        if get(hObject,'Value') == get(hObject,'Min')
            break
        end
    end
    set(handles.OnOffToggle,'String','Start');
    drawnow;
    rpmdata = serial('COM3','BaudRate',9600);
    fclose(rpmdata);
end

Step 3: Run the Rpm Reader

Once you finished with your code, connect your arduino, turn the wheel and run your program (green triangle play-like button on editor or layout editor window). A window of your program will come out (mine is as shown in the picture), click the toggle button and you will see the current rpm of your wheel there.

You can see how the program works in the video.

Hopefully someone will find this useful... Any feedback will be appreciated :) thanks!

Attachments