Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
Adrian Palafox
Published © TAPR-OHL

Osciloscope MATLAB + ARDUINO

This is a complete project on how to transform an arduino into an ocilloscope using matlab

IntermediateFull instructions provided2 hours415
Osciloscope MATLAB + ARDUINO

Things used in this project

Story

Read more

Schematics

PIN IN

Code

Interfaz_PPG.m

MATLAB
this is the code that the arduino must have
%% Cdigos de inicializacin de la interfaz
function varargout = Interfaz_PPG(varargin)
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @Interfaz_PPG_OpeningFcn, ...
                   'gui_OutputFcn',  @Interfaz_PPG_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 Interfaz_PPG is made visible.
%ejecucion de la interfaz grafica
function Interfaz_PPG_OpeningFcn(hObject, eventdata, handles, varargin)
% Choose default command line output for Interfaz_PPG
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
handles.a=arduino;
handles.a
set(handles.puerto,'String',handles.a.Port);
set(handles.placa,'String',handles.a.Board);
set(handles.PININ,'String',handles.a.AvailableAnalogPins);


% --- Outputs from this function are returned to the command line.
function varargout = Interfaz_PPG_OutputFcn(hObject, eventdata, handles) 
% Get default command line output from handles structure
varargout{1} = handles.output;

% ...::: Codigos de adquisicin y de interfaz :::...

% Ajuste de escala de voltaje
function vol_Callback(hObject, eventdata, handles)

function vol_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% Ajuste de posicin
function pos_Callback(hObject, eventdata, handles)

function pos_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% Ajuste de escala detiempo-----------------
function time_Callback(hObject, eventdata, handles)

function time_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% Boton para reestablecer valores iniciales------------------------
function restart_Callback(hObject, eventdata, handles)
set(handles.vol,'Value',0);
set(handles.pos,'Value',0);
set(handles.time,'Value',1);
set(handles.superior,'Value',5);
set(handles.inferior,'Value',0);
set(handles.cursor_a,'Value',0);
set(handles.cursor_b,'Value',10);

% Boton para iniciar el programa-----------------------------------
function start_Callback(hObject, eventdata, handles)
clc
global stop 
stop = 0;
global pause
pause = 0;
% Limpiamos y abrimos el puerto para Arduino-------------------- 
%puerto real---------------------------------------------------
delete(instrfind({'Port'},{'COM9'}));
IO = arduino('COM9');

% Parmetros de medidas---------------------------------------------
mps = 20;
tmax = get(handles.time,'Value'); % Tiempo de captura en segundos
tmax = round(tmax,0)*10; 
pos = get(handles.pos,'Value');
vol = get(handles.vol,'Value');

% Preparar la figura----------------------------------------
cla(handles.axes1,'reset');
axes(handles.axes1);
axis([0 tmax (-0.5+pos+vol) (5+pos-vol)]);
l1 = line(nan,nan,'Color','b','LineWidth',2);
l2 = line(nan,nan,'Color','r','LineWidth',2);
l3 = line(nan,nan,'Color','g','LineWidth',2);
l4 = line(nan,nan,'Color','m','LineWidth',2);
l5 = line(nan,nan,'Color','c','LineWidth',2);
grid on
hold on

% Inicializar---------------------------------------------
v1 = zeros(1,tmax*mps);
i = 1;
a = 0;
b = tmax;
band = tmax;
% Ejecutar bucle cronometrado-------------------------------
while (stop == 0)
    if(pause == 1)
        myString = sprintf('En pausa');
    else
        myString = sprintf('T. Real');
    end
    set(handles.texto_pausa, 'String', myString);
    tmax = get(handles.time,'Value');  
    if(tmax >= 1)
        tmax = round(tmax,0)*10;
    else
        tmax = round(tmax*10,0); 
    end
    pos = get(handles.pos,'Value');
    vol = get(handles.vol,'Value');
    ch = i/mps;
    if (ch >= b)
        cla(handles.axes1,'reset');
        a = a + tmax;
        b = b + tmax;
        if(ch >= 60)
            i = 1;
            a = 0;
            b = tmax;
        end
        v1 = zeros(a,b*mps);
        axis([a b (-0.5+pos+vol) (5+pos-vol)])
        l1 = line(nan,nan,'Color','b','LineWidth',2);
        l2 = line(nan,nan,'Color','r','LineWidth',2);
        l3 = line(nan,nan,'Color','g','LineWidth',2);
        l4 = line(nan,nan,'Color','m','LineWidth',2);
        l5 = line(nan,nan,'Color','c','LineWidth',2);
        grid on
    else
        if(tmax ~= band)
            b = a + tmax;
            band = tmax;
        end
        %limites de grafica
        axis([a b (-0.5+pos+vol) (5.5+pos-vol)])
    end
    
    % Leer del puerto analgico-----------------------------------A0   
    if(pause == 0)
        v1(i)= readVoltage(IO,'A0');
    end
    % Dibujar en la figura
    if(a == 0)
        st = 1;
        x = linspace(0,i/mps,i);
        set(l1,'YData',v1(st:i),'XData',x); % Seal
    else
        st = a*mps;
        x = linspace(a-1/20,i/mps,i-st+1);
        set(l1,'YData',v1(st:i),'XData',x); % Seal
    end
    sup = linspace(get(handles.superior,'Value'), get(handles.superior,'Value'), length(x));
    set(l2,'YData',sup,'XData',x); % Superior
    inf = linspace(get(handles.inferior,'Value'), get(handles.inferior,'Value'), length(x));
    set(l3,'YData',inf,'XData',x); % Inferior
    A = a+(b-a)/10*get(handles.cursor_a,'Value');
    set(l4,'YData',[0 5],'XData',[A A]); % A
    B = a+(b-a)/10*get(handles.cursor_b,'Value');
    set(l5,'YData',[0 5],'XData',[B B]); % B
    dv = sprintf('%f', round(sup-inf,2));
    set(handles.delta_v, 'String', dv);
    dt = sprintf('%f', round(B-A,2));
    set(handles.delta_t, 'String', dt);
    drawnow
    % Seguir
    if(pause == 0)
        i = i+1;
    end
    
end

% Botn para detener el programa
function stop_Callback(hObject, eventdata, handles)
global stop
stop = 1;


% Slider de cursor superior
function superior_Callback(hObject, eventdata, handles)

function superior_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% Slider de cursor inferior
function inferior_Callback(hObject, eventdata, handles)

function inferior_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% Boton de pausa de Grfica
function pausa_Callback(hObject, eventdata, handles)
global pause
if(pause == 0)
    pause = 1;
else
    pause = 0;
end


% Slider de cursor A
function cursor_a_Callback(hObject, eventdata, handles)

function cursor_a_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end

% Slider de cursor B
function cursor_b_Callback(hObject, eventdata, handles)

function cursor_b_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end



