Programmazione remota di un multimetro Siglent SCPI da banco usando Python

English version of this post

Per festeggiare il nuovo anno ho deciso che dovevo dotarmi di un multimetro da banco, e dato il mio budget, dopo un po’ di ricerca in rete ho optato per un Siglent SDM3065X.
Ho scelto la versione da 6 1/2 cifre per l’accuratezza molto superiore rispetto ai fratelli minori della stessa linea di prodotto, rispettivamente da 5 1/2 e 4 1/2 cifre. Questo dovrebbe garantirmi, oltre all’accuratezza migliore, anche una altrettanto minor deriva dei parametri di calibrazione nel tempo.

Molte delle caratteristiche, dei pregi e dei difetti dei multimetri da banco SDM3065X/55X/45X sono già stati abbondantemente trattati in svariati video di Youtube. Non intendo quindi fare una review copia della copia della copia di altre, mi limito a dire che finora sono contento della spesa fatta e la rifarei.

Tra i vantaggi noti e pubblicizzati dei multimetri da banco rispetto a quelli portatili, tra cui l’accuratezza, le dimensioni e la luminosità del display, il fatto che sono sempre disponibili sul tuo banco ed essendo alimentati a rete elettrica non hanno mai la batteria scarica, etc etc.. c’è una funzione che viene sì citata ma non sembra andare molto di moda, eppure è molto importante ed utile: la programmazione remota. Forse perché è meno immediata da mostrare e dunque i vari influencer non trovano pratico mostrarla…

La programmazione remota permette di definire sul proprio computer degli algoritmi, o procedure, o sequenze di test, che usano le misure rilevate dagli strumenti collegati e fanno potenzialmente qualunque cosa (tra cui ad esempio la registrazione dei dati per una successiva consultazione e statistiche). Se nel banco di lavoro ci sono anche alimentatori e carichi programmabili da remoto, diventa possibile usarli in modo combinato, aprendo a un mondo di scenari di test automatizzati.

L’SDM3065X, una volta connesso alla LAN via ethernet, espone un servizio SCPI (documentato qui) e utilizzabile da qualunque applicazione client via TCP/IP. L’accesso è possibile anche via USB, ma personalmente lo trovo meno pratico rispetto alla connesione di rete.

Per utilizzare il servizio basta connettersi via TCP all’indirizzo IP esposto dal DMM e iniziare ad inviare comandi e ricevere le letture. Ma ci sono librerie per i vari linguaggi di programmazione che rendono l’accesso molto più facile. La libreria di riferimento per connettersi ad un multimetro digitale è la “NI Visa” della National Instruments; nel mio caso ho potuto evitare di installarla perché ho usato Python e due librerie pyvisa + pyvisa-py, quest’ultima svolge il ruolo di NI Visa ed è di fatto un sostituto open source.

Scrivo questo post perché ci ho messo veramente poco a far funzionare il sistema: sia il collegamento remoto col multimetro, sia il salvataggio dei dati di misurazione in un database SQLite con successiva analisi, e ho pensato che un piccolo tutorial potrebbe aiutare molti ad accedere a questa funzionalità.

Perché e quando usare la programmazione remota?

Chi lo fa per lavoro sa già tutto, per un hobbista la domanda non è banale. Immaginiamo questi esempi:

  1. Abbiamo costruito un alimentatore chiudendo un modulo in una scatola di plastica (magari corredandola di amperometro, voltmetro, ecc) e siamo quasi sicuri che la dissipazione di calore non sarà un problema. Ma prima di consegnarlo al nostro amico che ce l’ha chiesto, dormiremmo meglio la notte se potessimo verificare le nostre ipotesi.
  2. Un alimentatore è difettoso e abbiamo bisogno di tenerlo acceso per molto tempo, facendo misurazioni ripetute, per riprodurre il problema.
  3. Abbiamo appena costruito un circuito amplificatore audio e ci piacerebbe verificare che possa reggere il carico per cui l’abbiamo progettato, con un duty-cycle del 100% (ovvero tenendo il carico sempre collegato alla potenza nominale).
  4. La nostra rete elettrica ha dei cali o dei picchi di tensione e ci piacerebbe sapere cosa succede la notte.

Sono solo dei banali esempi ma in tutti questi casi abbiamo bisogno di fare misure ripetute per un tempo anche molto lungo, in modo affidabile e in nostra assenza, per poi analizzare i risultati e trarre le nostre conclusioni. Capite bene che un multimetro da solo, anche se con il suo bravo display e la sua memoria locale, finisce presto la sua utilità. Il nostro computer invece sarebbe perfetto. Poterlo usare ci dà la possibilità di accedere a questo tipo molto importante di test in cui di fatto misuriamo dei parametri di qualità di un componente/circuito/apparato che stiamo costruendo o riparando.

