Le due batterie sono state montate nello stesso momento su due dispositivi gemelli che hanno lavorato insieme per tutto il tempo
Improvvisamente uno dei due dispositivi smette di trasmettere ed ovviamente escludo il problema di alimentazione perche' il telecontrollo del secondo dispositivo mostra un livello dell'accumulatore al 70%
Ovviamente dopo un'ora di prove ho preso il tester ed ho verificato che la batteria era vuota (<0.3 V)
Cosa ho imparato:
1) non comprare batterie sottocosto cinesi (vedi scritte sulle batteria nella foto, ovviamente quella funzionante e' a sinistra). Cio' che costa poco spesso dura poco
2) partire a risolvere i problemi dalle cose semplici (ricordo un manuale Ibm di un Desktop anni 90 che iniziava del tipo Il computer non si accende. Avete collegato il cavo della corrente??...non era un suggerimento stupido)
mercoledì 22 ottobre 2014
martedì 21 ottobre 2014
SSH ed XForwading
Normalmente SSH viene usata per l'amministrazione remota a livello di shell
E' possibile instradare anche una connessione criptata del server X mediante SSH
per avviare lato client l'XForwarding e' sufficiente aggiungere lo switch -X
da una macchina Linux e' possibile scrivere
ssh -X luca@xxx.xxx.xxx.xxx
una volta effettuato il login ci si trova in shell senza che apparentemente ci sia stato un effetto dello switch -X. Se pero' si lancia un applicativo X (tipo gedit) si vedra' comparire lato client la finestra di Gedit...da notare bene che questa applicazione sta girando sul server remoto per cui gli eventuali file saranno salvati sul disco fisso remoto
Se invece di un applicativo si vuole interagire con tutto il desktop e' sufficiente digitare
gnome-session
per aprire (per esempio) il desktop di Gnome
Un aspetto curioso e' che quanto descritto funziona anche su Mac OS X a patto di avere installato il pacchetto X11
Quanto descritto e' stato testato, senza modifiche al demone del server ssh, sia su Ubuntu 14.04 che su Debian 7
E' possibile instradare anche una connessione criptata del server X mediante SSH
per avviare lato client l'XForwarding e' sufficiente aggiungere lo switch -X
da una macchina Linux e' possibile scrivere
ssh -X luca@xxx.xxx.xxx.xxx
una volta effettuato il login ci si trova in shell senza che apparentemente ci sia stato un effetto dello switch -X. Se pero' si lancia un applicativo X (tipo gedit) si vedra' comparire lato client la finestra di Gedit...da notare bene che questa applicazione sta girando sul server remoto per cui gli eventuali file saranno salvati sul disco fisso remoto
Se invece di un applicativo si vuole interagire con tutto il desktop e' sufficiente digitare
gnome-session
per aprire (per esempio) il desktop di Gnome
Una sessione X remota su Mac Os X |
Un aspetto curioso e' che quanto descritto funziona anche su Mac OS X a patto di avere installato il pacchetto X11
Gedit in sessione remota su Mac Os X |
|
lis3lv02dq ed Arduino
A seguito del precedente post, ho provato l'accelerometro triassiale LIS3LV02DQ (scheda tecnica)
A differenza del modello ADXL335 questo integrato si collega ad Arduino mediante un bus I2C con i due pin SDA ed SCL rispettivamente ai pin A04 ed A05 di Arduino UNo
Schema in Fritzing (la pedinatura dell'accelerometro risulta differente da quella che ho usato io perche' in questo caso il sensore non e' montato su una basetta)
Come nel caso precedente ci sono un po' di indicazioni contrastanti sul tipo di alimentazione. La scheda tecnica riporta una tensione di Vcc di 3.6 V per cui, per sicurezza, ho alimentato mediante il pin 3V3 di Arduino
Lo sketch per Arduino e' stato copiato da Internet effettuando piccole modifiche (nell'originale erano usate dei metodi della libreria Wire che sono obsoleti)
------------------------------------------------------------------------------------
#include <Wire.h>
#include <Wire.h>
// TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer
//Modified code from http://research.techkwondo.com/blog/julian/279
//Thanks Julian.
// Using the Wire library (created by Nicholas Zambetti)
// http://wiring.org.co/reference/libraries/Wire/index.html
// On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
// These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL) on the Atmega8
// The Wire class handles the TWI transactions, abstracting the nitty-gritty to make
// prototyping easy.
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600);
Wire.beginTransmission(0x1D);
Wire.write(0x20); // CTRL_REG1 (20h)
Wire.write(0x87); // Device on, 40hz, normal mode, all axis's enabled
Wire.endTransmission();
}
void loop()
{
#define i2cID 0x1D
#define outXhigh 0x29
#define outYhigh 0x2B
#define outZhigh 0x2D
#define outXlow 0x28
#define outYlow 0x2A
#define outZlow 0x2C
byte z_val_l, z_val_h, y_val_l, y_val_h, x_val_l, x_val_h;
//----------X Values-----------------------
int x_val;
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.write(outXlow);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
while(Wire.available())
{
x_val_l = Wire.read();
}
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.write(outXhigh);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
x_val_h = Wire.read();
}
//-------------------------------
x_val = x_val_h;
x_val <<= 8;
x_val += x_val_l;
//----------Y Values-----------------------
int y_val;
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.write(outYlow);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
while(Wire.available())
{
y_val_l = Wire.read();
}
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.write(outYhigh);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
y_val_h = Wire.read();
}
//-------------------------------
y_val = y_val_h;
y_val <<= 8;
y_val += y_val_l;
//----------Z Values-----------------------
int z_val;
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.write(outZlow);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
while(Wire.available())
{
z_val_l = Wire.read();
}
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.write(outZhigh);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
z_val_h = Wire.read();
}
//-------------------------------
z_val = z_val_h;
z_val <<= 8;
z_val += z_val_l;
Serial.print(x_val, DEC);
Serial.print(";");
Serial.print(y_val, DEC);
Serial.print(";");
Serial.println(z_val, DEC);
delay(1);
}
In condizioni statiche il sensore sembra essere decisamente stabile
asse X : 27u +/- 0u
asse Y : -11u +/- 0u
asse Z : 1037 +/- 0.4u
il passo di campionamento nel tempo (calcolato usando lo script del post precedente) e' stato di 13.5+/-1.9 ms
Picchiettando sul tavolo (o meglio da sotto il tavolo, dal basso verso l'alto) e lateralmente si osserva la risposta del sensore
lunedì 20 ottobre 2014
ADXL335 su Arduino Due
L'ADXL335 e' un accelerometro triassiale analogico.
Ne ho comprato uno gia' saldato su basetta su Sparkfun ed il suo utilizzo e' piuttosto immediato. Basta dare corrente e leggere i valori di tensione sui tre pin di misura (uno per ogni asse)
Problema: quale tensione?? Sulla scheda tecnica dell'ADXL335 c'e' indicato che deve alimentato a 3.3V mentre su altre fonti viene riportato che sulla schedina di Sparkfun c'e' gia' un regolatore di tensione per cui puo' essere alimentato dai 5V dell'Arduino
Per non rischiare ho alimentato il pin VCC con il pin da 3V dell'Arduino e collegato il GND
Per la prova ho utilizzato solo l'asse Z collegato alla porta A0 (analogica 0 dell'Arduino)
Ho utilizzato una Arduino Due piu' che altro per avere un dato a 12 bit
Lo sketch montato sulla scheda e' quanto mai semplice
------------------------------------------------
void setup() {
Serial.begin(9600);
}
void loop() {
analogReadResolution(12);
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
delay(1);
}
------------------------------------------------
Sul portatile ho messo un piccolo script in Python in modo da salvare oltre al dato anche il tempo (in millisecondi) per vedere quanto era stabile il passo di acquisizione
------------------------------------------------
import serial
import timeser = serial.Serial('/dev/cu.usbmodem621', 9600)
while True:
line = ser.readline()
millis = int(round(time.time() * 1000))
print str(millis)+","+line,
------------------------------------------------
Per avere un'idea della qualita' del dato ho fatto prima una misura cercando di non avere accelerazioni sull'asse verticale
Senza perturbazione |
La misura ha avuto un valore medio di 1670 unita' +/- 2 unita' di standard deviation. Il valore massimo misurato e' stato di 1677 unita' (3 misure) ed un valore minimo di 1661 (1 misura)
Osservando la scala dei tempi, il passo di campionamento e' piuttosto variabile con un valore medio di 6 ms +/- 2 ms
Successivamente ho provato a fare una misura camminando attorno al tavolo dove era appoggiato il sensore.
Camminando attorno al tavolo |
Il valore medio misurato e' stato di 1669 unita' (coerente con quello precedente) con valore massimo di 1679 u e minimo di 1659 u
Sul grafico sono inserite le rette dei valori massimi, minimo e +/- st.dev della misura senza perturbazione.
I dati sono molto grossolani ma c'e' una qualche indicazione che il sensore abbia registrato la variazione di accelerazione verticale indotta dal mio camminare
Giusto per prova ho provato anche con il campionamento a 10 bit sempre su Arduino 2
il valore medio e' stato di 419 unita' con una standard deviation di 0.5 unita' (su 500 misure)
419 unita' a 10 bit su Arduino 2 valgono 2.04 V
1669 unita' a 12 bit su Arduino 2 valgono 2.03 V
In questo caso pero' ho deliberatamente picchiettato sul tavolo (come si vede chiaramente dal grafico, nella figura in basso un ingrandimento). Si vedono chiaramente i rimbalzi del segnale
Cerchero' nei prossimi giorni di fare qualche esperienza di campagna per vedere se l'integrato puo' essere utilizzato come piccolo sismometro
venerdì 17 ottobre 2014
giovedì 16 ottobre 2014
Serial to Ethernet con Arduino
Per risolvere il problema di un amico che deve mandare il segnale di uno strumento di monitoraggio (uscita solo in seriale) su Internet per la misura remota ho provato a costruire un convertitore seriale-ethernet.
Esistono soluzioni commerciali decisamente piu' solide ma anche piu' costose (vedi http://www.moxa.com/product/Serial_Device_Servers.htm) ma cosi' si perde il divertimento
Lo strumento esce con una seriale RS-232 quindi la prima parte e' inserire un MAX 3232 (gia' visto in questo post) con uno shield ethernet su Arduino Uno per trasmettere i dati in Udp
Per semplicita' ho simulato tutto sul portatile (non avendo peraltro a disposizione lo strumento che e' in uso per monitoraggio). Il segnale seriale e' stato simulato con un semplice programma in Python che manda numeri progressivi sulla porta seriale (per ovvi motivi non ho una seriale reale sul portatile ed ho usato un cavo usb-seriale per il collegamento
---------------------------------------------
import serial
ser = serial.Serial('/dev/ttyUSB0',9600)
conta = 0
while True:
ser.write(str(conta))
conta = conta + 1
---------------------------------------------
sulla Arduino e' stato montato questo sketch che semplicemente legge la seriale (sui Pin 0 ed 1 di una Arduino Uno) e crea un pacchetto Udp che viene lanciato ad un server udp remoto
Attenzione: in fase di programmazione mediante cavo Usb il pin 0 deve essere disconnesso dal convertitore MAX 3232 perche' altrimenti si ha un conflitto e lo sketch non viene caricato sull'Arduino. Il collegamento Usb con la IDE Arduino usa il pin 0
il server e' sul 192.168.1.10:5005. L'Arduino era collegata tramite un cavo cross con lo stesso portatile che mandava il segnale seriale
-----------------------------------------------
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 2);
unsigned int localPort = 5005;
int ingresso = 0;
EthernetUDP Udp;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac,ip);
Udp.begin(localPort);
Udp.beginPacket({192, 168, 1, 10}, 5005);
Udp.write("Pronto");
Udp.endPacket();
}
void loop() {
if (Serial.available() > 0)
{
ingresso = Serial.read();
Udp.beginPacket({192, 168, 1, 10}, 5005);
Udp.write(ingresso);
Udp.endPacket();
}
}
-------------------------------------------------
Questo e' il server in Python che gestisce l'arrivo dei dati
-------------------------------------------------
UDP_IP = "192.168.1.10"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024)
print data
-------------------------------------------------
Esistono soluzioni commerciali decisamente piu' solide ma anche piu' costose (vedi http://www.moxa.com/product/Serial_Device_Servers.htm) ma cosi' si perde il divertimento
Lo strumento esce con una seriale RS-232 quindi la prima parte e' inserire un MAX 3232 (gia' visto in questo post) con uno shield ethernet su Arduino Uno per trasmettere i dati in Udp
Per semplicita' ho simulato tutto sul portatile (non avendo peraltro a disposizione lo strumento che e' in uso per monitoraggio). Il segnale seriale e' stato simulato con un semplice programma in Python che manda numeri progressivi sulla porta seriale (per ovvi motivi non ho una seriale reale sul portatile ed ho usato un cavo usb-seriale per il collegamento
---------------------------------------------
import serial
ser = serial.Serial('/dev/ttyUSB0',9600)
conta = 0
while True:
ser.write(str(conta))
conta = conta + 1
---------------------------------------------
sulla Arduino e' stato montato questo sketch che semplicemente legge la seriale (sui Pin 0 ed 1 di una Arduino Uno) e crea un pacchetto Udp che viene lanciato ad un server udp remoto
Attenzione: in fase di programmazione mediante cavo Usb il pin 0 deve essere disconnesso dal convertitore MAX 3232 perche' altrimenti si ha un conflitto e lo sketch non viene caricato sull'Arduino. Il collegamento Usb con la IDE Arduino usa il pin 0
il server e' sul 192.168.1.10:5005. L'Arduino era collegata tramite un cavo cross con lo stesso portatile che mandava il segnale seriale
-----------------------------------------------
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 2);
unsigned int localPort = 5005;
int ingresso = 0;
EthernetUDP Udp;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac,ip);
Udp.begin(localPort);
Udp.beginPacket({192, 168, 1, 10}, 5005);
Udp.write("Pronto");
Udp.endPacket();
}
void loop() {
if (Serial.available() > 0)
{
ingresso = Serial.read();
Udp.beginPacket({192, 168, 1, 10}, 5005);
Udp.write(ingresso);
Udp.endPacket();
}
}
-------------------------------------------------
Questo e' il server in Python che gestisce l'arrivo dei dati
-------------------------------------------------
import socket
UDP_IP = "192.168.1.10"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024)
print data
-------------------------------------------------
Capitolo costi:
una soluzione industriale va circa sui 150 euro
con la soluzione fatta in casa i costi sono qualcosa meno di 20 euro per una Arduino Uno (se si va sui cloni i prezzi calano rapidamente), uno shield ethernet originale va circa a 30 euro ma si trovano moduli anche sui 10 euro, il MAX3232 montato e' circa sui 5 euro
in totale si spende da un minimo di 30 ad un massimo di 55 euro (montaggio e scatola esclusa).
mercoledì 15 ottobre 2014
Script Bash per riavviare un programma
Un problema che si e' posto recentemente e' quello di un programma che gestisce l'acquisione di un sensore si blocca in modo casuale con un messaggio nel log di connection reset by peer
Essendo un software commerciale la consultazione su internet non ha portato risultati e cosi' e'stato provato di scrivere un piccolo programmino in bash da mandare in background che controlla l'attivita' del programma e nel caso lo riavvia
Purtroppo quando il programma entra in errore di fatto non crasha ma rimane attivo in memoria senza fare niente, come in stallo, per cui mediante il comando ps non e' possibile verificare il suo stato di funzionamento
E' stato notato pero' che il file di log si blocca nel momento in cui il programma entra in stallo per cui lo script bash controlla la dimensione del file ad intervalli prefissati, nel caso le dimensioni del file di log non mutino si killa il processo e lo si riavvia
(in giallo le parti da personalizzare)
-----------------------------------------------------------------------------
#!/bin/bash
prima=0 #lunghezza file di log prima
dopo=0 #lunghezza file di log dopo
while true; do #ciclo infinito
dopo=$(stat -c%s "dati.log") #inserire qui il nome del file di log
if (($dopo==$prima)); #se prima e dopo l'intervallo la lunghezza e' uguale
then
echo "Non Cambiato" #effettua il kill del processo e lo riavvia
kill -9 $(pidof nome_programma) #mettere come parametro di pidoff il nome del programma da killare
nome_programma #mettere qui il nome del programma da far ripartire
fi
prima=$dopo #scambia il valore delle variabili per il prossimo ciclo
sleep 30 #intervallo di scansione del file di log
done
Essendo un software commerciale la consultazione su internet non ha portato risultati e cosi' e'stato provato di scrivere un piccolo programmino in bash da mandare in background che controlla l'attivita' del programma e nel caso lo riavvia
Purtroppo quando il programma entra in errore di fatto non crasha ma rimane attivo in memoria senza fare niente, come in stallo, per cui mediante il comando ps non e' possibile verificare il suo stato di funzionamento
E' stato notato pero' che il file di log si blocca nel momento in cui il programma entra in stallo per cui lo script bash controlla la dimensione del file ad intervalli prefissati, nel caso le dimensioni del file di log non mutino si killa il processo e lo si riavvia
(in giallo le parti da personalizzare)
-----------------------------------------------------------------------------
#!/bin/bash
prima=0 #lunghezza file di log prima
dopo=0 #lunghezza file di log dopo
while true; do #ciclo infinito
dopo=$(stat -c%s "dati.log") #inserire qui il nome del file di log
if (($dopo==$prima)); #se prima e dopo l'intervallo la lunghezza e' uguale
then
echo "Non Cambiato" #effettua il kill del processo e lo riavvia
kill -9 $(pidof nome_programma) #mettere come parametro di pidoff il nome del programma da killare
nome_programma #mettere qui il nome del programma da far ripartire
fi
prima=$dopo #scambia il valore delle variabili per il prossimo ciclo
sleep 30 #intervallo di scansione del file di log
done
-----------------------------------------------------------------------------
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...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
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...