Mi hanno prestato il DMX Relay Receiver della ThinkerKit
Si tratta di un componente che dovrebbe essere collegato al DMX Master Shield ma la presenza del processore ATMega32U4 lo rende anche indipendente
Prima osservazione: non usatelo su Windows. Richiede i driver e non sono riuscito a trovarli. Usarlo su Linux e' invece una passeggiata
Il sistema viene riconosciuto e programmato come una Arduino Micro anche se di fatto puo' solo pilotare i propri relay
Per permettere la commutazione dei rele' e' necessario utilizzare una alimentazione esterna a 12 V
Per rendere operativa la scheda si usa la libreria DMX (l'identificativo della scheda, modificabile mediante i jumper, e' stato impostato a 3)
---------------------------------
#include <DmxMaster.h>
int ADDRESS = 3;
int led = 13;
void setup() {
DmxMaster.maxChannel(ADDRESS + 3);
pinMode(led, OUTPUT);
Serial.begin(9600);
}
void loop() {
for (int i = ADDRESS; i < ADDRESS + 4; i++) {
digitalWrite(led, HIGH);
DmxMaster.write(i, HIGH);
delay(1000);
Serial.println(i);
DmxMaster.write(i, LOW);
digitalWrite(led, LOW);
}
}
---------------------------------
In conclusione direi che il sistema e' costoso (oltre i 40 euro) e piu' complicato che non usare il semplice metodo presentato in questo post oppure in questo
venerdì 13 dicembre 2013
giovedì 12 dicembre 2013
Gestire l'evento onrelease su pulsante di Android
Sto sviluppando una applicazione che mandi un segnale di allarme in caso di necessita' da parte di un utente.
Per inviare il messaggio e' previsto che l'utente prema un pulsante, grande quanto lo schermo
E' necessario pero' evitare falsi allarmi quindi il pulsante deve essere tenuto premuto per un determinato tempo (diciamo 1 secondo) e quindi non si puo' generare l'evento sull'onclick ma si deve fare in modo di calcolare la differenza di tempo tra l'evento onclick ed onrelease
Di seguito il codice per gestire questo problema
---------------------------------------------------------------
package com.test.onrelease;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.*;
import android.view.View.OnTouchListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button pulsante;
long lastDown;
long lastDuration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pulsante = (Button) findViewById(R.id.button1);
pulsante.setText("Premere il pulsante per almeno 1 secondo");
pulsante.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
lastDown = System.currentTimeMillis();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
lastDuration = System.currentTimeMillis() - lastDown;
if (lastDuration > 1000)
{
pulsante.setBackgroundColor(Color.GREEN);
pulsante.setText("Richiesta accettata. Invio in corso");
}
else
{
pulsante.setBackgroundColor(Color.RED);
pulsante.setText("Premere il pulsante per almeno 1 secondo");
}
}
return false;
}
});
}
Per inviare il messaggio e' previsto che l'utente prema un pulsante, grande quanto lo schermo
E' necessario pero' evitare falsi allarmi quindi il pulsante deve essere tenuto premuto per un determinato tempo (diciamo 1 secondo) e quindi non si puo' generare l'evento sull'onclick ma si deve fare in modo di calcolare la differenza di tempo tra l'evento onclick ed onrelease
Di seguito il codice per gestire questo problema
---------------------------------------------------------------
package com.test.onrelease;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.*;
import android.view.View.OnTouchListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button pulsante;
long lastDown;
long lastDuration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pulsante = (Button) findViewById(R.id.button1);
pulsante.setText("Premere il pulsante per almeno 1 secondo");
pulsante.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
lastDown = System.currentTimeMillis();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
lastDuration = System.currentTimeMillis() - lastDown;
if (lastDuration > 1000)
{
pulsante.setBackgroundColor(Color.GREEN);
pulsante.setText("Richiesta accettata. Invio in corso");
}
else
{
pulsante.setBackgroundColor(Color.RED);
pulsante.setText("Premere il pulsante per almeno 1 secondo");
}
}
return false;
}
});
}
---------------------------------------------------------------
mercoledì 11 dicembre 2013
Debian su IBM A31P
Il modello su cui e' stata provata Debian e' in questo caso un vetusto IBM A31P, il modello base dei portatili IBM della prima meta' degli anni 2000.
Dato il periodo di uscita e la fascia "economica" (sempre che IBM abbia mai fatto qualcosa di economico) si nota il peso oltre i 3 Kg, l'assenza di Wireless (per maggiori dettagli vedere qui), il connettore micro FireWire
A dispetto della batteria completamente priva di capacita' di carica, il portatile si distingue per una risoluzione del monitor di 1600x1200 pixel (un record per l'epoca ed anche per altri portatili piu' recenti)
Da segnalare la presenza di una Ultraport ben nascosta nel lato alto del display
Sulla macchina e' stata montata una Debian Squeeze (l'installazione di questo portatile risale al giugno di due anni fa ma solo in questi giorni mi e' ritornata tra le mani)
Non e' certo una macchina veloce ma la fantastica tastiera IBM fa dimenticare il peso eccessivo
Dato il periodo di uscita e la fascia "economica" (sempre che IBM abbia mai fatto qualcosa di economico) si nota il peso oltre i 3 Kg, l'assenza di Wireless (per maggiori dettagli vedere qui), il connettore micro FireWire
A dispetto della batteria completamente priva di capacita' di carica, il portatile si distingue per una risoluzione del monitor di 1600x1200 pixel (un record per l'epoca ed anche per altri portatili piu' recenti)
Da segnalare la presenza di una Ultraport ben nascosta nel lato alto del display
Sulla macchina e' stata montata una Debian Squeeze (l'installazione di questo portatile risale al giugno di due anni fa ma solo in questi giorni mi e' ritornata tra le mani)
Non e' certo una macchina veloce ma la fantastica tastiera IBM fa dimenticare il peso eccessivo
martedì 10 dicembre 2013
Resettare la password di root su Linux/Debian
Mi e' tornato indietro una macchina su cui avevo lavorato un paio di anni fa e che avevo configurato come Debian Box; nel disco fisso mi ricordavo di aver lasciato la copia di un programma che mi interessa e cosi' lo ho riacceso.
Al login ho dato la mia username e la mia password e sono entrato nella home ma non ho trovato traccia del file. Per cercare su tutto il disco ha cercato di elevarmi a root ma la password non veniva accettata (il calcolatore e' passato per diverse mani e niente di piu' semplice che qualcuno abbia modificato la password di root)
Mi sono trovato nell'imbarazzante posizione di dovermi sproteggermi da me stesso
1) avviare il calcolatore
2) alla finestra di Grub, selezionare Single Mode (senza premere Invio) e digiatare il tasto "e"
si entra quindi in modalita' di Edit della configurazione di Grub
3) trovare la line che inizia per "linux /boot.........." e inserire alla fine init=/bin/bash
in questo modo al prossimo riavvio parte una sessione bach
4) CTRL+X
termina e riavvia. Alla ripartenza ci si trova in bash. Si digitano i seguenti comandi
mount -rw -o remount /
passwd
che in sostanza montano la root del file system in lettura/scrittura e poi si resetta la password di root.
Il lavoro e' finito e si dovrebbe riavviare la macchina. A me i comandi "halt" od "init 0" non hanno funzionato per cui, per essere sicuro che le modifiche fossero andate a buon fine ho prima smontato il file system e poi riavviato mediante il tasto fisico la macchina
All'avvio successivo avevo il pieno controllo del calcolatore
lunedì 9 dicembre 2013
Torrent su Raspberry
Su richiesta di un amico ho provato a creare una torrent machine basata su Raspberry (ovviamente i concetti ed i comandi sono applicabili su qualsiasi Linux Box)
(il sistema e' nato per funzionare headless ovvero senza tastiera, mouse e monitor ma per le fasi di sviluppo ho usato un po' di aiuto)
Ci sono molti tutorial su Internet e questa cerca di essere il riassunto e la via piu' breve per mettere in funzione questa impostazione
Si parte da una installazione pulita di Raspbian (niente Noobs che ruba spazio per nulla sulla SD) su una schedina da almeno 8 Giga in modo da lasciare spazio ai dati (non e' infatti previsto l'utilizzo di un disco esterno)
Si installa quindi transmission-daemon
apt-get install transmission-daemon
si stoppa il servizio
/etc/init.d/transmission-deamon stop
e si edita il file /etc/transmission-deamon/settings.json
(sono evidenziate in giallo le modifiche. In pratica si cambia la username e la password del servizio, la directory dove sono salvati file viene spostata nella dir torrent della home dell'utente pi in modo da semplificare il recupero in sftp e si abilita le connessioni esterne da qualsiasi host)
----------------------------------
{
"alt-speed-down": 50,
"alt-speed-enabled": false,
"alt-speed-time-begin": 540,
"alt-speed-time-day": 127,
"alt-speed-time-enabled": false,
"alt-speed-time-end": 1020,
"alt-speed-up": 50,
"bind-address-ipv4": "0.0.0.0",
"bind-address-ipv6": "::",
"blocklist-enabled": false,
"blocklist-url": "http://www.example.com/blocklist",
"cache-size-mb": 4,
"dht-enabled": true,
"download-dir": "/home/pi/torrent",
"download-limit": 100,
"download-limit-enabled": 0,
"download-queue-enabled": true,
"download-queue-size": 5,
"encryption": 1,
"idle-seeding-limit": 30,
"idle-seeding-limit-enabled": false,
"incomplete-dir": "/home/pi/torrent",
"incomplete-dir-enabled": false,
"lpd-enabled": false,
"max-peers-global": 200,
"message-level": 2,
"peer-congestion-algorithm": "",
"peer-limit-global": 240,
"peer-limit-per-torrent": 60,
"peer-port": 51413,
"peer-port-random-high": 65535,
"peer-port-random-low": 49152,
"peer-port-random-on-start": false,
"peer-socket-tos": "default",
"pex-enabled": true,
"port-forwarding-enabled": false,
"preallocation": 1,
"prefetch-enabled": 1,
"queue-stalled-enabled": true,
"queue-stalled-minutes": 30,
"ratio-limit": 2,
"ratio-limit-enabled": false,
"rename-partial-files": true,
"rpc-authentication-required": true,
"rpc-bind-address": "0.0.0.0",
"rpc-enabled": true,
"rpc-password": "{efaed872245cfe54c92e668423872cf02458117bTl0EeuAR",
"rpc-port": 9091,
"rpc-url": "/transmission/",
"rpc-username": "kappadocio",
"rpc-whitelist": "*.*.*.*",
"rpc-whitelist-enabled": true,
"scrape-paused-torrents-enabled": true,
"script-torrent-done-enabled": false,
"script-torrent-done-filename": "",
"seed-queue-enabled": false,
"seed-queue-size": 10,
"speed-limit-down": 100,
"speed-limit-down-enabled": false,
"speed-limit-up": 100,
"speed-limit-up-enabled": false,
"start-added-torrents": true,
"trash-original-torrent-files": false,
"umask": 18,
"upload-limit": 100,
"upload-limit-enabled": 0,
"upload-slots-per-torrent": 14,
"utp-enabled": true
si riavvia il servizio
/etc/init.d/transmission-deamon start
a questo punto si sono due modi di interagire con il demone
1) via Browser
si puo' comandare lo scaricamento dei torrent indirizzando il browser all'indirizzo del server sulla porta 9091
per esempio
http://192.168.0.101:9091
si effettua il login e si effettua l'upload del file torrent o della url (per esempio del magnetic link)
Mi ero scordato che la directory in uso al demone deve essere scrivibile al servizio, altrimenti si genera questo errore. Basta, da root, un chmod 777 /home/pi/torrent (non ci sono problemi di sicurezza sulla macchina)
Ci sono molti tutorial su Internet e questa cerca di essere il riassunto e la via piu' breve per mettere in funzione questa impostazione
Si parte da una installazione pulita di Raspbian (niente Noobs che ruba spazio per nulla sulla SD) su una schedina da almeno 8 Giga in modo da lasciare spazio ai dati (non e' infatti previsto l'utilizzo di un disco esterno)
Si installa quindi transmission-daemon
apt-get install transmission-daemon
si stoppa il servizio
/etc/init.d/transmission-deamon stop
e si edita il file /etc/transmission-deamon/settings.json
(sono evidenziate in giallo le modifiche. In pratica si cambia la username e la password del servizio, la directory dove sono salvati file viene spostata nella dir torrent della home dell'utente pi in modo da semplificare il recupero in sftp e si abilita le connessioni esterne da qualsiasi host)
----------------------------------
{
"alt-speed-down": 50,
"alt-speed-enabled": false,
"alt-speed-time-begin": 540,
"alt-speed-time-day": 127,
"alt-speed-time-enabled": false,
"alt-speed-time-end": 1020,
"alt-speed-up": 50,
"bind-address-ipv4": "0.0.0.0",
"bind-address-ipv6": "::",
"blocklist-enabled": false,
"blocklist-url": "http://www.example.com/blocklist",
"cache-size-mb": 4,
"dht-enabled": true,
"download-dir": "/home/pi/torrent",
"download-limit": 100,
"download-limit-enabled": 0,
"download-queue-enabled": true,
"download-queue-size": 5,
"encryption": 1,
"idle-seeding-limit": 30,
"idle-seeding-limit-enabled": false,
"incomplete-dir": "/home/pi/torrent",
"incomplete-dir-enabled": false,
"lpd-enabled": false,
"max-peers-global": 200,
"message-level": 2,
"peer-congestion-algorithm": "",
"peer-limit-global": 240,
"peer-limit-per-torrent": 60,
"peer-port": 51413,
"peer-port-random-high": 65535,
"peer-port-random-low": 49152,
"peer-port-random-on-start": false,
"peer-socket-tos": "default",
"pex-enabled": true,
"port-forwarding-enabled": false,
"preallocation": 1,
"prefetch-enabled": 1,
"queue-stalled-enabled": true,
"queue-stalled-minutes": 30,
"ratio-limit": 2,
"ratio-limit-enabled": false,
"rename-partial-files": true,
"rpc-authentication-required": true,
"rpc-bind-address": "0.0.0.0",
"rpc-enabled": true,
"rpc-password": "{efaed872245cfe54c92e668423872cf02458117bTl0EeuAR",
"rpc-port": 9091,
"rpc-url": "/transmission/",
"rpc-username": "kappadocio",
"rpc-whitelist": "*.*.*.*",
"rpc-whitelist-enabled": true,
"scrape-paused-torrents-enabled": true,
"script-torrent-done-enabled": false,
"script-torrent-done-filename": "",
"seed-queue-enabled": false,
"seed-queue-size": 10,
"speed-limit-down": 100,
"speed-limit-down-enabled": false,
"speed-limit-up": 100,
"speed-limit-up-enabled": false,
"start-added-torrents": true,
"trash-original-torrent-files": false,
"umask": 18,
"upload-limit": 100,
"upload-limit-enabled": 0,
"upload-slots-per-torrent": 14,
"utp-enabled": true
}
----------------------------------si riavvia il servizio
/etc/init.d/transmission-deamon start
1) via Browser
si puo' comandare lo scaricamento dei torrent indirizzando il browser all'indirizzo del server sulla porta 9091
per esempio
http://192.168.0.101:9091
si effettua il login e si effettua l'upload del file torrent o della url (per esempio del magnetic link)
Inserire un torrent |
File in download |
Errore se la directory non e' abilitata in scrittura |
1) via Cellulare
Ci sono applicazioni Android che permettono di comandare Transmission via cellulare. La piu' semplice e gratuita e' Remote Transmission, piuttosto banale nell'utilizzo
Impressioni di uso
Il sistema e' semplice e funzionale ma necessita comunque di un po' di amministrazione. Per errore ho tentato il download di un file enorme che ha saturato subito la SD Card. Risultato file system saturato e sistema che non si e' avviato al reboot (ho dovuto ricreare la torrent machine da zero)
L'interazione da telefono e' pessima ed al massimo l'applicazione Android puo' essere utile per monitorare come stanno andando le cose ma non per editare la lista dei download
ps. i file impiegati per il download sono stati cancellati subito dopo la creazione degli screenshot
pss : il case di plastica standard della Raspberry e' veramente orribile, si chiude con difficolta' e non permette il passaggio del flat cable delle GPIO
Ci sono applicazioni Android che permettono di comandare Transmission via cellulare. La piu' semplice e gratuita e' Remote Transmission, piuttosto banale nell'utilizzo
Login al server |
Schermata di download |
Il sistema e' semplice e funzionale ma necessita comunque di un po' di amministrazione. Per errore ho tentato il download di un file enorme che ha saturato subito la SD Card. Risultato file system saturato e sistema che non si e' avviato al reboot (ho dovuto ricreare la torrent machine da zero)
L'interazione da telefono e' pessima ed al massimo l'applicazione Android puo' essere utile per monitorare come stanno andando le cose ma non per editare la lista dei download
ps. i file impiegati per il download sono stati cancellati subito dopo la creazione degli screenshot
pss : il case di plastica standard della Raspberry e' veramente orribile, si chiude con difficolta' e non permette il passaggio del flat cable delle GPIO
venerdì 6 dicembre 2013
Speech To Text in Android
La funzione SpeechToText e' compresa nelle API di Android e permette di parlare al microfono del telefono e ricevere in risposta la stringa di quanto e' stato detto. Possono essere quindi implementati dei comandi vocali associati all'evento ed alla stringa pronunciata
Per provare questo sistema e' stata creata, sulla base una semplice applicazione basata sull'esempio a questo link
L'implementazione e' molto semplice ma ci sono un paio di dettagli non trascurabili
1) Non tutti i telefoni sono abilitati al SpeechToText (per esempio il Samsung Next Turbo GT-5570i non ha questa funzione mentre il Nexus S si'...francamente non riesco a capire il motivo della differenza)
2) La funzione Speech To Text ricalca il modo di lavorare di Siri per Apple. L'elaborazione non avviene in locale ma il file audio viene mandato ai server di Google che lo elaborano e rimandano indietro la stringa del risultato
di seguito il codice
MainActivity.java
---------------------------------------------------------
package com.luca.innocenti.texttospeech;
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.speech.RecognizerIntent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
protected static final int RESULT_SPEECH = 1;
private TextView testo;
private Button pulsante;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testo = (TextView) findViewById(R.id.textView1);
pulsante = (Button) findViewById(R.id.button1);
pulsante.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
try {
startActivityForResult(intent, RESULT_SPEECH);
testo.setText("-------");
} catch (ActivityNotFoundException a) {
Toast t = Toast.makeText(getApplicationContext(),"Speech to Text non disponibile su questo telefono",
Toast.LENGTH_SHORT);
t.show();
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_SPEECH: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
testo.setText(text.get(0));
}
break;
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Per provare questo sistema e' stata creata, sulla base una semplice applicazione basata sull'esempio a questo link
1) Non tutti i telefoni sono abilitati al SpeechToText (per esempio il Samsung Next Turbo GT-5570i non ha questa funzione mentre il Nexus S si'...francamente non riesco a capire il motivo della differenza)
2) La funzione Speech To Text ricalca il modo di lavorare di Siri per Apple. L'elaborazione non avviene in locale ma il file audio viene mandato ai server di Google che lo elaborano e rimandano indietro la stringa del risultato
di seguito il codice
MainActivity.java
---------------------------------------------------------
package com.luca.innocenti.texttospeech;
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.speech.RecognizerIntent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
protected static final int RESULT_SPEECH = 1;
private TextView testo;
private Button pulsante;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testo = (TextView) findViewById(R.id.textView1);
pulsante = (Button) findViewById(R.id.button1);
pulsante.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "it-IT");
try {
startActivityForResult(intent, RESULT_SPEECH);
testo.setText("-------");
} catch (ActivityNotFoundException a) {
Toast t = Toast.makeText(getApplicationContext(),"Speech to Text non disponibile su questo telefono",
Toast.LENGTH_SHORT);
t.show();
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_SPEECH: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
testo.setText(text.get(0));
}
break;
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
---------------------------------------------------------
activity_main.xml
---------------------------------------------------------
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="28dp"
android:text="Push to Talk" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/button1"
android:layout_centerHorizontal="true"
android:layout_marginTop="80dp"
android:text="--------" />
</RelativeLayout>
---------------------------------------------------------
Plotly
update : https://debiaonoldcomputers.blogspot.com/2024/11/update-plotly-dash-csv.html
Vista la pubblicita' di questi ultimi tempi ho voluto provare il servizio di grafici online Plotly come possibile alternativa a Xively
Vi sono API per numerosi linguaggi ma per semplicita' ho preferito usare Python
Prima di iniziare a scrivere il codice si deve importare la libreria Python per Plotly mediante il comando
pip install plotly
una volta autenticati con Plotly (anche mediante account Google o Facebook) si deve reperire la propria chiave entrando in Settings
si seguito lo script di esempio piu' semplice
Sono da modificare la parte in giallo (attenzione che il nome utente non coincide necessariamente con l'utente di Google... nel caso in cui ci si autentica in questo modo)
------------------------------------
import plotly
py = plotly.plotly(username='LucaInnocenti', key='ifntvfcaa9')
x1 = [1,2,3,10]
y1 = [4,5,6,10]
x2 = [1,2,3]
y2 = [2,10,12]
line1 = {"x": x1,"y": y1, "type":"scatter", "name":"Experiment",
"line":{"color":"rgb(3,78,123)", "width":6, "dash":"dot"},
"marker":{"opacity":1.0,"symbol":"square", "size":12,"color":"rgb(54,144,192)",
"line":{"width":3, "color":"darkblue"}}}
line2 = {"x":x2, "y":y2,"type":"scatter","name":"Control",
"line":{"color":"purple", "width":4, "dash":"dashdot"},
"marker":{"opacity":0.9,"symbol":"cross","size":16,"color":"fuchsia",
"line":{"color":"","width":0}}}
py.plot([line1, line2])
------------------------------------
Una volta che si lancia lo script viene generato un nuovo grafico. Non sembra possibile appendere dei dati ad un grafico gia' esistente creato da un altro script, questo pone dei limiti nel creare grafici incrementali con misure ogni tot secondi per esempio da letture di strumenti
In definitiva, per plottare dati da strumentazione considero superiore Xively
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...