leggere e visualizzare temperature pc

ciao a tutti,
avevo in testa di leggere le temperature del mio pc tramite arduino, per poi stampare i dati su uno schermo collegato alla scheda.
è fattibile come progetto? avete dei consigli su come impostare lo strech?

in teoria vorrei collegare il pc ad arduino con il cavo usb, e magari far comunicare arduino con lo schermo tramite i pin. posso tenere entrambe le comunicazioni in contemporanea?

Se usi osx o gnu/linux potresti scrivere uno script in python.

Usi python con subprocess per leggere la temperatura. Poi stampi i dati in seriale con pyserial

dr_jekyll:
Se usi osx o gnu/linux potresti scrivere uno script in python.

Usi python con subprocess per leggere la temperatura. Poi stampi i dati in seriale con pyserial

ho capito cosa intendi dire, ma se volessi che funzionasse sia su windows che su linux dovrei scrivere due varianti dello stesso programma (a seconda del so), corretto? non è possibile far funzionare il tutto solo da arduino senza avere in esecuzione alcun programma sul pc (dubito ma chiedo lo stesso)?

Beppos:
... non è possibile far funzionare il tutto solo da arduino senza avere in esecuzione alcun programma sul pc (dubito ma chiedo lo stesso)?

SI, montando un sensore di temperatura dove vuoi misurarla e collegando tale sensore ad Arduino.

Guglielmo

Beppos:
ho capito cosa intendi dire, ma se volessi che funzionasse sia su windows che su linux dovrei scrivere due varianti dello stesso programma (a seconda del so), corretto? non è possibile far funzionare il tutto solo da arduino senza avere in esecuzione alcun programma sul pc (dubito ma chiedo lo stesso)?

Dovresti cambiare la parte che lavora con subprocess. Non uso windows da anni e non conosco il prompt dei comandi ma, penso si possa fare.

Per mettere un sensore aggiuntivo, non penso sia una cosa facile. Ne avresti una precisione maggiore rispetto a quelli che ti da la scheda madre. Sempre se non ti metti a montare il sensore direttamente sulla CPU. Comunque non la vedo come la soluzione più semplice.

gpb01:
SI, montando un sensore di temperatura dove vuoi misurarla e collegando tale sensore ad Arduino.

Guglielmo

Le temperature che vorrei leggere sono quelle di cpu e gpu, non penso sia pratico usare dei sensori esterni. Almeno questo è come la penso io, poi correggetemi se sbaglio in quanto mi sono da poco approcciato al mondo di arduino, quindi non ho la minima esperienza.
Comunque vi ringrazio per gli interventi.
Il prima possibile tenterò di pubblicare qualche abbozzo del codice.

dr_jekyll:
Dovresti cambiare la parte che lavora con subprocess. Non uso windows da anni e non conosco il prompt dei comandi ma, penso si possa fare.

Per mettere un sensore aggiuntivo, non penso sia una cosa facile. Ne avresti una precisione maggiore rispetto a quelli che ti da la scheda madre. Sempre se non ti metti a montare il sensore direttamente sulla CPU. Comunque non la vedo come la soluzione più semplice.

Per quanto riguarda linux potresti darmi dei consigli?

Che conoscenza di python hai? Di linux sei pratico? Conosci sensors?

Ho scritto questo al volo:

import subprocess

proc = subprocess.Popen("sensors", shell=True, stdout = subprocess.PIPE)
output = proc.communicate()[0]
lista = output.split()
print(lista)

che ti da il seguente output:

runfile('/home/pollo/.config/spyder/Macchine/ITG/untitled0.py', wdir='/home/pollo/.config/spyder/Macchine/ITG')
['iwlwifi-virtual-0', 'Adapter:', 'Virtual', 'device', 'temp1:', '+32.0\xc2\xb0C', 'coretemp-isa-0000', 'Adapter:', 'ISA', 'adapter', 'Package', 'id', '0:', '+38.0\xc2\xb0C', '(high', '=', '+100.0\xc2\xb0C,', 'crit', '=', '+100.0\xc2\xb0C)', 'Core', '0:', '+37.0\xc2\xb0C', '(high', '=', '+100.0\xc2\xb0C,', 'crit', '=', '+100.0\xc2\xb0C)', 'Core', '1:', '+36.0\xc2\xb0C', '(high', '=', '+100.0\xc2\xb0C,', 'crit', '=', '+100.0\xc2\xb0C)', 'Core', '2:', '+38.0\xc2\xb0C', '(high', '=', '+100.0\xc2\xb0C,', 'crit', '=', '+100.0\xc2\xb0C)', 'Core', '3:', '+37.0\xc2\xb0C', '(high', '=', '+100.0\xc2\xb0C,', 'crit', '=', '+100.0\xc2\xb0C)', 'pch_skylake-virtual-0', 'Adapter:', 'Virtual', 'device', 'temp1:', '+33.5\xc2\xb0C']

essendo la temperatura che ci interessa la quinta posizione in lista = output.split(), devo stampare solo lista[5]

Quindi il codice diventa:

import subprocess

proc = subprocess.Popen("sensors", shell=True, stdout = subprocess.PIPE)
output = proc.communicate()[0]
lista = output.split()
print(lista[5])

output:

runfile('/home/pollo/.config/spyder/Macchine/ITG/untitled0.py', wdir='/home/pollo/.config/spyder/Macchine/ITG')
+32.0°C

Mo sta a te andarti a vedere come usare pyserial per passare la temperatura ricavata, tramite seriale all'arduino.

Buon lavoro

Un'alternativa all'uso di Python per ottenere quelle e tante altre informazioni HW su un sistema GNU-Linux, è il comando lm-sensors da immettere nella shell. lm-sensors fornisce in output sullo schermo la temperatura delle componenti HW del PC in generale, per cui si deve filtrare l'informazione che interessa mediante il comando grep o altri simili. Come saprai sui sistemi operativi più diffusi, l'output dei comandi può essere reindirizzato dove si vuole con il comando >.
Poi se ti interfacci con Arduino tramite USB, il dato della temperatura - opportunamente elaborato - lo puoi inviare via seriale da PC ad Arduino. Tutto l'insieme di questi comandi infine lo scrivi in un file di script, il classico .sh, e poi lo puoi lanciare automaticamente all'avvio del sistema operativo includendone la chiamata nel file rc.local. Tieni presente che lm-sensors potrebbe non essere preinstallato nel sistema, nel caso lo puoi scaricare con una una semplice apt-get.
Esempio dell'output testuale di lm-sensors:
how-do-i-get-the-cpu-temperature

Paradossalmente su Windows la strada per rilevare le temperature è resa impervia dal fatto che il 100% delle utility è ad interfaccia grafica. Esiste un comando built-in in Windows deputato a ciò (wmic), ma non tutti i PC lo supportano. Cioè se lo invochi e il sistema non lo supporta un messaggio prontamente ti segnala la situazione. Qua trovi maggiori dettagli:
batch-file-get-cpu-temperature
L'alternativa è usare programmi specializzati di terze parti, tipo speedfan, e abilitare la scrittura su file log dei dati che interessano, ed estrapolare questi dati ad intervalli regolari dal file di log utilizzando i comandi integrati (find, findstr) nel prompt dei comandi di Windows, infine inviarli dalla solita seriale ad Arduino. Come nel caso di prima, puoi automatizzare questa serie di operazioni scrivendole in un file .bat ad avvio automatico col sistema operativo.

Esempi, non esaustivi e non provati direttamente da me, dei soli comandi di invio dati dalla seriale di un PC.

Windows:

mode com4: BAUD=9600 PARITY=n DATA=8 STOP=1 to=off dtr=off rts=off
echo ciao > COM4 (invio della stringa ciao via seriale)

nota: l'indirizzo della porta seriale, com4 nell'esempio, la devi sostituire con quello che è assegnato effettivamente ad Arduino, perché nel 99% dei casi è un altro.