Esempio di risultati che si possono ottenere

Volevo misurare la stabilità della tensione d’uscita di un mio alimentatore da banco basato su LM317:

Prima ora di logging delle letture:

Fin qui tutto bene, ma se lo guardiamo in un tempo più ampio includendo la notte:

Possiamo quindi dire che abbiamo avuto una deriva nella tensione d’uscita dopo qualche ora. Tale effetto è dovuto a molteplici cause, tra le più rilevanti ci sono sicuramente l’andamento della temperatura ambiente (che impatta non solo sul dispositivo sotto test ma anche, in misura inferiore, sul multimetro!), manopole e potenziometri, parametri dell’integrato LM317, …

Osservando l’entità della deriva la variazione totale di tensione è di circa 6 mV in 12 ore, trascurabile nella gran parte dei casi, ma… sarei stato mai capace di rilevarla e misurarla con facilità senza questa funzione? Comunque ora so che quel mio alimentatore deriva di 12 mV / giorno, un dato che potrebbe servirmi in qualche prossimo lavoro che farò.

Altro esempio:

Variazione di temperatura interna in un alimentatore tra stao ON e OFF, Iout=1A.
Notare che la temperatura Toff= Tambiente

che mostra l’escursione termica tra gli stati OFF e ON in un alimentatore avente Vout=5V e Iout = 1A. Per la misura ho usato una banalissima termocoppia tipo K.

Impostazione dell’ambiente di programmazione

Per dotarvi del mio stesso ambiente di programmazione dovrete installare i seguenti tool:

  • PyCharm CE, una IDE Python molto famosa e completa (forse su Windows bisogna installare prima Python)
  • DB Browser for SQLite, un tool grafico per aprire e lavorare con i file database SQLite
    • include anche dei semplici grafici, tipo quelli che vedete qui sopra
    • Ha l’export verso CSV
    • e molte altre utili funzioni

Il mio ambiente è su Apple M1, Macbook Air. Alcuni dettagli della procedura potrebbero variare leggermente sotto altri OS.

Ora, per prima cosa connettete il vostro multimetro alla rete. Impostate il TCP/IP in modo da aggiungerlo alla vostra LAN. Supponendo che stiate utilizzando DHCP, controllate che gli venga assegnato un indirizzo IP nella sottorete giusta (o nel pannello di controllo del multimetro, o nella pagina dei “DHCP lease” del vostro router). No indirizzo IP -> no collegamento al multimetro, perciò vi consiglio caldamente di smarcare subito questo punto!

Impostazione del progetto in Pycharm

Creiamo ora un nuovo progetto in PyCharm. Dopo averlo aperto, andate sul menu “File-> New Project…”, si aprirà un popup simile a questo:

dove suggerirei di selezionare “New Virtualenv environment” come si vede nella schermata. Questo farà si che le librerie e pacchetti scaricati da questo progetto rimangano locali alla cartella del progetto, rendendo anche un po’ più stabile l’ambiente Python.
Impostare la cartella voluta nel campo Location sopra mostrato. Una volta fatto cliccate sul pulsante “Create” in basso a destra e si dovrebbe aprire il workspace del nuovo progetto.

