lunedì 14 gennaio 2019

Arduino Sleep Mode e risveglio con Interrupt da DS3231

Arduino ha diverse modalita' di funzionamento, oltre a quella standard, per ridurre al minimo il consumo di una eventuale batteria. La modalita' sleep mode interna al processore prevede un watchdog che puo' essere settato al massimo ad 8 secondi; per ottenere dei tempi di sleep mode piu' lunghi di deve fornire al microprocessore un segnale dall'esterno che viene gestito come interrupt


Per fornire tale segnale esterno uno dei metodi piu' comodi e' quello di usare un RTC che preveda il canale SQW come il DS3231 (che peraltro risulta essere molto piu' preciso del DS1307)

Il DS3231 funzione su I2C per cui le connessioni sono VCC=3.3 V (attenzione), GND, SDA su A4 Arduino e SCL su A5 Arduino. In piu' si deve collegare SQW sul Pin dell'Arduino per avere segnale di risveglio


Sul DS3231 ci sono due allarmi ma ne sara' usato uno che dopo ogni utilizzo sara' spostato di 60 minuti nel futuro e subito dopo la scheda sara' messa in sleep mode in attesa di essere risvegliata

Il codice del loop riparte dall'ultima istruzione eseguita prima di essere andata in sleep

-------------------------------------------------------------------------------------------------
#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>

#define wakePin 2    
RTC_DS3231 rtc;     
//-------------------------------------------------
void wakeUp()        // here the interrupt is handled after wakeup
{
}
//------------------------------------------------------------

void setup() {
  Serial.begin(9600);
  delay(3000);
  //imposta il PIN D2 per il wqakeup
  pinMode(wakePin, INPUT);;

  Wire.begin();
  rtc.begin();
  rtc.adjust(DateTime(__DATE__, __TIME__));   //imposta l'orologio in fase di compilazione col computer
  
  //elimina allarmi eventualmente presenti
  rtc.armAlarm(1, false);
  rtc.clearAlarm(1);
  rtc.alarmInterrupt(1, false);
  rtc.armAlarm(2, false);
  rtc.clearAlarm(2);
  rtc.alarmInterrupt(2, false);

  rtc.writeSqwPinMode(DS3231_OFF);
  delay(1000);
  Serial.println("Inizio");

}

//------------------------------------------------------------

void loop() {

    DateTime now = rtc.now();
    Serial.print(now.hour(),DEC);
    Serial.print(":");
    Serial.print(now.minute(),DEC);
    Serial.print(":");
    Serial.print(now.second(),DEC);
    Serial.println();
    
   //calcola la prossima ora di risveglio ovvero dopo un'ora
    DateTime nextAlarm = now + TimeSpan(0, 1, 0, 0);
  // l'ordine del timespan e' giorni,ore,minuti,secondi
    
    rtc.setAlarm(ALM1_MATCH_HOURS, nextAlarm.minute(), nextAlarm.hour(), nextAlarm.second());   //imposta l'allarme 
    rtc.alarmInterrupt(1, true);
    delay(3000); // wait for console
    attachInterrupt(0, wakeUp, LOW);          
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);   //entra in sleep su questa istruzione
    detachInterrupt(0);                                    //execution resumes from here after wake-up
    //cancella la precedente impostazione dell'allarme 1
    rtc.armAlarm(1, false);
    rtc.clearAlarm(1);
    rtc.alarmInterrupt(1, false);
    delay(3000);
}


Addipresto Lanza

Era da tempo che volevo aggiungere alla mia collezione di regoli calcoatori una calcolatrice analogica per addizioni ma i prezzi su Ebay non sono trascurabili. Ieri ad un mercatino per 10 euro ho preso questa Addipresto Lanza completa del suo stilo originale perfettamente funzionante (a dire il vero sono strumenti cosi' semplici che e' difficile si rompano)




E' databile indicativamente seconda meta' degli anni 60 ed ha 7 rotori decimali. Non ha indicatore di overflow ma semplicemente il conteggio riparte da zero


Per effettuare una somma, per esempio 65+47 (come nel video sottostante). si procede puntando lo stilo sul numero delle unita' e ruotando verso il basso procedendo poi con il rotore delle decine. Inserito il primo addendo si ripete la procedura per il secondo per avere infine il risultato sul display in alto ovvero 112. Il reset e' effettuato con la levetta rossa



Le sottrazioni possono essere effettuate con i numeri in rosso come complemento a 9

Alcune informazioni sul meccanismo interno si possono ricavare a questo link

mercoledì 9 gennaio 2019

Cordova File Plugin per salvare file

questo esempio e' stato ripreso da questo esempio

si parte da zero

cordova create MyApp
cordova platform add android
cordova plugin add cordova-plugin-file

a questo punto e' stato creato il progetto base. Si apre Android Studio e si risolvono i vari errori di Gradle e poi si fa una prima build. In seguito si modificano i file come segue

Nella pagina html l'unico aspetto importante e' che siano importati cordova.js e /js/index.js

/assets/www/index.html
////////////////////////////////////////////////////////////
<html>
    <head>

        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Hello World</title>
    </head>
    <body onload="onLoad()">
        <div class="app">
            <h1>Apache Cordova</h1>
            <div id="deviceready" class="blink">
                <p class="event listening">Connecting to Device</p>
                <p class="event received">Device is Ready</p>
            </div>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>

    </body>
</html>
////////////////////////////////////////////////////////////