Linux

stty -F /dev/ttyS0 speed 9600 cs8 -cstopb -parenb raw
echo 'ciao' > /dev/ttyS0 (invio della stringa ciao via seriale)

nota: vale la stessa nota scritta per Windows, a parte il modo in cui è definito l'indirizzo della porta che in ambiente Linux è determinato da questo percorso /dev/ttySx - dove x è il numero della porta seriale.

Per prima cosa voglio ringraziarvi dei consigli che mi avete dato e poi voglio scusarmi per l'assenza di questi giorni, ma sono un po' occupato con la sessione estiva degli esami.

Tornando al topic, ho provato a buttare giù qualche linea di codice usando il terminale linux:

#!/bin/bash 
cpuTemp=`sensors`
echo ${cpuTemp}
gpuTemp=`nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader`
echo ${gpuTemp}

praticamente utilizzo due le variabili "cpuTemp" e "gpuTemp" per registrare le temperature rispettivamente di cpu e gpu.
Il comando "nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader" mi da come output proprio un numero che rappresenta la temperatura della gpu, il che è proprio quello che voglio.
Per quanto riguarda la cpu invece ricevo come output una stringa con molti valori da cui dovrei filtrare la temperatura. Ora vi chiedo consiglio sul da farsi: mado all'arduino la stringa intera e lascio a lui il compito di filtrarla? oppure prima la filtro e poi mando il dato fatto e finito?

Beppos:
oppure prima la filtro e poi mando il dato fatto e finito?

Direi che questa è la soluzione migliore

Beppos:
Per prima cosa voglio ringraziarvi dei consigli che mi avete dato e poi voglio scusarmi per l'assenza di questi giorni, ma sono un po' occupato con la sessione estiva degli esami.

Tornando al topic, ho provato a buttare giù qualche linea di codice usando il terminale linux:

#!/bin/bash 

cpuTemp=sensors
echo ${cpuTemp}
gpuTemp=nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader
echo ${gpuTemp}




praticamente utilizzo due le variabili "[u]cpuTemp[/u]" e "[u]gpuTemp[/u]" per registrare le temperature rispettivamente di cpu e gpu.
Il comando "[u]nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader[/u]" mi da come output proprio un numero che rappresenta la temperatura della gpu, il che è proprio quello che voglio.
Per quanto riguarda la cpu invece ricevo come output una stringa con molti valori da cui dovrei filtrare la temperatura. Ora vi chiedo consiglio sul da farsi: mado all'arduino la stringa intera e lascio a lui il compito di filtrarla? oppure prima la filtro e poi mando il dato fatto e finito?

Considera che un generico PC è dotato di un processore che raggiunge velocità di clock di svariati Ghz (miliardi di Hertz), mentre un Arduino UNO arriva a 16 Mhz (milioni di Hertz). Ne risulta che un Arduino è molto più lento a processare dati rispetto a un PC. Aggiungici poi il fatto che la trasmissione seriale introduce a sua volta una latenza all'invio del dato, quindi più dati trasmessi = più ritardo a riceverli, e che Arduino deve elaborarlo e ciò comporta anche un uso maggiore della sua SRAM. Direi che la soluzione migliore è di filtrare il dato all'origine di dove viene generato, dunque sì prima filtri e poi invii.

Ho trovato al volo un esempio di filtro al comando che usi per rilevare la temperatura del processore:
sensors | grep '^Core\s[[:digit:]]+:'

fonte: bash - Show just two lines in lm-sensors - Ask Ubuntu

Ok, quindi il codice diventa questo:

#!/bin/bash 
cpuTemp=`sensors | grep '^Physical'| cut -f2 -d"+" | cut -f1 -d"."`
echo ${cpuTemp}
gpuTemp=`nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader`
echo ${gpuTemp}

Rispetto a prima prendo solo la riga con "Physical id 0" che credo misuri la temperatura del processore in generale e non dei singoli core (se sbaglio ditemelo perché non sono molto certo della cosa), poi taglio prima del numero che indica la temperatura e successivamente dopo (non prendo i decimali perché voglio un intero). In fine come output ottengo un numero da due cifre che è proprio quello che voglio.