Il nostro programma Python userà pyvisa (https://pyvisa.readthedocs.io/en/latest/index.html) e pyvisa-py (quest’ultimo rimpiazza NI-Visa che quindi non dovremo preoccuparci di scaricare ed installare).

Per installarle cliccare i selettore “Python Packages” in basso e ricercare pyvisa e successivamente pyvisa-py:

e per ciascuna di esse cliccare il tasto “Install” che compare sul lato destro della pagina descrittiva.

Installare con questa procedura i seguenti pacchetti: pyvisa, pyvisa-py, psutil e zeroconf.

Una volta fatto siete pronti per collegarvi al multimetro.

Connessione remota al multimetro

Innanzitutto provate questo:

import pyvisa

rm = pyvisa.ResourceManager('@py') # '@py' dice a pyvisa di usare pyvisa-py
resources = rm.list_resources()
print(resources)

Dovrebbe produrre un output di questo tipo:

('TCPIP::192.168.1.232::INSTR',)

se si, il nostro multimetro è stato trovato! Nel caso avessimo più di un dispositivo connesso, la tupla visualizzata conterrebbe altrettante stringhe, e sarebbe nella forma (stringa1, stringa2,…stringaN,).

Connettiamoci ora al multimetro e facciamci restituire il suo IDN (ovvero il suo identificativo):

for resource in resources:
    instrument = rm.open_resource(resource) # Connessione al DMM, restituisce un oggetto che lo rappresenta
    instrument_id = instrument.query('*IDN?').strip() 
    print(instrument_id)

Se abbiamo solo un multimetro non abbiamo realmente bisogno di un ciclo for, ma concentriamoci dapprima sul codice ivi contenuto.

Ciascuna resource è una stringa, es. ‘TCPIP::192.168.1.232::INSTR’.

Invocando rm.open_resource(resource) ci stiamo connettendo al multimetro, ottenendo un oggetto che lo rappresenta, e lo salviamo nella variabile instrument.

Invocando instrument.query(‘*IDN?’) stiamo chiedendo al nostro strumento di restituire il suo identificativo IDN.

Il valore stampato da print sarà qualcosa tipo questa se ci stiamo connettendo ad un DMM della Siglent:

Siglent Technologies,SDM3065X,<il seriale del DMM>,3.01.01.10

che è appunto una stringa univoca.

In generale, la LAN potrebbe avere più di uno strumento installato, anche se oggi magari non è così.

Quasi certamente comunque, gli strumenti verrebbero configurati con DHCP e non sarà una buona idea usare la risorsa di rete (es. ‘TCPIP::192.168.1.232::INSTR’) come elemento costante per connettersi. Molto meglio usare l’IDN che è stato creato apposta per questo.

Ecco quindi che il ciclo for mostrato prima inizierà ad avere una sua utilità:

import pyvisa

rm = pyvisa.ResourceManager('@py') # '@py' dice a pyvisa di usare pyvisa-py
resources = rm.list_resources()
multimeter1 = None # qui assegneremo l'oggetto "instrument" relativo al nostro multimetro
for resource in resources:
    instrument = rm.open_resource(resource) # Connessione al DMM, restituisce un oggetto che lo rappresenta
    instrument_id = instrument.query('*IDN?').strip() 
    if instrument_id == 'Siglent Technologies,SDM3065X,<il seriale del DMM>,3.01.01.10':
        print('Using multimeter 1: ' + instrument_id)
        multimeter1 = instrument

# my test code starts here...

infatti ci permette di trovare il nostro DMM mediante il suo ID univoco e assegnarlo alla variabile multimeter1. Il ciclo for diventerà addirittura necessario quando avremo più strumenti e vorremo identificarli con certezza per stabilire quale di questi è il nostro multimetro A e quale è il multimetro B.

Inviare richieste di letture

Chiediamo ora al nostro multimetro di misurare una tensione DC con auto range. basta una singola riga di codice!

voltage_string = multimeter1.query('MEAS:VOLT:DC? AUTO').strip()

e restituirà una stringa tipo questa:

+5.09841574E+00

ed ecco qui la nostra misura di 5V DC! Notare che abbiamo dovuto aggiungere “.strip()” al valore restituito da query() perché questo contiene dei caratteri vuoti (ritorni a capo) alla fine del valore e la cosa potrebbe dare problemi nella successiva elaborazione.

Salvataggio dei dati nel database

Fin qui tutto bene: ci siamo connessi al nostro DMM e abbiamo ottenuto le letture che ci interessavano. Ora dobbiamo salvarle in un database.

Questa parte è stata anch’essa molto facile e si compone di due parti: inizializzazione del database, scrittura di dati nel database.

Sqlite3 è un db su file, molto leggero da utilizzare e usatissimo. Inizializziamo il database con una tabella per salvare le nostre misure:

import sqlite3
dbconn = sqlite3.connect('my_measurements.db')
dbconn.execute('''CREATE TABLE IF NOT EXISTS MEASURES (id INTEGER PRIMARY KEY AUTOINCREMENT, meas_time 
TIMESTAMP NOT NULL, command TEXT NOT NULL, value TEXT NOT NULL)''')
dbconn.commit()

che crea (se non già presente) un file “my_measurements.db” contenente il database, nella cartella del progetto. Nel database verrà creata la tabella “MEASURES”, che conterrà un campo id autoincrementante, un campo timestamp (ovvero data-ora-minuti-secondi) meas_time, e il nostro valore value definito come testo. Tutti i campi sono definiti come not null, quindi saranno obbligatori.

Per salvare le misurazioni nel database, aggiungere infine un codice tipo questo, che continuerà a misurare e salvare i dati fino a che non lo interrompiamo:

import datetime
import time

while True:
    command = 'MEAS:VOLT:DC? AUTO'
    val_string = self.multimeter1.query(command).strip()
    value = float(val_string)
    now = datetime.datetime.now()
    dbconn.execute('INSERT INTO MEASURES (meas_time,command,value) VALUES (?,?,?)',
                   (now, command, value))
    print'Inserted measured value: ' + command + ', ' + str(value))
    dbconn.commit()
    time.sleep(5)

… ed è finito, anche se il tutto è di livello molto “base”!

Per fermare il programma premere il bottone di “stop” quadrato rosso nel pannello “run” di PyCharm oppure cliccare nella voce di menu Run -> Stop ‘main’.