sull'evento deviceready si aggiunge quindi il codice evidenziato

/assets/www/js/index.js
///////////////////////////////////////////////////////////

var app = {
    // Application Constructor
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
    },

    // deviceready Event Handler
    //
    // Bind any cordova events here. Common events are:
    // 'pause', 'resume', etc.
    onDeviceReady: function() {
        this.receivedEvent('deviceready');
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
        var fileName = 'myfile.txt';    // your file name
        var data = '...';               // your data, could be useful JSON.stringify to convert an object to JSON string
        window.resolveLocalFileSystemURL( cordova.file.externalRootDirectory, function( directoryEntry ) {
            directoryEntry.getFile(fileName, { create: true }, function( fileEntry ) {
                fileEntry.createWriter( function( fileWriter ) {
                    fileWriter.onwriteend = function( result ) {
                        console.log( 'pippoplutopaperino' );
                    };
                    fileWriter.onerror = function( error ) {
                        console.log( error );
                    };
                    fileWriter.write( data );
                }, function( error ) { console.log( error ); } );
            }, function( error ) { console.log( error ); } );
        }, function( error ) { console.log( error ); } );
    }
};

app.initialize();

///////////////////////////////////////////////////////////

/res/config.xml
anche in questo file si modifica aggiungendo la parte evidenziata
///////////////////////////////////////////////////////////
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <feature name="Whitelist">
        <param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
        <param name="onload" value="true" />
    </feature>
    <name>HelloCordova</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <allow-intent href="market:*" />
    <preference name="loglevel" value="DEBUG" />
    <feature name="File">
        <param name="android-package" value="org.apache.cordova.file.FileUtils" />
        <param name="onload" value="true" />
    </feature>
    <allow-navigation href="cdvfile:*" />
    <preference name="AndroidPersistentFileLocation" value="Compatibility" />
    <preference name="AndroidExtraFilesystems" value="files,cache, sdcard, cache-external, files-external" />
</widget>
///////////////////////////////////////////////////////////

se tutto e' andata a buon fine si trovera' il file myfile.txt nella cartella Documenti

martedì 8 gennaio 2019

Mandelbrot su Olivetti M10

Per la rubrica Retrocomputing Estremo insieme di Mandelbrot su Olivetti, splendido portatile del 1983 marcato Olivetti ma non prodotto da Olivetti, con un processore 8085 (dove il 5 sta per 5 Volt, non c'e' bisogno della doppia alimentazione 5-12V) a 2.4 MHz

25 minuti di calcolo per una griglia 64x44 con soglia di 20 cicli utilizzando Virtual T, un emulatore per Olivetti M10 e TRS-80
Il codice BASIC e' stato adattato partendo dalla base di Rosetta Code






Perche' ho usato un emulatore....non ho nella mia collezione un Olivetti M10??
Errato serial 40301385 24K perfettamente funzionate




lunedì 7 gennaio 2019

Interagire con DynamoDB con Lambda e API Gateway

Un sistema per interagire con DynamoDB mediante una funzione Lambda triggerata da API Gateway




Prima prima cosa ho creato a mano una tabella in DynamoDB con due colonne nome (stringa) ed indice (numerico)

La funzione Lambda per interagire con DynamoDB necessita di permessi. Per rendere le cose piu' semplici ho usato i permessi piu' estesi che corrispondono al ruolo AmazonDyamoDBFullAccess (per creare il ruolo si va in consolle di AWS, si apre IAM, Ruolo, Crea Ruolo, si selezione il servizio Lambda e si spunta AmazonDyamoDBFullAccess) Dopo aver salvato il ruolo con un nome si modifica il Ruolo di Esecuzione nella finestra della funzione Lambda impostando il nuovo ruolo

La funzione Lambda di seguito mostra un insertItem ed un getItem condizionato al valore dell'indice numerico

================================================
var AWS = require('aws-sdk');
var DOC = require('dynamodb-doc');
var dynamo = new DOC.DynamoDB();

exports.handler = function(event, context) {
  
  var tableName = "bollettini";
var item = {
    nome: "Federico",
    indice: Number(4)
}
var params = {
    TableName: tableName,
    Item: item
};


    dynamo.putItem(params, function (err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else console.log(data);               // successful response
    });
  
  var cb = function(err, data) {
    if(err) {
      console.log('error getItem: ',err);
      context.done('Unable to getItem', null);
    } else {
      if(data.Item && data.Item.nome) {
        context.done(null, data.Item);
      } else {
        context.done(null, {});
      }
    }
  };
  dynamo.getItem({TableName:"bollettini", Key:{indice:2}}, cb);

};
================================================

A questo punto per eseguire la Lambda e' necessario impostare un trigger che nel mio caso e' API Gateway. Dalla consolle di AWS si sceglie API Gateway, si selezione Create API, si indica il nome, Nella pagina successiva si clicca sul menu' a tendina Actions e si sceglie GET. Si apre una pagina sulla destra in si inserisce  l'ARN della Lambda e si salva. A questo punto si pubblica la API e si avra' come risposta un link del tipo https:/xxxxxxxx.execute-api.eu-west-1.amazonaws.com/test/

Puntano il browser al link indicato si mettera' in esecuzione la funzione Lambda

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

Change Detection with structural similarity

L'idea di base e' quella di cercare le differenze tra le due immagini sottostanti Non e' immediatamente visibile ma ci sono dei ...