Ora ho un numero da due cifre sia per la cpu che per la gpu, aggiornerò il codice appena mi arriverà l'adattatore per collegare arduino alla usb sulla mobo.

Adesso se volessi fare la stessa cosa su windows?

@echo off

for /f "delims== tokens=2" %%a in (
    'wmic /namespace:\\root\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature /value'
) do (
    set /a degrees_celsius=%%a / 10 - 273
)

echo %degrees_celsius%

Con questo codice riesco ad ottenere la temperatura della cpu, come faccio per la gpu?
Inoltre per dare il comando ho bisogno dei privilegi da amministratore, come avvio un file .bat con tali privilegi?

p.s. Il codice di windows dovrebbe stampare anche la dicitura "gradi centigradi", lo correggerò al più presto per ottenere solo le due cifre.

Rispetto a prima prendo solo la riga con "Physical id 0" che credo misuri la temperatura del processore in generale e non dei singoli core (se sbaglio ditemelo perché non sono molto certo della cosa)

Cercando su Google non ho trovato conferma unanime di quell'ipotesi, ho però trovato un buon consiglio per verificarla:

It can be different for different hardware combinations. Might be best to look at your BIOS/EFI for it's sensor info (it should be correct), and try comparing those to the output from sensors.

Ovvero su Linux lanci il comando e ti annoti/memorizzi la temperatura che viene dichiarata. Poi riavvii il PC, accedi al BIOS nella sezione dei sensori del PC, infine rilevi se la temperatura del processore è circa la stessa di quella che hai letto poco prima con il comando di Linux.

La definizione esplicita di Physical id 0 l'ho trovata su un forum tedesco, ma non so se è attendibile:

Physical ID 0 is the CPU package temperature

https://forums.gentoo.org/viewtopic-t-973892-start-0.html

Adesso se volessi fare la stessa cosa su windows?

Verifica innanzitutto che il comando "wmic...ecc. ecc.", se lanciato singolarmente da riga di comando, ti fornisca il valore di temperatura corrente. Io se provo ad eseguirlo sul mio PC mi viene restituito il seguente messaggio: ERRORE Descrizione = Non supportato

Quindi anche se da te funzionasse, sappi che non è una soluzione universale. Se cambi PC, quel comando potrebbe lasciarti a piedi.

Con questo codice riesco ad ottenere la temperatura della cpu, come faccio per la gpu?

E qui casca il proverbiale asino, scherzo :D. Da quel che ho letto con wmi non è possibile fare richiesta della temperatura della GPU, dato che non è stato progettato per interrogare i dispositivi di costruttori terzi che implementano la richiesta secondo specifiche proprie.

Inoltre per dare il comando ho bisogno dei privilegi da amministratore, come avvio un file .bat con tali privilegi?

Se vuoi eseguire lo script "a mano" fai tasto destro sopra di esso e scegli l'opzione "esegui come amministratore". Se invece vuoi eseguire lo script con un semplice doppio-click, ma non ti assicuro che la procedura vada a buon fine, fai tasto destro sul file e scegli proprietà, nella finestra che si aprirà clicchi sulla scheda sicurezza ed assegni i vari diritti di "lettura ed esecuzione" con i diritti di ammministratore, dalla volta successiva che fai doppio-click lo script dovrebbe andare in esecuzione senza veti da parte di Windows. Non ti assicuro il risultato perché se Windows interpreta il comando "wmic...ecc. ecc." come una modifica al sistema, non ti permetterà comunque di eseguire lo script che lo contiene se sei un utente normale del sistema.
Diverso è il discorso dell'esecuzione automatica. In questo caso è sufficiente che cerchi la cartella di esecuzione automatica nel menù start, fai tasto destro su di essa, apri e ci incolli il collegamento allo script o brutalmente lo script stesso. Nota che se cerchi la cartella nella barra di ricerca scrivendone il nome non la troverai, devi cercarla manualmente nel menu.