Visualizzare i dati

E’ arrivato finalmente il momento di visualizzare i risultati della nostra sessione, apriamo quindi il programma DB Browser for SQLite.

Clicchiamo su “Apri Database” e selezioniamo il database del nostro progetto. Possiamo fare questo anche mentre il nostro progamma python sta scrivendo i dati. L’importante in questo caso è non modificare il database.

Si aprirà il file sulla visualizzazione “Struttura database”: cliccare ora su “Naviga nei dati” e selezionare la tabella MEASURES. Abbiamo finito! Il pannello sarà tipo questo:

Si può ordinare per campo id in modo discendente, in questo modo possiamo vedere i dati popolarsi cliccando sul pulsante di refresh vicino al selettore di tabella. Il pannello a destra invece permette di fare il grafico dei dati, selezionando meas_time come variabile X e value come variabile Y1:

Grafico dei record selezionati nel pannello di sinistra.

Si possono filtrare i record della tabella MEASURES, nel qual caso il grafico si aggiornerà automaticamente di conseguenza. Si possono salvare i dati su file CSV per poi aprirlo con Excel/Libreoffice e fare ulteriori analisi.

Punti di attenzione / sviluppi futuri

VISA Timeouts

Potrebbe succedervi di avere dei timeout interrogando il multimetro/i. Per fare sì che il programma non si fermi e che invece continui nel suo loop infinito di misurazioni e inserimenti dati, proteggiamo il codice racchiudendolo in una clausola try..except, ad esempio in questo modo:

command = 'MEAS:VOLT:DC? AUTO'
while True:
    try:
        val_string = self.multimeter1.query(command).strip()
        value = float(val_string)
        now = datetime.datetime.now()
        dbconn.execute('INSERT INTO MEASURES (meas_time,command,value) VALUES (?,?,?)',
                       (now, command, value))
        print('Inserito nel database il record ' + command + ', ' + str(value))
        dbconn.commit()
        time.sleep(5)
    except pyvisa.errors.VisaIOError as v_e
        print(v_e)

In caso di errore si avrà evidenza nella console grazie all’istruzione print(v_e) ma il programma continuerà ad interrogare il DMM e salvare dati.

Comandi multiriga

Potreste avere bisogno di mandare comandi multiriga al vostro DMM, o comunque fare interazioni più complesse di un semplice ‘MEAS:VOLT:DC? AUTO’.

La documentazione di programmazione infatti riporta moltissimi casi di comunicazione multiriga per ottenere un dato.

Per farlo, basti notare che l’oggetto instrument non ha solo il metodo query() ma anche write(). Esempio:

command = 'CONF:VOLT:DC ' + scale
multimeter1.write(command)
command = 'SAMP:COUN 1'
multimeter1.write(command)
while True:
    # Più veloce rispetto a 'MEAS' in quanto non riconfiguro niente tra una lettura e l'altra:
    command = 'READ?'
    val_string = multimeter1.query(command).strip()
    value = float(val_string)
    ....

Conclusion

Questo post è un po’ più lungo di quanto avessi voluto ma spero serva ad altri per introdursi nella programmazione di un multimetro digitale compatibile coi comandi di rete SCPI. Spero vi permetta di impostare una sessione di test automatizzata anche se non siete dei professionisti di programmazione, e che possiate ottenere il massimo dal vostro DMM e dai vostri progetti!

Siglent SCPI bench multimeter remote programming using Python

(versione italiana)

Lately I decided it was time to buy my first bench multimeter. Based on my idea of budget and requirements I went for the Siglent SDM3065X.
I decided for the 6 1/2 digits version because of its much higher accuracy compared to the 5 1/2 and 4 1/2 versions (and it should also have a slower calibration drift).

Many of the features, goodies and shortcomings of the SDM3065X/55X/45X have already been shown in youtube reviews. I’m very happy with my new DMM so far.

Among the well known and much advertised advantages of a bench multimeter over a portable one, such as accuracy, display size and brigtness, mains powered and always available, etc etc.. there is one feature in the recent bench DMM’s which is not so much talked about, but in my opinion very important and useful: the remote programming feature.

It allows you to write any algorythm that uses your measures (the most obvious being monitoring and data logging), and if your bench power supplies and electronic loads also allow for remote programming, you’re pretty much in control for implementing highly automated test workflows.

The SDM3065X, once connected to the LAN via ethernet port, will expose a SCPI service (documented here) usable by client applications. It can be accessed via USB too, but I find it less handy than a network connection.

To use it, you simply connect via TCP to the DMM’s IP address and start issuing commands and getting results. But there are libraries that make it much easier. The reference library is National Instrument’s “NI Visa”, in my case I used Python to give it a try (libraries: pyvisa + pyvisa-py).

