We can lick gravity, but sometimes the paperwork is overwhelming. - Wernher von Braun
Indice |
Introduzione
Talvolta è comodo poter manipolare su MATLAB le forme d'onda ricavate con LTspice. L'articolo propone uno script per importare su MATLAB le forme d'onda salvate in ASCII da simulazioni con LTspice.
L'utente deve soltanto inserire nello script il nome del file LTspice, la sua estensione (.raw) e la directory. Lo script riconoscerà automaticamente le variabili, salvandole nel workspace assieme ai loro valori.
LTspice IV
Codifica ASCII
LTspice salva le forme d'onda in un formato codificato. Per poterle leggere con MATLAB bisogna cambiare la codifica, impostandola in ASCII. Lo si può fare dal pannello di controllo:
Circuito d'esempio
Netlist:
* C:\Users\Amministratore\Desktop\Articolo\Es.asc V1 N001 0 SINE(0 1 5k) R1 OUT N001 3.3k C1 OUT 0 1µ .SAVE V(OUT) I(C1) .TRAN 250u .backanno .end
Poniamo che le variabili da esaminare siano la corrente che scorre nel condensatore C1 e la tensione sulla resistenza R1. Con la direttiva .SAVE si limitano le variabili di cui LTspice tiene traccia nel file .raw.
I dati di queste due forme d'onda sono nel file .raw del circuito. Se il circuito si chiama "nomeCircuito.asc" il file .raw corrispondente avrà lo stesso nome con estensione diversa: "nomeCircuito.raw".
Il file .raw
Prime decine di righe del file .raw:
Title: * C:\Users\Amministratore\Desktop\Articolo\Es.asc Date: Mon Dec 19 12:39:42 2016 Plotname: Transient Analysis Flags: real forward No. Variables: 3 No. Points: 1042 Offset: 0.0000000000000000e+000 Command: Linear Technology Corporation LTspice IV Variables: 0 time time 1 V(out) voltage 2 I(C1) device_current Values: 0 0.000000000000000e+000 0.000000000000000e+000 0.000000000000000e+000 1 2.441406235162424e-012 5.674348840351720e-017 2.324213299133404e-011 2 4.882812470324849e-012 1.702304651685713e-016 4.648426596547293e-011 3 9.765624940649698e-012 5.106913953377910e-016 9.296853187935979e-011 4 1.953124988129940e-011 1.872535114503343e-015 1.859370635007858e-010
Lo script MATLAB estrarrà i dati delle variabili da questo file .raw.
Il file .raw è molto più lungo del piccolo estratto mostrato qui.
Nel file ci sono il tempo e le due variabili che sono state salvate col comando .SAVE.
MATLAB
Il codice è commentato passo passo.
L'utente inserisce il nome del file, la sua estensione e la directory. Lo script riconoscerà automaticamente le variabili, salvandole assieme ai loro valori.
Le inserirà in un vettore di vettori di cell chiamato "variabili".
Ogni elemento del vettore "variabili" è composto a sua volta da un vettore, di 4 cell, così strutturato:
- Numero
- Nome
- Tipo (tempo, tensione, corrente)
- Vettore con tutti i valori
Nel codice c'è una parte finale che plotta i risultati. È possibile riutilizzare il codice modificando la parte iniziale (che istruisce MATLAB sul file da andare a recuperare) e quella finale.
nomeFile = 'Es'; directory = 'C:\Users\Amministratore\Desktop\Articolo\'; estensioneFile = '.raw'; file = fopen([directory '\' nomeFile estensioneFile], 'r'); %Acquisizione dati iniziali. File scandito riga per riga "fino alla fine". %In realtà si uscirà dal while con un break. La lunghezza del paragrafo %delle impostazioni sul file è ignota. while feof(file) == 0 %fgetl acquisisce da file una linea, eliminando l'a-capo alla fine. line = fgetl(file); %isempty resistuisce 0 se l'input è vuoto. %strfind confronta due stringhe, cioè due vettori di char. Fornisce %in output l'indirizzo di INIZIO del matching, se c'è. %Con questo if ci si assicura che il file sia semanticamente corretto. if isempty(strfind(line, 'No. Variables:')) == 0 %str2double converte una stringa in un double. numeroVariabili = str2double(line(15:length(line))); %cell crea un vettore di cell. In questo caso un vettore riga %lungo numeroVariabili. variabili = cell(1, numeroVariabili); end %Con questo if ci si assicura che il file sia semanticamente corretto. if isempty(strfind(line, 'No. Points:')) == 0 numeroPunti = int64(str2double(line(15:length(line)))); end %Quando, scandendo il file riga per riga, si arriva a "Variables:"... if isequal(line, 'Variables:') for c1 = 1 : 1 : numeroVariabili line = fgetl(file); %Viene utilizzato strtok in un loop per separare il numero della %variabile, il suo nome ed il tipo. Questa è la prima implementazione, %sarebbe stato più corretto usare texscan. È stata lasciata con strtok %a fini dimostrativi. %strtok è in un loop perché di volta in volta separa in DUE SOLE PARTI %la stringa che gli viene fornita. remain = line; for c3 = 1 : 1 : 3 [dato, remain] = strtok(remain); if c3 == 1 numVar = str2double(dato); end if c3 == 2 nomeVar = dato; end if c3 == 3 tipoVar = dato; end end %Il vettore di cell variabili viene riempito. Nella quarta cell %di ogni indice viene istanziato un vettore riga, lungo come il numero di %punti della forma d'onda. variabili{c1} = [{numVar} {nomeVar} {tipoVar} {zeros(1, numeroPunti)}]; %Un po' di pulizia. clear dato remain numVar nomeVar tipoVar; end end %Questo if permette di uscire dal while ben prima che venga scandito (inutilmente) %il resto del file. if isequal(line, 'Values:') break end end %Acquisizione dei valori delle variabili if numeroPunti ~= 0 && numeroVariabili ~= 0 for c1 = 1 : 1 : numeroPunti for c2 = 1 : 1 : numeroVariabili %Di fianco al primo dato c'é il numero dell'iterazione if c2 == 1 dati = textscan(file, '%50.50f %50.50f', 1); variabili{1}{4}(1, c1) = dati{2}; else dati = textscan(file, '%50.50f', 1); variabili{c2}{4}(1, c1) = dati{1}; end end end else %Eventuale messaggio di errore msgbox('0 punti o 0 variabili', 'ERRORE'); end %Chiusura del file fclose('all'); %Pulizia delle variabili clear c1 c2 c3 line dati nomeFile estensioneFile file %Vettori rinominati per chiarezza. Il vettore variabili è un vettore di cell, %ogni suo elemento è formato a sua volta da un vettore di 4 cell. Nella quarta %c'è il vettore di valori. tempo = variabili{1}{4}; tensioneR1 = variabili{2}{4}; correnteC1 = variabili{3}{4}; %Grafici figure(1) hold on plot(tempo, tensioneR1); title('Tensione su R1'); xlabel(gca,'Tempo'); ylabel(gca,'Tensione'); set(gca, 'xlim', [min(tempo) max(tempo)]); grid on figure(2) plot(tempo, correnteC1); title('Corrente attraverso C1'); xlabel(gca,'Tempo'); ylabel(gca,'Corrente'); set(gca, 'xlim', [min(tempo) max(tempo)]); grid on
Output
Considerazioni sulla velocità d'esecuzione
Attenzione: il tempo d'esecuzione dello script può essere molto lungo, in funzione del numero di punti della simulazione.
Per eseguire l'esempio dell'articolo il mio PC (i7-2630QM, 2 GHz) ha impiegato 1.067s, plot compresi. I punti erano "soltanto" 1024*3 = 3072.
Con centinaia di migliaia di punti il tempo di esecuzione può salire tranquillamente a 10-15s, salendo a molti minuti con file di testo di 80-85 MB (circa 3 miliardi di punti).