Per aprirla direttamente da esplora risorse di Windows, ti copi quest'indirizzo C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp, lo incolli nella barra degli indirizzi e premi INVIO.

Per rilevare le temperature su Windows, come ti dicevo nel post precedente, puoi usare il palliativo di "pescare" le informazioni dai log che crea SPEEDFAN ogni x secondi.

Altrimenti se vuoi fare una cosa fatta bene, e perché no utile anche per altri, puoi creare tu un'applicazione da riga di comando che trae i dati sulla base di una libreria già fatta implementata nel programma openhardwaremonitor. Più precisamente, la libreria si chiama OpenHardwareMonitorLib.dll
Essa nativamente fornisce delle funzioni (metodi) che, se interrogate da un programma esterno di interfaccia, ti permettono di richiedere i dati di temperatura di CPU/GPU e non solo, ma anche la velocità della ventola del processore, e tante altre caratteristiche del sistema volendo.
Uno spunto di qualcuno che ci ha già fatto qualcosa, lo trovi a questo indirizzo:

Non vi aggrada scrivere un solo programma valido per entrambi i sistemi operativi a meno di particolarizzare solo il metodo con cui si "raccoglie" la temperatura e il modo in cui viene espresso il percorso seriale?

windows windows - Accessing CPU temperature in python - Stack Overflow

dr_jekyll:
Non vi aggrada scrivere un solo programma valido per entrambi i sistemi operativi a meno di particolarizzare solo il metodo con cui si "raccoglie" la temperatura e il modo in cui viene espresso il percorso seriale?

windows windows - Accessing CPU temperature in python - Stack Overflow

A questo punto se l'obiettivo è usare un linguaggio comune fra i due sistemi ed installare meno applicazioni possibile (almeno su Windows), si potrebbe pensare di usare powershell sia su Linux che su Windows. Poi si potrebbe attingere da librerie esterne i dati delle temperature su Windows e invece richiamare i comandi nativi (sensors) su Linux. E' una proposta buttata lì. Non so fino a che punto uno script di powershell, condizionato da opportuni switch che differenziano l'impiego dei due sistemi, sia possibile da realizzare.

Si nota che sono un po' allergico a python? :D.

Beh ti capisco. Ma personalmente sono abbastanza pigro ed invece di reinventare la ruota preferisco appoggiarmi su un linguaggio pieno di librerie, si trova di tutto. Poi power shell su un sistema gnu/linux.... insomma :smiling_imp:

Lo Zen di Python, di Tim Peters

Bello è meglio che brutto.
Esplicito è meglio che implicito.
Semplice è meglio che complesso.
Complesso è meglio che complicato.
Lineare è meglio che nidificato.
Sparso è meglio che denso.
La leggibilità conta.
I casi speciali non sono abbastanza speciali per infrangere le regole.
Anche se la praticità batte la purezza.
Gli errori non dovrebbero mai passare sotto silenzio.
A meno che non vengano esplicitamente messi a tacere.
In caso di ambiguità, rifiuta la tentazione di indovinare.
Ci dovrebbe essere un modo ovvio — e preferibilmente uno solo — di fare le cose.
Anche se questo modo potrebbe non essere ovvio da subito, a meno che non siate olandesi.
Ora è meglio che mai.
Sebbene mai sia spesso meglio che proprio adesso.
Se l’implementazione è difficile da spiegare, l’idea è pessima.
Se l’implementazione è facile da spiegare, l’idea può essere buona.
I namespace sono una grandiosa idea, usiamoli il più possibile!

dr_jekyll:
Beh ti capisco. Ma personalmente sono abbastanza pigro ed invece di reinventare la ruota preferisco appoggiarmi su un linguaggio pieno di librerie, si trova di tutto.

