Ho ripreso la Intel Edison dal cassetto per un progetto che prevede di salvare dati da un GPS.
La Edison non sara' connessa ad una rete WiFi e quindi non e' possibile ricavare data/ora via NTP
Intel Edison dichiara nelle specifiche di montare un RTC (anche se non c'e' l'alloggiamento della batteria) rispettivamente sul pin 23 del modulo Edison od al pin 5 del J18 del mini breakout
Io in realta' uso il breakout Arduino e si trova solo il connettore J2 con indicazione BATT. Attandoci una LiPO che questa non funziona solo come batteria tampone per RTC ma funziona come un UPS per tutta la scheda (e quindi secondariamente mantiene vivo anche RTC)
In conclusione con il breakout Arduino non ha una connessione diretta con l'RTC, la batteria esterna alimenta tutta la scheda
venerdì 4 gennaio 2019
giovedì 3 gennaio 2019
Salvare dati da seriale in blocchi orari
Una soluzione semplice per un problema: lo scopo e' registrati i dati derivanti in continuo da un GPS via seriale su file di dimensioni in base ad un'ora di acquisizione
Per fare cio' viene in aiuto il comando bash timeout che permette di interrompere dopo un certo numero di secondi un comando di lunga (od infinita esecuzione). Dopo essere passata un'ora viene di nuovo riavviato il comando per creare il nuovo file orario
-----------------------------------------------------------------
#!/bin/sh
while true
do
timeout -s 15 3600 /home/root/gps_data.sh
done
-----------------------------------------------------------------
con il seguente semplice comando si invia tutto il flusso dati dalla seriale su USB verso un file
gps_data.sh
-----------------------------------------------------------------
Per fare cio' viene in aiuto il comando bash timeout che permette di interrompere dopo un certo numero di secondi un comando di lunga (od infinita esecuzione). Dopo essere passata un'ora viene di nuovo riavviato il comando per creare il nuovo file orario
-----------------------------------------------------------------
#!/bin/sh
while true
do
timeout -s 15 3600 /home/root/gps_data.sh
done
-----------------------------------------------------------------
con il seguente semplice comando si invia tutto il flusso dati dalla seriale su USB verso un file
gps_data.sh
-----------------------------------------------------------------
(stty raw; cat> /media/sdcard/`date +%y%m%d%H%M`.txt) < /dev/ttyACM0
-----------------------------------------------------------------
in generale ho visto che il GPS produce circa 150Kb al secondo
mercoledì 2 gennaio 2019
Arduino GPS Datalogger
Ho provato a riconvertire un vecchio progetto in un GPS Datalogger
Lo shield aggiunto presenta un lettore SD Card ed un modulo DS1307 con il GPS collegato su Software Serial
I principali problemi:
1) pur acquisendo a 9600 dalla seriale ho scoperto che la scrittura della SD Card e' piu' lenta ..da questo la necessita' di fare un buffer. La scrittura di un blocco di byte e' molto piu' veloce di aprire il file in append, scrivere il byte, chiudere il file
2) il nome del file di acquisizione (che viene creato sulla base del tempo acquisito dall'RTC del DS1307) deve essere nel formato 8+3 del vecchio MSDOS (nel mio caso ho preferito usare due caratteri per mese, due carattteri per giorni, due caratteri per ora ed infine due caratteri per i minuti di inizio acquisizione)
3) questo semplice script segnala comunque che la memoria dell'Arduino e' ad limite critico
non ho ancora provato la funzione di deep sleep
--------------------------------------------------------------------------------------
// Low Power header
#include "LowPower.h"
// RTC headers
#include <Wire.h>
#include "RTClib.h"
// SD Card headers
#include <SPI.h>
#include <SD.h>
// Seriale dove invia il GPS
#include <SoftwareSerial.h>
RTC_DS1307 rtc;
const unsigned long SECOND = 1000;
const unsigned long HOUR = 3600 * SECOND;
unsigned long contatore = 0;
const unsigned int dim_buffer = 250;
byte SerialData[dim_buffer];
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 10;
char incomingByte = 0; // for incoming serial data
char filen[10];
String filename;
// impostazione della seriale secondaria del GPS
SoftwareSerial mySerial(8, 9); // RX, TX
void setup() {
Serial.begin(9600);
while (!Serial) {
}
// inizializzazione RTC
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// Inizializzazione SD
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
while (1);
}
mySerial.begin(9600);
contatore = 0;
Serial.println("Inizializzazione terminata.");
}
void loop() {
DateTime now = rtc.now();
sprintf(filen, "%02d%02d%02d%02d.txt", now.month(), now.day(), now.hour(), now.minute());
String filename(filen);
delay(2500);
for (int i=0; i <= 100000; i++){
contatore = 0;
while (mySerial.available()) {
SerialData[contatore] = mySerial.read();
contatore++;
}
File dataFile = SD.open(filename, FILE_WRITE);
if (dataFile) {
for (int s=0; s < contatore; s++){
dataFile.print(char(SerialData[s]));
}
dataFile.close();
}
}
Serial.println("Finita acquisizione");
//entra in sleep mode
delay(HOUR);
//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,SPI_OFF, USART0_OFF, TWI_OFF);
}
Lo shield aggiunto presenta un lettore SD Card ed un modulo DS1307 con il GPS collegato su Software Serial
I principali problemi:
1) pur acquisendo a 9600 dalla seriale ho scoperto che la scrittura della SD Card e' piu' lenta ..da questo la necessita' di fare un buffer. La scrittura di un blocco di byte e' molto piu' veloce di aprire il file in append, scrivere il byte, chiudere il file
2) il nome del file di acquisizione (che viene creato sulla base del tempo acquisito dall'RTC del DS1307) deve essere nel formato 8+3 del vecchio MSDOS (nel mio caso ho preferito usare due caratteri per mese, due carattteri per giorni, due caratteri per ora ed infine due caratteri per i minuti di inizio acquisizione)
3) questo semplice script segnala comunque che la memoria dell'Arduino e' ad limite critico
non ho ancora provato la funzione di deep sleep
--------------------------------------------------------------------------------------
// Low Power header
#include "LowPower.h"
// RTC headers
#include <Wire.h>
#include "RTClib.h"
// SD Card headers
#include <SPI.h>
#include <SD.h>
// Seriale dove invia il GPS
#include <SoftwareSerial.h>
RTC_DS1307 rtc;
const unsigned long SECOND = 1000;
const unsigned long HOUR = 3600 * SECOND;
unsigned long contatore = 0;
const unsigned int dim_buffer = 250;
byte SerialData[dim_buffer];
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 10;
char incomingByte = 0; // for incoming serial data
char filen[10];
String filename;
// impostazione della seriale secondaria del GPS
SoftwareSerial mySerial(8, 9); // RX, TX
void setup() {
Serial.begin(9600);
while (!Serial) {
}
// inizializzazione RTC
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// Inizializzazione SD
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
while (1);
}
mySerial.begin(9600);
contatore = 0;
Serial.println("Inizializzazione terminata.");
}
void loop() {
DateTime now = rtc.now();
sprintf(filen, "%02d%02d%02d%02d.txt", now.month(), now.day(), now.hour(), now.minute());
String filename(filen);
delay(2500);
for (int i=0; i <= 100000; i++){
contatore = 0;
while (mySerial.available()) {
SerialData[contatore] = mySerial.read();
contatore++;
}
File dataFile = SD.open(filename, FILE_WRITE);
if (dataFile) {
for (int s=0; s < contatore; s++){
dataFile.print(char(SerialData[s]));
}
dataFile.close();
}
}
Serial.println("Finita acquisizione");
//entra in sleep mode
delay(HOUR);
//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,SPI_OFF, USART0_OFF, TWI_OFF);
}
Moltipicazioni con logaritmi
Un tuffo nel passato del calcolo: moltiplicazioni con i logaritmi.
Una proprieta' dei logaritmi e' che una moltiplicazione di due numeri puo' essere effettuata come somma dei rispettivi logaritmi. Questa proprieta' e' usata nei regoli calcolatori ma si inizia con un esempio da un libro dei logaritmi dove sono tabulati (precalcolati) il valore dei logaritmi
Un esempio : calcolare 44 x 36
Dalle tavole si ricava la mantissa dei due numeri. Si legge che la mantissa di 44 e' pari a 64345 mentre la mantissa di 36 e' 55630. Visto che 44 e 36 sono numeri a due cifre la caratteristica del logaritmo e' pari a 1. (per esempio tra 44,440 e 4400 cambia solo la parte caratteristica mentre la mantissa del logaritmo rimane sempre uguale...ovviamente in base 10)
Per moltiplicare i due numeri si possono sommare quindi 1.64345 e 1.55630 per un risultato di 3.19975.
A questo punto si deve calcolare il numero per il quale il logaritmo e' pari a 19974. Dalle tavole si trova che la mantissa 19976 corrisponde al numero 1584. Dal calcolo della somma il risultato deve essere a 4 cifre (parte caratteristica pari a 3) quindi il risultato e' compreso tra 1000 e 9999
Dalle tavole sembra che il risultato della nostra moltiplicazione sia di poco maggiore di 1584 (tipo 1584.1) ma si tratta di un problema di approssimazione delle tavole. Il risultato della moltiplicazione di due interi e' a sua volta un intero. Quindi il risultato di 44x36=1584
Una proprieta' dei logaritmi e' che una moltiplicazione di due numeri puo' essere effettuata come somma dei rispettivi logaritmi. Questa proprieta' e' usata nei regoli calcolatori ma si inizia con un esempio da un libro dei logaritmi dove sono tabulati (precalcolati) il valore dei logaritmi
Un esempio : calcolare 44 x 36
Dalle tavole si ricava la mantissa dei due numeri. Si legge che la mantissa di 44 e' pari a 64345 mentre la mantissa di 36 e' 55630. Visto che 44 e 36 sono numeri a due cifre la caratteristica del logaritmo e' pari a 1. (per esempio tra 44,440 e 4400 cambia solo la parte caratteristica mentre la mantissa del logaritmo rimane sempre uguale...ovviamente in base 10)
Per moltiplicare i due numeri si possono sommare quindi 1.64345 e 1.55630 per un risultato di 3.19975.
A questo punto si deve calcolare il numero per il quale il logaritmo e' pari a 19974. Dalle tavole si trova che la mantissa 19976 corrisponde al numero 1584. Dal calcolo della somma il risultato deve essere a 4 cifre (parte caratteristica pari a 3) quindi il risultato e' compreso tra 1000 e 9999
Dalle tavole sembra che il risultato della nostra moltiplicazione sia di poco maggiore di 1584 (tipo 1584.1) ma si tratta di un problema di approssimazione delle tavole. Il risultato della moltiplicazione di due interi e' a sua volta un intero. Quindi il risultato di 44x36=1584
Si passa quindi al regolo calcolatore
Usando il cursore si allineano i valori 4.4 su D e 3.6 su CL. Si legge il risultato 1.58x guardando l'indice 1 di C su D
Usando un regolo calcolatore si puo' spostare l'indice 10 della scala C sul valore di 4.4 su D. Con il cursore ci si sposta sul valore 3.6 su C e si legge il risultato 1.58x su D. Dato che in 36x44 le ultime cifre sono 6 e 4 la cifra meno significativa e' 4 (6x4=24) per cui il risultato e' 1.584 ..rimane solo da sistemare la virgola
Lens Flare
Stamani ho provato a fotografare la Luna e Venere molto vicine nella stessa porzione di cielo con un iPhone SE
Questa e' la foto ripresa dalla camera del telefono
Mi sono accorto subito che ci sono troppi punti luminosi (la Luna e Venere sono poco sopra il centro dell'immagine)
Iphone oltre all'immagine registra anche un piccolo video per scegliere la posa migliore
Si vede chiaramente che due punti seguono i movimenti della camera muovendosi intorno al centro dell'immagine. Si tratta dei due riflessi dei lampioni all'interno dell'obbiettivo per un fenomeno conosciuto come lens flare
questa e' l'immagine del cielo senza i lampioni
Questa e' la foto ripresa dalla camera del telefono
Mi sono accorto subito che ci sono troppi punti luminosi (la Luna e Venere sono poco sopra il centro dell'immagine)
Iphone oltre all'immagine registra anche un piccolo video per scegliere la posa migliore
Si vede chiaramente che due punti seguono i movimenti della camera muovendosi intorno al centro dell'immagine. Si tratta dei due riflessi dei lampioni all'interno dell'obbiettivo per un fenomeno conosciuto come lens flare
questa e' l'immagine del cielo senza i lampioni
venerdì 28 dicembre 2018
Scrivere Json File in ElectronJS
Un esempio di come salvare i dati in formato JSon in un progetto ElectronJS
Prima viene creato un nuovo oggetto vuoto e successivamente si inseriscono le coppie chiave-valore per popolare l'oggetto, l'oggetto viene poi convertito in una stringa Json con stringify ed infine la stringa viene salvata sul filesystem
===============================================================
var sinkhole = {};
sinkhole.localita = sessionStorage.getItem("localita");
sinkhole.comune = sessionStorage.getItem("comune");
sinkhole.data = sessionStorage.getItem("data");
sinkhole.ora = sessionStorage.getItem("ora");
sinkhole.compilatore = sessionStorage.getItem("compilatore");
sinkhole.annotazioni = sessionStorage.getItem("annotazioni");
sinkhole.nord = sessionStorage.getItem("nord");
sinkhole.est = sessionStorage.getItem("est");
sinkhole.sistema = sessionStorage.getItem("sistema");
sinkhole.diametro = diametro;
sinkhole.deformazione = deformazione;
sinkhole.pericolo = pericolo;
sinkhole.elemento = elemento;
var esportazione = JSON.stringify(sinkhole);
const fs = require('fs');
var nome_file = sessionStorage.getItem("comune")+"_"+sessionStorage.getItem("ora")+".json";
fs.writeFile(nome_file, esportazione, (err) => {
if(err){
alert("An error ocurred creating the file "+ err.message)
}
else {
alert("File salvato come " + nome_file);
}
});
Prima viene creato un nuovo oggetto vuoto e successivamente si inseriscono le coppie chiave-valore per popolare l'oggetto, l'oggetto viene poi convertito in una stringa Json con stringify ed infine la stringa viene salvata sul filesystem
===============================================================
var sinkhole = {};
sinkhole.localita = sessionStorage.getItem("localita");
sinkhole.comune = sessionStorage.getItem("comune");
sinkhole.data = sessionStorage.getItem("data");
sinkhole.ora = sessionStorage.getItem("ora");
sinkhole.compilatore = sessionStorage.getItem("compilatore");
sinkhole.annotazioni = sessionStorage.getItem("annotazioni");
sinkhole.nord = sessionStorage.getItem("nord");
sinkhole.est = sessionStorage.getItem("est");
sinkhole.sistema = sessionStorage.getItem("sistema");
sinkhole.diametro = diametro;
sinkhole.deformazione = deformazione;
sinkhole.pericolo = pericolo;
sinkhole.elemento = elemento;
var esportazione = JSON.stringify(sinkhole);
const fs = require('fs');
var nome_file = sessionStorage.getItem("comune")+"_"+sessionStorage.getItem("ora")+".json";
fs.writeFile(nome_file, esportazione, (err) => {
if(err){
alert("An error ocurred creating the file "+ err.message)
}
else {
alert("File salvato come " + nome_file);
}
});
giovedì 27 dicembre 2018
DynamoDB con NodeJS
per prima cosa si installa nel progetto AWS SDK per NodeJS con
npm install aws-sdk
si lancia poi DynamoDB in locale come visto qui
npm install aws-sdk
si lancia poi DynamoDB in locale come visto qui
per fare il deploy sui server Amazon del DB si deve decommentare la riga evidenziata in giallo
=========================================================
var AWS = require("aws-sdk");
AWS.config.update({region: "us-west-1",endpoint: "http://localhost:8000"});
// per fare il deploy su DynamoDB sui server Amazon
//AWS.config.update({endpoint: "https://dynamodb.us-west-2.amazonaws.com"});
var dynamodb = new AWS.DynamoDB();
var params = {
TableName : "Informazioni",
KeySchema: [
{ AttributeName: "indice", KeyType: "HASH"}, //Partition key
{ AttributeName: "title", KeyType: "RANGE" } //Sort key
],
AttributeDefinitions: [
{ AttributeName: "indice", AttributeType: "N" },
{ AttributeName: "title", AttributeType: "S" }
],
ProvisionedThroughput: {
ReadCapacityUnits: 10,
WriteCapacityUnits: 10
}
};
dynamodb.createTable(params, function(err, data) {
if (err) {
console.error("Unable to create table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Created table. Table description JSON:", JSON.stringify(data, null, 2));
}
});
//////////// INSERT ////////////////////////
var docClient = new AWS.DynamoDB.DocumentClient();
var table = "Informazioni";
var indice = 2015;
var title = "Il nome della rosa";
var params = {
TableName:table,
Item:{
"indice": indice,
"title": title,
}
};
console.log("Adding a new item...");
docClient.put(params, function(err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});
//////////// QUERY ////////////////////////
var params = {
TableName : table,
KeyConditionExpression: "#yr = :yyyy",
ExpressionAttributeNames:{
"#yr": "indice"
},
ExpressionAttributeValues: {
":yyyy": 2015
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log(" -", item.indice + ": " + item.title);
});
}
});
//////////// DELETE ITEM ////////////////////////
var params = {
TableName:table,
Key:{
"indice": indice,
"title": title
},
ConditionExpression:"indice <= :val",
ExpressionAttributeValues: {
":val": 2016
}
};
console.log("Attempting a conditional delete...");
docClient.delete(params, function(err, data) {
if (err) {
console.error("Unable to delete item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("DeleteItem succeeded:", JSON.stringify(data, null, 2));
}
});
var params = {
TableName : table
};
//////////// DELETE TABLE////////////////////////
dynamodb.deleteTable(params, function(err, data) {
if (err) {
console.error("Unable to delete table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Deleted table. Table description JSON:", JSON.stringify(data, null, 2));
}
});
=========================================================
var AWS = require("aws-sdk");
AWS.config.update({region: "us-west-1",endpoint: "http://localhost:8000"});
// per fare il deploy su DynamoDB sui server Amazon
//AWS.config.update({endpoint: "https://dynamodb.us-west-2.amazonaws.com"});
var dynamodb = new AWS.DynamoDB();
var params = {
TableName : "Informazioni",
KeySchema: [
{ AttributeName: "indice", KeyType: "HASH"}, //Partition key
{ AttributeName: "title", KeyType: "RANGE" } //Sort key
],
AttributeDefinitions: [
{ AttributeName: "indice", AttributeType: "N" },
{ AttributeName: "title", AttributeType: "S" }
],
ProvisionedThroughput: {
ReadCapacityUnits: 10,
WriteCapacityUnits: 10
}
};
dynamodb.createTable(params, function(err, data) {
if (err) {
console.error("Unable to create table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Created table. Table description JSON:", JSON.stringify(data, null, 2));
}
});
//////////// INSERT ////////////////////////
var docClient = new AWS.DynamoDB.DocumentClient();
var table = "Informazioni";
var indice = 2015;
var title = "Il nome della rosa";
var params = {
TableName:table,
Item:{
"indice": indice,
"title": title,
}
};
console.log("Adding a new item...");
docClient.put(params, function(err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});
//////////// QUERY ////////////////////////
var params = {
TableName : table,
KeyConditionExpression: "#yr = :yyyy",
ExpressionAttributeNames:{
"#yr": "indice"
},
ExpressionAttributeValues: {
":yyyy": 2015
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log(" -", item.indice + ": " + item.title);
});
}
});
//////////// DELETE ITEM ////////////////////////
var params = {
TableName:table,
Key:{
"indice": indice,
"title": title
},
ConditionExpression:"indice <= :val",
ExpressionAttributeValues: {
":val": 2016
}
};
console.log("Attempting a conditional delete...");
docClient.delete(params, function(err, data) {
if (err) {
console.error("Unable to delete item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("DeleteItem succeeded:", JSON.stringify(data, null, 2));
}
});
var params = {
TableName : table
};
//////////// DELETE TABLE////////////////////////
dynamodb.deleteTable(params, function(err, data) {
if (err) {
console.error("Unable to delete table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Deleted table. Table description JSON:", JSON.stringify(data, null, 2));
}
});
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...