Since I was able to get up and running much quicker than I expected, I decided to make an article so others may try and approach the automated and long repeated test practice for their own stuff.

Why/when using remote measurement?

Imagine the following example scenarios:

  1. You have built a power supply and decided to enclose it in a plastic box because you think it won’t generate heat for the usage it will serve. But before sending it to your friend who asked you to build it, you’d like to verify your assumptions.
  2. You have a defective power supply and need to leave it on for a long time to be able to catch the glitch.
  3. You have built your new audio amplifier and you’d like to make sure it can handle a certain load with a full 100% duty-cycle.
  4. Your mains voltage is fluctuating a bit too much and would like to verify that.

In all those cases you need to be able to do repeated measures of your variable (temperature, voltage, current, …), in a dependable way and for a potentially very long time (i.e. some days), and review the results at the end of the test session without losing any data. in other words you need a database for storing all the measured data and be able to do your stats on that.

You can easily accomplish this using your computer, improving the quality of your projects when needed, even if you’re a hobbyist maker (like I am) because we all want to do quality stuff when we need it.

Example results preview

I wanted to measure the voltage stability of a LM317 based variable power supply:

First hour of logging:

So far so good, but look at what happened during the night:

We can safely say that we had a drift in the output voltage after a few hours. Such effect is due to several possible causes, including drift in temperature (not only in the device under test, but partly also in your DMM!), knobs & pots, LM317 parameters, …

The overall voltage variation is about 6 mV in 12 hours, negligible in most use cases, but would I have been able to detect and measure it without such a feature? More importantly, now I know that my PSU will drift no more than approx. 12 mV / day, which is something I can take into account form now on in my projects.

Another example:

Temperature variation in a power supply between ON and OFF, Iout=1A.
Note that Toff= Tambient

which shows the temperature excursion between the OFF and ON state in a power supply under test, having Vout=5V and Iout = 1A. Used a cheap K-type thermocouple.

Setting up your environment

To get up and running using my Python setup you’ll need to install the following tools:

  • PyCharm CE, a full featured Python IDE (on Windows you may need to install Python too)
  • DB Browser for SQLite, a graphical tool to browse SQLite database files
    • simple graphics included
    • CSV export and much more

My environment is an Apple M1 Macbook Air. Some details on your procedure may differ a bit from mine.

Now connect your SCPI enabled DMM to your network. Setup its TCP/IP to have it added in your network. Assuming you’re using DHCP, you’ll want to check for its successful IP address assignment (either in the DMM’s settings panel or in your router DHCP leases page). No IP address -> no connection for sure, so have this done as your first step!

Python project setup in PyCharm

Let’s now create a new Python project from PyCharm. Menu “File -> New Project…” will open the following popup:

where I’d suggest you to select “New Virtualenv environment” like you see in the above screenshot. This will keep the downloaded libraries local to the workspace, making your project more easily portable to other computers. It will also stabilize the interpreter and libraries versions for your project so you won’t experience unexpected breaking changes due to libraries updates at system level.
The Location field sets the project’s root folder. Once you’ve chosen your best fitting folder, click the “Create” button (bottom right), that should open your new project workspace.