Beh non è proprio reinventare la ruota. Se si utilizzano librerie esterne fatte da altri e comandi di shell si ha comunque riutilizzo di codice e a parte il richiamo degli stessi, cosa che bisognerebbe fare anche in python visto che negli esempi ho letto che su piattaforma Windows ci si deve appoggiare alla solita libreria esterna di openhardwaremonitor, non ci si inventa granché.
La mia puntalizzazione riguarda quest'applicazione specifica, ma in generale è vero che python dispone sicuramente di molte più librerie se confrontato a powershell.

La scimmia di passare a python mi era già passata per la testa (soprattutto per windows).
Per ora il dilemma è questo: dato il seguente codice

#!/bin/bash 
while :  ; do
    cpuTemp=`sensors | grep '^Physical'| cut -f2 -d"+" | cut -f1 -d"."`
    gpuTemp=`nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader`
    echo ${cpuTemp} >/dev/ttyUSB0
    echo ${gpuTemp} >/dev/ttyUSB0
    sleep 1s
done

leggo ed invio due numeri da due cifre l'uno (fisicamente non posso scendere sotto i 20 gradi medi della temperatura ambiente e a 100 la cpu va in stallo). Qualcuno sarebbe così gentile da scrivere uno strech per arduino uno che legga i due numeri e li salvi in due variabili? Il resto dell'implementazione la posso fare anche da solo, ma per la comunicazione seriale sono negato. :slightly_frowning_face:

Beppos:
La scimmia di passare a python mi era già passata per la testa (soprattutto per windows).
Per ora il dilemma è questo: dato il seguente codice

#!/bin/bash 

while :  ; do
    cpuTemp=sensors | grep '^Physical'| cut -f2 -d"+" | cut -f1 -d"."
    gpuTemp=nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader
    echo ${cpuTemp} >/dev/ttyUSB0
    echo ${gpuTemp} >/dev/ttyUSB0
    sleep 1s
done




leggo ed invio due numeri da due cifre l'uno (fisicamente non posso scendere sotto i 20 gradi medi della temperatura ambiente e a 100 la cpu va in stallo). :slightly_frowning_face:

Occhio che nello script manca la definizione della velocità di trasmissione:
stty -F /dev/ttyUSB0 speed 9600 cs8 -cstopb -parenb raw

Qualcuno sarebbe così gentile da scrivere uno strech per arduino uno che legga i due numeri e li salvi in due variabili? Il resto dell'implementazione la posso fare anche da solo, ma per la comunicazione seriale sono negato.

Non è questione di essere negati a fare qualcosa ma di provare a farla di testa propria, ci sono n-mila esempi sparsi sulla rete su come impostare una comunicazione seriale con Arduino e basta veramente poco per adattarli. Se poi ci sono problemi, perché il programma funziona parzialmente, siamo qui per aiutarti e darti delle dritte. In qualche mio precedente post delle ultime settimane, ho già trattato l'argomento della seriale. Prova a darci un'occhiata.

krypton18:
Occhio che nello script manca la definizione della velocità di trasmissione:
stty -F /dev/ttyUSB0 speed 9600 cs8 -cstopb -parenb rawNon è questione di essere negati a fare qualcosa ma di provare a farla di testa propria, ci sono n-mila esempi sparsi sulla rete su come impostare una comunicazione seriale con Arduino e basta veramente poco per adattarli. Se poi ci sono problemi, perché il programma funziona parzialmente, siamo qui per aiutarti e darti delle dritte. In qualche mio precedente post delle ultime settimane, ho già trattato l'argomento della seriale. Prova a darci un'occhiata.

Devo dichiarare la velocità una volta sola corretto? Quindi la metterei come prima riga prima del ciclo while.
Facendo questo ho la certezza che i dati vengano inviati in modo corretto? In questo modo so, che se non leggo i dati il problema è sicuramente nello strech.
precisamente come vengono interpretati i byte inviati da seriale? voglio dire: ipotizziamo di inviare "30", questo è considerato un numero (intero) oppure una stringa?
magari potreste darmi qualche link a del materiale che spieghi bene l'argomento?

grazie per la pazienza e l'aiuto che mi state offrendo :slight_smile: