venerdì 4 gennaio 2019

Intel Edison: Batteria RTC o UPS

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

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
-----------------------------------------------------------------
(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);

}

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


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


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);
        }
      });

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 
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));
    }
});

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...