function puerto_Callback(hObject, eventdata, handles)
% hObject    handle to puerto (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of puerto as text
%        str2double(get(hObject,'String')) returns contents of puerto as a double


% --- Executes during object creation, after setting all properties.
function puerto_CreateFcn(hObject, eventdata, handles)
% hObject    handle to puerto (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% 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 figure1_CloseRequestFcn(hObject, eventdata, handles)
% Hint: delete(hObject) closes the figure
clear handles.a
delete(hObject);
clear

Interfaz_PPG.fig

MATLAB
this is matlab visual interface
No preview (download only).

Graph

Arduino
this is the code that the arduino must have
/*
  Graph

  A simple example of communication from the Arduino board to the computer: The
  value of analog input 0 is sent out the serial port. We call this "serial"
  communication because the connection appears to both the Arduino and the
  computer as a serial port, even though it may actually use a USB cable. Bytes
  are sent one after another (serially) from the Arduino to the computer.

  You can use the Arduino Serial Monitor to view the sent data, or it can be
  read by Processing, PD, Max/MSP, or any other program capable of reading data
  from a serial port. The Processing code below graphs the data received so you
  can see the value of the analog input changing over time.

  The circuit:
  - any analog input sensor attached to analog in pin 0

  created 2006
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe and Scott Fitzgerald

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Graph
*/

void setup() {
  // initialize the serial communication:
  Serial.begin(9600);
}

void loop() {
  // send the value of analog input 0:
  Serial.println(analogRead(A0));
  // wait a bit for the analog-to-digital converter to stabilize after the last
  // reading:
  delay(2);
}

/* Processing code for this example

  // Graphing sketch

  // This program takes ASCII-encoded strings from the serial port at 9600 baud
  // and graphs them. It expects values in the range 0 to 1023, followed by a
  // newline, or newline and carriage return

  // created 20 Apr 2005
  // updated 24 Nov 2015
  // by Tom Igoe
  // This example code is in the public domain.

  import processing.serial.*;

  Serial myPort;        // The serial port
  int xPos = 1;         // horizontal position of the graph
  float inByte = 0;

  void setup () {
    // set the window size:
    size(400, 300);

    // List all the available serial ports
    // if using Processing 2.1 or later, use Serial.printArray()
    println(Serial.list());

    // I know that the first port in the serial list on my Mac is always my
    // Arduino, so I open Serial.list()[0].
    // Open whatever port is the one you're using.
    myPort = new Serial(this, Serial.list()[0], 9600);

    // don't generate a serialEvent() unless you get a newline character:
    myPort.bufferUntil('\n');

    // set initial background:
    background(0);
  }

  void draw () {
    // draw the line:
    stroke(127, 34, 255);
    line(xPos, height, xPos, height - inByte);

    // at the edge of the screen, go back to the beginning:
    if (xPos >= width) {
      xPos = 0;
      background(0);
    } else {
      // increment the horizontal position:
      xPos++;
    }
  }

  void serialEvent (Serial myPort) {
    // get the ASCII string:
    String inString = myPort.readStringUntil('\n');

    if (inString != null) {
      // trim off any whitespace:
      inString = trim(inString);
      // convert to an int and map to the screen height:
      inByte = float(inString);
      println(inByte);
      inByte = map(inByte, 0, 1023, 0, height);
    }
  }

*/

/* Max/MSP v5 patch for this example

  ----------begin_max5_patcher----------
  1591.3oc0YszbaaCD9r7uBL5RalQUAO3CvdyS5zVenWZxs5NcfHgjPCIfJIT
  RTxj+6AOHkoTDooroUs0AQPR73a+1cwtK3WtZxzEpOwqlB9YveAlL4KWMYh6
  Q1GLo99ISKXeJMmU451zTUQAWpmNy+NM+SZ2y+sR1l02JuU9t0hJvFlNcMPy
  dOuBv.U5Rgb0LPpRpYBooM3529latArTUVvzZdFPtsXAuDrrTU.f.sBffXxL
  vGE50lIHkUVJXq3fRtdaoDvjYfbgjujaFJSCzq4.tLaN.bi1tJefWpqbO0uz
  1IjIABoluxrJ1guxh2JfPO2B5zRNyBCLDFcqbwNvuv9fHCb8bvevyyEU2JKT
  YhkBSWPAfq2TZ6YhqmuMUo0feUn+rYpY4YtY+cFw3lUJdCMYAapZqzwUHX8S
  crjAd+SIOU6UBAwIygy.Q1+HAA1KH6EveWOFQlitUK92ehfal9kFhUxJ3tWc
  sgpxadigWExbt1o7Ps5dk3yttivyg20W0VcSmg1G90qtx92rAZbH4ez.ruy1
  nhmaDPidE07J+5n2sg6E6oKXxUSmc20o6E3SPRDbrkXnPGUYE.i5nCNB9TxQ
  jG.G0kCTZtH88f07Rt0ZMMWUw8VvbKVAaTk6GyoraPdZff7rQTejBN54lgyv
  HE0Ft7AvIvvgvIwO23jBdUkYOuSvIFSiNcjFhiSsUBwsUCh1AgfNSBAeNDBZ
  DIDqY.f8.YjfjV1HAn9XDTxyNFYatVTkKx3kcK9GraZpI5jv7GOx+Z37Xh82
  LSKHIDmDXaESoXRngIZQDKVkpxUkMCyXCQhcCK1z.G457gi3TzMz4RFD515F
  G3bIQQwcP3SOF0zlkGhiCBQ1kOHHFFlXaEBQIQnCwv9QF1LxPZ.A4jR5cyQs
  vbvHMJsLll01We+rE2LazX6zYmCraRrsPFwKg1ANBZFY.IAihr8Ox.aH0oAL
  hB8nQVw0FSJiZeunOykbT6t3r.NP8.iL+bnwNiXuVMNJH9H9YCm89CFXPBER
  bz422p8.O4dg6kRxdyjDqRwMIHTbT3QFLskxJ8tbmQK4tm0XGeZWF7wKKtYY
  aTAF.XPNFaaQBinQMJ4QLF0aNHF0JtYuHSxoUZfZY6.UU2ejJTb8lQw8Fo5k
  Rv6e2PI+fOM71o2ecY1VgTYdCSxxUqLokuYq9jYJi6lxPgD2NIPePLB0mwbG
  YA9Rgxdiu1k5xiLlSU6JVnx6wzg3sYHwTesB8Z5D7RiGZpXyvDNJY.DQX3.H
  hvmcUN4bP1yCkhpTle2P37jtBsKrLWcMScEmltOPv22ZfAqQAdKr9HzATQwZ
  q18PrUGt6Tst2XMCRUfGuhXs6ccn23YloomMqcTiC5iMGPsHsHRWhWFlaenV
  XcqwgCQiGGJzptyS2ZMODBz6fGza0bzmXBj7+DA94bvpR01MffAlueO7HwcI
  pWCwmzJdvi9ILgflLAFmyXB6O7ML0YbD26lenmcGxjVsZUN+A6pUK7AtTrPg
  M+eRYG0qD9j4I7eEbco8Xh6WcO.or9XDC6UCiewbXHkh6xm5LiPEkzpJDRTu
  mEB44Fgz4NCtJvX.SM1vo2SlTCZGAe7GZu6ahdRyzFOhYZ+mbVVSYptBw.K1
  tboIkatIA7c1cTKD1u.honLYV04VkluHsXe0szv9pQCE9Ro3jaVB1o15pz2X
  zYoBvO5KXCAe0LCYJybE8ZODf4fV8t9qW0zYxq.YJfTosj1bv0xc.SaC0+AV
  9V9L.KKyV3SyTcRtmzi6rO.O16USvts4B5xe9EymDvebK0eMfW6+NIsNlE2m
  eqRyJ0utRq13+RjmqYKN1e.4d61jjdsauXe3.2p6jgi9hsNIv97CoyJ01xzl
  c3ZhUCtSHx3UZgjoEJYqNY+hYs5zZQVFW19L3JDYaTlMLqAAt1G2yXlnFg9a
  53L1FJVcv.cOX0dh7mCVGCLce7GFcQwDdH5Ta3nyAS0pQbHxegr+tGIZORgM
  RnMj5vGl1Fs16drnk7Tf1XOLgv1n0d2iEsCxR.eQsNOZ4FGF7whofgfI3kES
  1kCeOX5L2rifbdu0A9ae2X.V33B1Z+.Bj1FrP5iFrCYCG5EUWSG.hhunHJd.
  HJ5hhnng3h9HPj4lud02.1bxGw.
  -----------end_max5_patcher-----------

*/

Credits

Adrian Palafox
1 project • 1 follower
Soy ingeniero eléctrico con más de 10 años de experiencia en la industria eléctrica y electrónica, a hora docente de ingenieria,

Comments