Arduino & Matlab: real time plot

 

Con questo mini post scopriremo come plottare con Matlab i dati ricevuti da un pin dell’Arduino. Specialmente nei progetti Meccatronici, risulta inevitabile acquisire i dati, processarli e generare un’uscita da inviare ad esempio ad un motore elettrico. Nonostante la sua semplicità, la capacità di calcolo dell’Arduino è ridotta, non si può di certo pensare alla creazione di matrici ed operazioni ad esse annesse, risulta quindi molto conveniente sfruttare le capacità di un software di calcolo numerico come Matlab.

COME INIZIARE

Innanzitutto occorre stabilire una comunicazione client-server tra Arduino e Matlab, rifacendoci al precedente articolo “Arduino incontra Matlab!” i passi necessari per installare il pacchetto sono:

1) scaricare Arduino IO Package dal sito della Mathworks
2) caricare lo  sketck  /pde/adiosrv/adiosrv.pde nell’Arduino
3) assicurarsi che si possa scrivere sul file pathdef.m in caso contrario cambiare le proprietà, per i possessori di Linux digitare da terminale il comando (il percorso dipende da dove è stato installato Matlab)

[cpp]sudo chmod 777 usr/local/matlab/R2012a/toolbox/local/pathdef.m [/cpp]

4) aprire Matlab, includere nella current folder la cartella scaricata ed eseguire il comando

[cpp]install_arduino[/cpp]

Installati i protocolli di comunicazione, occorre infine collegare Arduino, e digitare da Matlab il comando:

[cpp] a=arduino(‘port’)</code>
[/cpp]

in cui al posto di port per gli utenti di Windows bisogna specificare la porta COM dove l’Arduino è collegato, ad esempio la COM1, per gli utenti di Linux, al posto di port inserire /dev/ttyUSB0

Se è andato tutto a buon fine, sulla Command Window di Matlab appare il seguente messaggio:

[cpp] &gt;&gt; a=arduino(‘/dev/ttyUSB1’);
Attempting connection ……..
Basic I/O Script detected !
Arduino successfully connected !
&gt;&gt; [/cpp]

REAL TIME PLOT

Instaurata la connessione con Arduino, possiamo raccogliere i dati letti da una porta, ed effettuare su di essi varie operazioni, tra le più comuni visualizzare l’andamento grafico in tempo reale. Per prima cosa colleghiamo un sensore all’Arduino, in questo esempio è stato utilizzato un potenziometro angolare multigiro, di seguito viene riportato lo schema circuitale in Fritzing

In questo caso si è considerato come pin di lettura l’AnalogIn 0, di conseguenza la caduta di tensione ai capi del potenziometro viene letta da tale pin e, digitalizzata mediante l’A/D converter dell’Arduino assumerà un valore che varia tra 0 e 1023.

Inizializziamo il tempo, il vettore in cui verranno salvati i valori in ingresso all’Arduino, il passo del ciclo, e la condizione di ciclo:

[cpp] t=0;
x=0;
interv=1000; % consideriamo 1000 campioni
passo=1; %abbassando il passo si ha un numero di cicli e quindi si acquisiscono più dati
[/cpp]

successivamente facciamo partire un ciclo while al cui interno, viene recuperato il dato dalla porta analogica, salvato in coda al vettore x e plottato:

[cpp] while(t<interv)
b=a.analogRead(0);
x=[x,b];
plot(x);
[/cpp]

Bisogna però aggiungere qualche riga di codice per completare il tutto ovvero manca di definire le caratteristiche (limite inferiore e superiore) dell’asse dell’ascissa e dell’ordinata, inserire la griglia, incrementare la variabile t, ed infine aggiornare il grafico.  Nel caso in questione il potenziometro adottato varia all’interno della fascia in ordinata tra i valori 680 e 800.

[cpp] %sempre all’interno del ciclo while
axis([0,interv,680,800]) %asse_x [0-interv] asse_y [680,800] grid %disegna la griglia
t=t+passo; %aggiornamento della variabile t
drawnow
end %fine del ciclo while
[/cpp]

CODICE COMPLETO

in definitiva il codice completo da utilizzare in Matlab è il seguente:

[cpp] t=1;
x=0;
while(t<interv)
b=a.analogRead(0);
x=[x,b];
plot(x);
axis([0,interv,680,800]);
grid
t=t+passo;
drawnow;
end
[/cpp]