Our Python program will use pyvisa (https://pyvisa.readthedocs.io/en/latest/index.html) and pyvisa-py (you don’t need to install NI Visa thanks to pyvisa-py, an open source replacement to the NI Visa library).

To install the libraries, just click the “Python Packages” bottom tab and search for pyvisa and pyvisa-py:

and click on the “Install” button that you’ll find on the right side of the descriptive panel.

Make sure you install at least pyvisa, pyvisa-py, psutil and zeroconf.

Once done you’re ready to connect to your instrument.

Connecting to the DMM

First thing first, try this:

import pyvisa

rm = pyvisa.ResourceManager('@py') # '@py' tells pyvisa to use pyvisa-py as backend library
resources = rm.list_resources()
print(resources)

You should see an output like this:

('TCPIP::192.168.1.232::INSTR',)

which means your instrument has been found! If you have more than one, the output tuple will show more entries. Now let’s connect to our instrument and get its IDN which is the identification string:

for resource in resources:
    instrument = rm.open_resource(resource) # this will connect and return an object representing our DMM
    instrument_id = instrument.query('*IDN?').strip() 
    print(instrument_id)

If we have only one instrument we don’t really need a for loop but let’s focus on the rest of the code first.

Each resource is a string, i.e. ‘TCPIP::192.168.1.232::INSTR’.

By calling rm.open_resource(resource) we are connecting to the DMM and getting an object representing it. We assign it to the instrument variable.
By querying ‘*IDN?’ we are asking instrument to return its identification string.

The print output will be something like the following if you’re connecting to a Siglent DMM:

Siglent Technologies,SDM3065X,<my DMM serial>,3.01.01.10

which is a unique string.

In general, your LAN may have more than one instrument, even if not today.

Your instruments are likely be configured via DHCP in order to keep the network configuration easier. Therefore, your resource string ‘TCPIP::192.168.1.232::INSTR’ is subject to change and it’s not a good identifier for your multimeter.

That’s the reason we are keeping the for loop, because we’re adding the following to our code:

import pyvisa

rm = pyvisa.ResourceManager('@py') # '@py' tells pyvisa to use pyvisa-py as backend library
resources = rm.list_resources()
multimeter1 = None # here we'll assign our multimeter instrument
for resource in resources:
    instrument = rm.open_resource(resource) # this will connect and return an object representing our DMM
    instrument_id = instrument.query('*IDN?').strip() 
    if instrument_id == 'Siglent Technologies,SDM3065X,<my DMM serial>,3.01.01.10':
        print('Using multimeter 1: ' + instrument_id)
        multimeter1 = instrument

# my test code starts here...

This allows us to find our DMM by its unique ID and assign it to our variable multimeter1. The for loop will be good for when we’ll add more instruments and we’ll need to decide which is our multimeter A and which is our multimeter B.

Requesting measurements

Let’s now ask our multimeter to read a DC voltage. This is as easy as a single line of code:

voltage_string = multimeter1.query('MEAS:VOLT:DC? AUTO').strip()

which will print something like:

+5.09841574E+00

And there it is! Our expected 5V DC reading! Please note we had to .strip() the string returned by the DMM as it has some trailing blank characters.

Saving our measurements to a database

So far so good: we have connected to our DMM and got values. Now to the data logging feature. Again this can be very easy. Python has a native ability to deal with sqlite3, a very lightweight and widespread file db used by a large number of programs.

Let’s create a database and create our table to store our measurements:

import sqlite3
dbconn = sqlite3.connect('my_measurements.db')
dbconn.execute('''CREATE TABLE IF NOT EXISTS MEASURES (id INTEGER PRIMARY KEY AUTOINCREMENT, meas_time 
TIMESTAMP NOT NULL, command TEXT NOT NULL, value TEXT NOT NULL)''')
dbconn.commit()

which creates (if not already there) a new file “my_measurements.db” containing our database, along with a table named “MEASURES”, containing an auto-increment field id, a timestamp meas_time, and our value, which is stored as text. All the fields are not null, meaning that the database will accept a new row only if all the field values are not empty.

Just add the following snippet to keep logging until you terminate the program:

import datetime
import time

while True:
    command = 'MEAS:VOLT:DC? AUTO'
    val_string = self.multimeter1.query(command).strip()
    value = float(val_string)
    now = datetime.datetime.now()
    dbconn.execute('INSERT INTO MEASURES (meas_time,command,value) VALUES (?,?,?)',
                   (now, command, value))
    print'Inserted measured value: ' + command + ', ' + str(value))
    dbconn.commit()
    time.sleep(5)

… and you’re done, although in a very basic setup!

To stop the program, hit the stop button in PyCharm’s “run” panel or click on the menu “Run -> Stop ‘main'”.

Viewing data

It’s time to open DB Browser for SQLite.

Click the “Open Database” button and select the database file.

It will open up the file and show the database structure. Now click on the “Data navigation” tab and select the MEASURES table and you’re done! You’ll see a panel like this:

You can sort by id descending, and refresh the data view by hitting the refresh button you see near the MEASURES table selector. On the right panel you can view a graph of your data, selecting meas_time as the X variable and value as the Y1 variable:

Graph of the selected records on the left panel.

You can filter the values on the table, the graph will update accordingly. You can also save the data as CSV and work on it using your preferred spreadsheet to add more graphics and functions to your analysis.

Caveats / further developments

VISA Timeouts

You might notice that sometimes you get timeout exceptions querying your instrument. To fix this you need to protect your query invocation in a try..except clause, like this:

command = 'MEAS:VOLT:DC? AUTO'
while True:
    try:
        val_string = self.multimeter1.query(command).strip()
        value = float(val_string)
        now = datetime.datetime.now()
        dbconn.execute('INSERT INTO MEASURES (meas_time,command,value) VALUES (?,?,?)',
                       (now, command, value))
        print'Inserted measured value: ' + command + ', ' + str(value))
        dbconn.commit()
        time.sleep(5)
    except pyvisa.errors.VisaIOError as v_e
        print(v_e)

This will print errors on the python console but won’t stop the program.

You also might want to do more complicated stuff than simply querying ‘MEAS:VOLT:DC? AUTO’.

Multi-statement tasks

The documentation shows multi line settings for many tasks. How to do that?

Your instrument object does not only have the query method, it also has write. Example:

command = 'CONF:VOLT:DC ' + scale
multimeter1.write(command)
command = 'SAMP:COUN 1'
multimeter1.write(command)
while True:
    # Faster than calling 'MEAS':
    command = 'READ?'
    val_string = multimeter1.query(command).strip()
    value = float(val_string)
    ....

Conclusion

This post is a bit longer than I initially wanted, but I hope it will serve for getting started on remote programming a SCPI bench DMM. I hope you’ll be able to setup your long test session and be succsessful in getting the most out of your DMM and your projects!

MoCA: alternativa di “fascia alta” agli adattatori powerline

Per chi vive in una casa relativamente grande ma non molto recente quindi priva di rete ethernet cablata – e anche dello spazio utile per poter passare i cavi nell’impianto, le due opzioni che vanno per la maggiore per estendere la propria rete domestica wireless sono:

  1. Estendere la portata del segnale radio wi-fi mediante rete mesh (o anche i vecchi “range extender”);
  2. Usare degli adattatori powerline per poi connettere ulteriori acess point wi-fi alla rete cablata così ottenuta (alcuni adattatori hanno l’access point incorporato).

Adattatori powerline

L’opzione 2 funziona solitamente meglio rispetto ad una rete mesh puramente wireless ed è più che sufficiente per esigenze generiche ovvero connettersi alla Rete per navigare, utilizzare i social dai propri smartphone/tablet e vedere film on demand sulle varie piattaforme.

Rispetto alle performance che offrirebbe una LAN ethernet da 1 Gbps (ovvero ping di 0.1 ms e troughput di 1000 Mbps full duplex), però, gli adattatori powerline sono ancora abbastanza lontani. Si parla infatti di latenze intorno ai 4-6ms e di banda reale dell’ordine del centinaio di Mbps in condizioni buone/ottimali, a volte anche meno (a casa mia ad esempio siamo sui 45 Mbps negoziati). Questo con adattatori che decantano 600 Mbps e oltre (ma anche 1000 o addirittura 2000Mbps), dotati di connettori gigabit ethernet. Ci sono molte review a riguardo, ad esempio questa che ci introduce all’argomento di questo post.

Gli adattatori powerline, per funzionare, si basano su appositi chipset che contengono un modem, necessario a trasformare la rete di distribuzione elettrica in una linea dati che permetta la comunicazione bidirezionale (o più in generale tra N apparati). Ovviamente la rete elettrica non è progettata per la trasmissione dati a larga banda, anzi è quanto di più lontano ci possa essere anche dal punto di vista realizzativo, quindi non si può certo biasimare questi chipset per non dare le stesse performance di un cavo ethernet, anzi possiamo dire che fanno un piccolo miracolo! Spesso marchi diversi montano lo stesso chipset, questo perché i relativi produttori non sono poi molti.

Adattatori MoCA

Scavando un po’ più a fondo emerge che in realtà oggi esiste almeno un’opzione 3, poco usata in Italia ma ben più comune in USA, ovvero usare il cavo TV (invece della linea 220V) come rete dati.
Lo standard usato per questo tipo di adattatori è chiamato MoCA, letteralmente “Multimedia Over Coax Alliance”, che oggi è alla versione 2.5.

Essendo attestata su un coassiale a 75 ohm con basse perdite di segnale e schermature solitamente adeguate, non dovrebbe stupire che le performance ottenibili siano ben superiori rispetto al powerline, tanto che come troughput saturano facilmente i 1000 Mbps full duplex dell’Ethernet! Addirittura, per connessioni tra più di due punti il coassiale riesce a reggere una banda aggregata ancora maggiore (MoCA 2.5: 2.5 Gbps).

Anche gli adattarori MoCA fanno uso di chipset, uno di questi è il Maxlinear MxL3710. Personalmente sospetto che sia uno dei pochi produttori in circolazione, nel senso che guardando le varie review degli atattatori MoCA noto che le interfacce web di configurazione si assomigliano tutte davvero moltissimo tra loro.

Rispetto alla Ethernet, comunque, le latenze restano comunque ben più alte e si attestano nei dispositivi attuali intorno ai 3 ms, che comunque è generalmente meglio rispetto a molti powerline.

Notare infine che, siccome le frequenze di lavoro vanno dai 1100 ai 1600 MHz, gli splitter presenti nella calata del cavo antenna dovrebbero a rigore avere un’adeguata banda passante. In molti casi essi lavorano fino alla banda satellitare (2500 MHz).

Ethernet vs Powerline e MoCA: Latenza