Oss

Per valori troppo grandi della variabile interv, o per un valore di passo troppo basso, la dimensione del vettore x potrebbe diventare elevata rallentando la visualizzazione del plot.

ecco il risultato…

Francesco Celiberti
Ciao a tutti,

mi chiamo Francesco, sono laureato in Ing. Informatica e dell'Automazione. Sono attualmente coinvolto in un progetto di ricerca Europeo, MOTORIST. www.motorist-ptw.eu
Tags: ,
By Francesco Celiberti | maggio 23rd, 2012 | SHOW COMMENTS (18)

18 Responses

  1. mohan murali says

    sampling rate is very low ..
    while using this code.. max of 10 hz may be..

    if try to read more than 20 hz signal it gives complete noise graph..
    pls help to improve samping rate

  2. Paulin says

    Il codice completo mi sembra non essere quello che avete messo. Per favore lo potete riguardare e correggerlo? Per noi che siamo all’inizio risulta un po difficile seguirlo.
    Grazie

    • Francesco Celiberti
      fra_celi says

      Ciao Paulin,

      ho ricontrollato, il codice completo è identico a quello mostrato nel video, puoi dirmi di preciso cosa non ti è chiaro, cosi posso darti una mano?

      Francesco

  3. Irsyaad says

    Hi, can i just ask, what if i have multiple inputs? can i plot all these into a graph. for example, a graph with many lines.

    Thanks in advance!
    Regards,
    Irsyaad

  4. abdo says

    hi , I work with matlab R2015a this code don’t works for me !
    saying that :
    while(t<interv)
    |
    Error: Unbalanced or unexpected parenthesis or bracket.

    • Automazione Open Source
      automazioneos says

      Hi, Can you post the entire code?

  5. Augusto Firmo says

    Hi, do you know how plot two analog entrances in a same graph?

  6. Youssef Hanna says

    i want to set the sampling rate to 1.5 KHz can u help?

  7. Aruthiran Yogenthira says

    can i know the rate at which this method obtains samples per second, the sampling frequency. And can i know whether the sampling frequency can be altered??

    • fra_celi says

      Sure! All you have to do is just use the tick and tock functions in each cycle, the difference between their values, returns the elapsed within a cycle. You can set the samplig freq by executing the code inside the while, only when the elapsed time (difference between the returned values of tock and tick functions) is greater or equal to a certain elapsed time expressed in ms.

  8. daniel says

    you can show me how to display the signal straight into a gui? and how do I reset or restart the acquisition?

    • fra_celi says

      Hi Daniel,

      you can use Processing2 –> http://www.processing.org/ to create a simple and quick GUI, or ROS –> http://www.ros.org/

      In order to restart the acquisition, you can put a condition into the while cycle, which clears the figure and the x vector
      sets the axes to zero

  9. Pier says

    Ciao ho trovato molto interessante l’articolo e ho una domanda. Non capisco quale sia l’unità di misura di “passo=1” ! Se volessi avere in ascissa del grafico il tempo espresso in secondi come dovrei fare? E ancora se volessi dire a matlab di campionare il segnale ogni 100 ms come dovrei fare?

    • fra_celi says

      Ciao! dunque passo=1 non indica una unità di misura. Il “tempo” viene memorizzato nella variabile t, e la frequenza con cui avviene l’aggiornamento di tale variabile dipende dalla velocità di esecuzione del ciclo for. Per campionare un segnale con una frequenza desiderata, puoi usare le funzioni “tic” e “toc” di Matlab, ecco la reference http://www.mathworks.co.uk/help/matlab/ref/toc.html

      grazie per il commento 😉

  10. aku says

    i got problem with “plot(x)
    my command window return this:??? Error using ==> plotInvalid first data argumentError in ==> realtime at 15    plot(x) 

    • Automazione Open Source
      automazioneos says

      can you post the complete code you’re using?

  11. Propeller Pendulum: regolazione a 90° con PID | Automazione Open Source says

    […] per prima cosa occorre instaurare la connessione tra Matlab e Arduino, in precedenti post post2 abbiamo trattato […]

  12. Luciano Mariani says

    ciao ragazzi bel blog, volevo solo suggerirvi “ardulab”, provate a vedere che cosa si puo’ fare con lui. potreste inserirlo per qualche articolo, ciao