Vi potreste chiedere come mai una latenza così alta anche nel caso di adattatori MoCA visto che, come troughput, siamo a livelli di eccellenza. La risposta sta nella modulazione e demodulazione che deve essere fatta, ben più complessa rispetto a quella usata per i segnali elettrici Ethernet 1000Mbps. Il segnale viene modulato a frequenze tra i 1100 e i 1600 MHz (sopra la banda TV e sotto quella satellitare), suddiviso fino a 5 canali larghi 100 MHz ciascuno. La modulazione arriva ad essere la OFDM 1024-QAM quindi anche qui possiamo dire che il chipset il suo mezzo miracoletto lo fa. Il prezzo da pagare è un tempo di codifica/decodifica maggiore rispetto ad ethernet, dove la codifica è molto più semplice ed immediata.

Anche nel caso degli adatttori powerline la modulazione è la OFDM, con codifiche che variano a seconda del particolare standard e dei disturbi presenti, fondamentalmente si tratta di QAM (nel caso degli adattatori G.hn si arriva alla 4096-QAM).

Possiamo dunque dedurre che la modulazione OFDM+QAM è tra i principali responsabili per la maggior latenza rispetto allo standard Ethernet, mentre non ci sono dubbi che il troughput sia elevato, essendo la QAM in grado di trasportare molta informazione per simbolo e l’accoppiata OFDM+QAM massimizza la capacità trasmissiva anche in presenza di disturbi o attenuazioni.

Altre differenze da me riscontrate tra Powerline e MoCA

La mia rete di casa è suddivisa in due sezioni: la “primaria” ha switch, NAS, router verso Internet, access point (Mikrotik hAP AC Lite) e adattatore MoCA (prima era Powerline), la seconda -a valle dell’altro adattatore- vede un televisore e l’access point secondario (Mikrotik hAP Lite). Ho abilitato CAPSMan per aggregare la rete wireless dei due Mikrotik.
Dopo avere in uso gli adattatori MoCA da un po’ di tempo ormai (una coppia di Starlink 2525), posso dire che rispetto agli adattatori Powerline che ho avuto (ne ho cambiati parecchi nel tempo, gli ultimi sono degli Zyxel da 600Mbps dichiarati) ci sono alcune sottili differenze, oltre alla banda consistentemente vicina al livello ethernet, che mi fanno propendere per il sistema MoCA nonostante il prezzo sia più alto (attualmente intorno ai 140€ a coppia):

  • Stabilità del collegamento: Powerline è stabile ma ogni tanto -a volte qualche settimana a volte un paio di mesi e con tutti gli adattatori che ho avuto- la connessione si interrompe e ne devo riavviare uno (o a volte entrambi). Me ne accorgo perché i dispositivi collegati all’access point secondario perdono la connettività. Gli adattatori MoCA non sembrano manifestare mai alcun problema di continuità del collegamento.
  • Inoltre, cosa più subdola, con l’addattatore powerline alcuni dispositivi connessi via wi-fi all’access point secondario, come la mia stampante, poco tempo dopo l’entrata in risparmio energetico risultavano inaccessibili. Per poter stampare mi toccava spesso spegnerla e riaccenderla. Da quando sono passato a MoCA questo problema è scomparso, il che mi fa pensare a qualche limitazione a livello di L2 bridging che ora non c’è più, ma è difficile dirlo con certezza.
  • Calore: sicuramente dipenderà dalla marca e dal modello ma gli adattatori MoCA non scaldano affatto, i powerline invece diventano ben caldi al tatto, quindi sicuramente consumano anche di più.

Tabella riassuntiva

Le mie esperienze con i due tipi di adattatori sono così riassumibili:

Gigabit EthernetMoCAPowerline
Latenza [ms]0,12-33-6
Troughput reale [Mbps]10001000 su porta ethernet
(2500 su coax)
50~300
StabilitàRiferimentoOttimaMolto buona
Generazione di radiodisturbiNoNo (segnali confinati nel coassiale)Moderata e accettabile (ma non inesistente, per via di come è cablata la rete elettrica)
Tabella riassuntiva delle caratteristiche tipiche per tipologia di connesione

Conclusioni

Mi è sembrato utile condividere le esperienze che ho avuto a casa mia con vari tipi di adattatore che nel tempo ho testato. Questo articolo non vuol essere un paragone del tipo “questo è meglio di quello” nè tanto meno “questo va male a prescindere, quello invece va bene”.

Piuttosto, vorrebbe offrire una serie di considerazioni utili per farsi un’idea più chiara di cosa si può ragionevolmente pretendere da un certo tipo di adattatore.

Penso non ci sia dubbio che l’ideale, potendolo fare, sarà sempre passare un bel cavo Ethernet (es. Cat.5E o Cat.6) e connettere così le varie sezioni della rete domestica.

Non potendolo fare ci sono vari compromessi accessibili, con prezzi molto diversi tra loro e caratteristiche pure diverse. Per me che sono un radioamatore minimizzare i disturbi radio è molto importante e dunque preferisco passare i segnali all’interno di cavi schermati (il coassiale TV in questo caso) invece che nella rete elettrica.