venerdì 9 dicembre 2016

Particle Electron

Qualche tempo fa avevo provato la Particle Photon, adesso e' il turno di Particle Electron

La principale differenza e' che Photon e' basata su una comunicazione WiFi mentre Electron utilizza una connessione GSM mediante una SIM


L'altro aspetto interessante e' che la Electron puo' essere alimentata da una batteria LiPo e sulla scheda c'e' anche l'elettronica per ricaricare la batteria sia dal connettore Vin che da USB


Electron Pinout
Per la programmazione si puo' utilizzare la modalita' cloud ma qualunque errore puo' essere pagato con la perdita con la connessione del dispositivo. La cosa piu' semplice e' programmare Electron via USB.

Per prima cosa si deve scaricare particle-cli via npm

npm install -g particle-cli
e poi ci si connette al cloud

particle cloud login

(nonostante si usi particle-cli e' necessaria comunque la connessione di rete perche' la compilazione avviene sempre sul cloud di particle)

a questo punto mediante la Ide Web di Particle si crea il programma. 
Attenzione: se si hanno piu' dispositivi si deve cliccare sulla colonna di destra al menu devices e selezionare quella che si vuole utilizzare


Il dispositivo predefinito e' quello con il simbolo delle stella. Si deve anche annotare il Device ID (servira' in seguito)

A questo punto si deve scaricare dal cloud il programma compilato. Si clicca quindi sulla colonna di destra il menu Code (con il simbolo <>) e si clicca la nuvola vicino al nome del programma 


Si scarica quindi un file denominato firmware.bin
Per effettuare l'upload si deve prima impostare la Electron in listening mode (luce blu pulsante, si deve premere per tre secondi il pulsante MODE sulla scheda) e poi si digita  il comando 

particle flash --serial firmware.bin




le variabili possono essere lette tramite cloud tramite la sintassi

https://api.particle.io/v1/devices/ID_DEVICE/nome_variabile?access_token=ACCESS_TOKEN

(sostituire le parti in giallo con i corretti valori)



La scheda viene venduta con una SIM preinstallata con un traffico a pacchetti prepagato. Si puo' comunque utilizzare qualsiasi scheda SIM dotata di traffico dati (questa operazione puo' risultare piu' conveniente rispetto al contratto fornito da Particle) basta impostare nel programma in giusto APN con la sintassi. Nell'esempio sottostante una configurazione per TIM

---------------------------------------------------------
#include "cellular_hal.h"
STARTUP(cellular_credentials_set("ibox.tim.it", "", "", NULL));
---------------------------------------------------------

particolare attenzione deve essere posta al colore del LED sulla scheda perche' e' da questo che si evidenzia se si ha la connessione di rete o meno


Un altro aspetto molto comodo di Electron e' quello di poter monitorare lo stato di carica della batteria LiPo mediante il comando

-----------------------------------
FuelGauge fuel;
double batteria = 0.0;

batteria = static_castz<double>(fuel.getSoC()); //attenzione che SoC e' scritto con la o centrale minuscola
-----------------------------------

L'utilizzo del cavo seriale permette anche di poter visualizzare i dati inviati lungo la seriale
In modo del tutto analogo di Arduino si puo' scrivere nel codice
-----------------------------------
void setup(){
    Serial.begin(9600);
    Serial.println("Luca");
}
-----------------------------------

le informazioni possono essere visualizzati in qualsiasi programma di monitor seriale.

Un altro bonus, soprattutto per il risparmio della batteria, e' la possibilita' di spengere ed accendere via software la componente radio

------------------------------------
Cellular.on(); 
delay(1000);
Cellular.connect();

While Cellular.ready()
      {

      }
delay(1000);
Cellular.off();
------------------------------------

un esempio di un programma funzionante con la lettura della porta analogica A0 e la trasmissione dei dati della porta e la carica della LiPo
------------------------------------
#include "cellular_hal.h"
STARTUP(cellular_credentials_set("ibox.tim.it", "", "", NULL));

double lettura = 0.0;
double mm = 0.0;
double batteria = 0.0;

int analogPin0 = A0;

FuelGauge fuel;

void setup(){
    Particle.variable("lettura", &lettura, DOUBLE);
    Particle.variable("mm", &mm, DOUBLE);
    Particle.variable("batteria", &batteria, DOUBLE);
    Serial.begin(9600);
}

void loop(){
    lettura = analogRead(analogPin0);
    mm = (lettura/4096)*50;
    batteria = static_castz<double>(fuel.getSoC())

    Particle.publish("lettura", "lettura");
    Particle.publish("mm", "mm");
    Particle.publish("batteria","batteria");
    
    Serial.println(batteria);
    delay(1000);
    
}

TimeOut Error
Attenzione : utilizzando una scheda SIM differente da quella fornita da Particle si puo' riscontrare il seguente errore dopo pochi minuti di uso della scheda e dello sketch sopra riportato


per ovviare a questo problema il programma sopra riportato deve essere modificato con una funzione di keep alive

-----------------------------------------------------
#include "cellular_hal.h"
STARTUP(cellular_credentials_set("ibox.tim.it", "", "", NULL));

double lettura = 0.0;
double mm = 0.0;
double batteria = 0.0;

int analogPin0 = A0;

long previousMillis = 0;
long interval = 40000;

FuelGauge fuel;

void setup(){
    Particle.variable("lettura", &lettura, DOUBLE);
    Particle.variable("mm", &mm, DOUBLE);
    Particle.variable("batteria", &batteria, DOUBLE);
}

void loop(){

    keep_alive();
    
}

void keep_alive()
{
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
        {
            previousMillis = currentMillis;
            if (Particle.connected())
                {
                        lettura = analogRead(analogPin0);
                        mm = (lettura/4096)*50;
                        batteria = static_cast<double>(fuel.getSoC());

                        Particle.publish("lettura", "lettura");
                        Particle.publish("mm", "mm");
                        Particle.publish("batteria","batteria");
                }
        }
}

-----------------------------------------------------

Consumi 



 da un breve test fatto con una batteria LiPo da 2000 mAh si ha un consumo del 5% di batteria circa ogni 90 minuti


lunedì 5 dicembre 2016

Batteria cinese per Moto E

Tempo fa avevo sostituito la batteria su un Moto E a causa della perdita' di funzionalita' di quella originale.
Avevo comprato il sostituto su un e-commerce cinese.


A meno di un anno di distanza la batteria e' morta e stavolta ne ho comprata una originale su Amazon
Come si vede dalla foto le differenze sono evidenti anche dall'esterno ad un costo simile tra la sostituzione originale e quella cinese

In conclusione...non conviene comprare alcune cose su e-commerce cinese

Lupi sul M.Falterona

Non e' certo una novita' che sul M.Falterona abitino i lupi.... ma fa sempre una certa sensazione quando trovi le loro tracce mentre te ne vai a giro da solo nel bosco

Fatta di Lupo vicino alla Sorgente dell'Arno
Risalendo il sentiero 18 ho trovato anche questa mandibola



Quasi certamente si tratta di un canide..non saprei dire se si tratta di un lupo (cucciolo viste le dimensioni)


Altre foto dell'area.
Nella prima massi derivanti dalla frana del 1335


Loc.Gorga Nera. Le storie raccontano che il lago si e' formato a seguito della frana del 1335

Gorga Nera



Balze alle Rondinaie

venerdì 2 dicembre 2016

Sostituzione batteria Nexus 5

Sostituzione della batteria di un Nexus 5.
Per prima cosa e' necessario rimuovere la cover posteriore. Attenzione: non si tratta solo di un solo un pezzo di plastica ma c'e' elettronica sul retro. E' quindi necessario rimuoverla con calma

Si svitano quindi 6 viti per rimuovere la copertura della parte superiore


Si sgancia quindi il cavo flat colore oro che attraversa la batteria sul lato sinistro (basta alzare con delicatezza il connettore in alto indica dalla lettera T). Si piega quindi a 90°§ per liberare la batteria


Si sgancia, sempre con una leggera pressione verso l'alto il connettore della batteria. La batteria e' incollata allo chassis per cui bisogna fare un po' di leva per sollevarla


Si ripete il tutto all'incontrario per rimontare il tutto. Difficolta' da 1 a 3 direi 1 (bastano 10 minuti ed un po' di manualita')



Notifiche cloud con Firebase su IOS

Nel precedente post era stato mostrato come inviare notifiche push a client Android tramite il cloud di Firebase. Si puo' fare la stessa cosa anche con IOS ma e' un inferno  e rimando al video linkato



dopo aver creato un progetto generico per prima cosa si devono aggiungere le librerie via Firebase
inizializzando Cocoapod

pod init

poi si edita il Podfile
----------------------------------
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'Notifica' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!


  # Pods for Notifica

  target 'NotificaTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'NotificaUITests' do
    inherit! :search_paths
    # Pods for testing
  end

pod 'Firebase'
pod 'Firebase/Messaging'
end
----------------------------------
poi si installano le librerie

pod install

e si apre il progetto

open Notifica.xcworkspace

per attivare le notifiche e' sufficiente modificare AppDelegate.m (in giallo sono selezionate le righe di interesse)

AppDelegate.m
-----------------------------------
//
//  AppDelegate.m
//  Notifica
//
//  Created by Luca Innocenti on 30/11/16.
//  Copyright © 2016 Luca Innocenti. All rights reserved.
//

#import "AppDelegate.h"
@import Firebase;
@import FirebaseMessaging;


@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [FIRApp configure];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshCallback:) name: kFIRInstanceIDTokenRefreshNotification object:nil];
    
    UIUserNotificationType allNotificationTypes = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [application registerUserNotificationSettings:settings];
    [application registerForRemoteNotifications];
    
     return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    
    [[FIRMessaging messaging]disconnect];
    
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    [self connectToFirebase];

}


- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
    NSLog(@"%@",userInfo);
}

- (void)tokenRefreshCallback:(NSNotification *)notification{
    NSString *refreshToken = [[FIRInstanceID instanceID] token];
    NSLog(@"Instance ID Token: %@",refreshToken);
    [self connectToFirebase];
}

- (void)connectToFirebase{
    [[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error){
        if (error != nil) {
            NSLog(@"Unable to connect to FCM %@",error);
        }else {
            NSLog(@"Connesso");
        }
        
    }];
}


@end
-----------------------------------

Si devono poi modificare le Capabilities del progetto attivando le Push Notification e Keyring Sharing


il problema principale e' quello di creare un certificato di autenticazione, aspetto che non e' presente sulla versione Android. La procedura e' spiegata nel dettaglio nel video e non e' esattamente banale

Un avvertimento: non e' possibile usare l'emulatore software di IOS, e' necessario utilizzare un dispositivo fisico







giovedì 1 dicembre 2016

Notifiche cloud con Firebase su Android

In questo post viene descritto come usare il cloud di Firebase per mandare notifiche push su dispositivi Android.

Per prima cosa ci si deve registrare, anche con account gratuito, sulla console di firebase e si crea un progetto



si crea quindi una nuova applicazione. E' possibile creare applicazione per Android ed IOS. In questo caso si sceglie Android


per creare l'applicazione e' richiesto il solo nome del pacchetto Android


a questo punto si clicca sul pulsante con i tre puntini sovrapposti e si visualizza la configurazione SDK



e si scarica il file google-services.json che dovra' essere copiato nella directory /app del proprio progetto

si crea quindi un progetto Android usando il nome del pacchetto gia' fornito nella configurazione di Firebase


build.gradle (Project)
-------------------------------------

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'        
        classpath 'com.google.gms:google-services:3.0.0'
        // NOTE: Do not place your application dependencies here; they belong        // in the individual module build.gradle files    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
-------------------------------------

build.gradle (Module: App)
-------------------------------------
apply plugin: 'com.android.application'
android {
    compileSdkVersion 23    
    buildToolsVersion "23.0.3"    
    defaultConfig {
        applicationId "com.lucainnocenti.notifica.notifica"        
        minSdkVersion 21        
        targetSdkVersion 23        
        versionCode 1        
        versionName "1.0"        
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    }
    buildTypes {
        release {
            minifyEnabled false            
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }
    }
}

dependencies {
    compile 'com.google.firebase:firebase-messaging:10.0.0'    
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'    })
    compile 'com.android.support:appcompat-v7:23.4.0'    
   testCompile 'junit:junit:4.12'}

apply plugin: 'com.google.gms.google-services'
-------------------------------------



AndroidManifest.xml
-------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.lucainnocenti.notifica.notifica">

    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <service        android:name=".MyFirebaseMessagingService" android:exported="false">
        <inter-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </inter-filter>
    </service>

    <service        android:name=".MyFirebaseInstanceIdService" android:exported="false">
        <inter-filter>
            <action android:name="com.google.firebase.MESSAGING_ID_EVENT" />
        </inter-filter>
    </service>
</manifest>
-------------------------------------



MyFirebaseMessagingService.java
-------------------------------------
package com.lucainnocenti.notifica.notifica;

import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceIdService;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

/** * Created by root on 29/11/16. */
public class MyFirebaseMessagingService extends FirebaseMessagingService{
    private static final String TAG="MyFMService";

    @Override    public void onMessageReceived(RemoteMessage remoteMessage)
    {
        Log.d(TAG,"ID :"+remoteMessage.getMessageId());
        Log.d(TAG,"Notification :" +remoteMessage.getNotification());
        Log.d(TAG,"Data : "+remoteMessage.getData());

    }
}
-------------------------------------

MyFirebaseInstanceIdService.java
-------------------------------------
package com.lucainnocenti.notifica.notifica;

import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
import com.google.firebase.messaging.FirebaseMessaging;

/** * Created by root on 29/11/16. */
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
    private static final String TAG="MyFirebaseIIDService";
    private static final String FRIENDLY_ENGAGE_TOPIC = "friendly_engange";



    @Override    public void onTokenRefresh(){
    String token = FirebaseInstanceId.getInstance().getToken();
    Log.d(TAG,"Token " + token);
        FirebaseMessaging.getInstance().subscribeToTopic(FRIENDLY_ENGAGE_TOPIC);
    }

}
-------------------------------------

Una volta compilata ed installata l'applicazione si crea un messagggio dall'interfaccia web della Firebase Console dal menu Notification
Si possono creare diverse regole. La cosa piu' semplice e' mandare il messaggio a tutti gli utenti che hanno installato l'applicazione impostando il solo identificativo del pacchetto (altrimenti per creare dei messaggi personalizzati bisogna conoscere gli identificativi unici dei vari client)


Non e' possibile avere un QoS .. in pratica si sa se il messaggio e' stato inviato dal server ma non quanti sono stati consegnati regolarmente

Per inviare messaggi non e' strettamente necessaria l'interfaccia Web. Si puo' utilizzare anche il comando curl da riga di comando

Per prima cosa si clicca sull'icona dell'ingranaggio vicino al nome del progetto e si selezionano le impostazioni del progetto, si seleziona Cloud Messaging e si copia la Server Key (nel futuro si dovra' usare il token ovvero il codice sottostante)


e si lancia poi il seguente comando inserendo la
---------------------------------------
curl --insecure --header "Authorization: key=XXXXXXXXXXXX" --header "Content-Type:application/json" -d "{\"notification\":{\"title\":\"note-Title\",\"body\":\"note-Body\"}}" https://fcm.googleapis.com/fcm/send
---------------------------------------



Arduino 101 a Foligno

In occasione del recente sisma a Norcia il mio ente ha richiesto ai geologi di un servizio volontario di protezione civile presso le aree colpite dal sisma. Con l'occasione volevo provare a vedere se l'accelerometro integrato in Arduino 101 era in grado di registrare i movimenti del terreno. Il luogo di pernottamento era presso Foligno dove e' presente anche una stazione sismica che pubblica i dati su Internet ed era quindi la posizione ideale per la calibrazione


visto il rumore dell'accelerometro, la minima accelerazione valida registrata era superiore a 0.03g (maggiore del 3% dell'accelerazione di gravita')

lo sketch impiegato e' stato semplicemente quello degli esempi della IMu di Curie

--------------------------------
#include "CurieIMU.h"

void setup() {
  Serial.begin(9600); // initialize Serial communication
  while (!Serial);    // wait for the serial port to open

  // initialize device
  Serial.println("Initializing IMU device...");
  CurieIMU.begin();

  // Set the accelerometer range to 2G
  CurieIMU.setAccelerometerRange(2);
}

void loop() {
  float ax, ay, az;   //scaled accelerometer values

  // read accelerometer measurements from device, scaled to the configured range
  CurieIMU.readAccelerometerScaled(ax, ay, az);

  // display tab-separated accelerometer x/y/z values
  Serial.print("a:\t");
  Serial.print(ax);
  Serial.print("\t");
  Serial.print(ay);
  Serial.print("\t");
  Serial.print(az);
  Serial.println();
}

/*
   Copyright (c) 2016 Intel Corporation.  All rights reserved.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*/

--------------------------------
dato che Arduino non ha un Real Time Clock ho usato uno script Python per aggiungere il timestamp ai dati di accelerazione
sisma.py
---------------------------
#!/usr/bin/env python
import time
import datetime
import serial

port = serial.Serial("/dev/ttyACM0", baudrate=9600, timeout=3.0)

base_datetime=datetime.datetime(1970,1,1)

while True:
    millis=int(round(time.time()*1000))
    delta = datetime.timedelta(0,0,0,millis)
    target_date=base_datetime+delta
    print target_date,
    print "\t",
    rcv = port.readline()
    print rcv[:-2]
---------------------------
con poi uno script bash per lanciare il tutto

---------------------------
#!/bin/bash
nome=$(date '+%F--%T').log
/home/luca/sisma.py > /home/luca/$nome
---------------------------

il sistema ha lavorato per oltre 48 ore ma, nonostante la stazione sismica avesse registrato diversi eventi (tutti di modesta entita' sicuramente sotto al 4°§) , i dati della Arduino non mostravano niente di significativo


Dati registrati da Arduino


Esempio dati sismografo Foligno Monte Pale http://www.iesn.it/index.php/eventi-iesn/umbria/foligno-pg.html
La spiegazione e' venuta da questo grafico empirico che correla la magnitudine con l'accelerazione (in cm/sec2). Come si vede per avere una accelerazione di almeno 0.03g (29 cm/sec2) sono necessari sismi di almeno il 5° Richter

http://www.ingegneri.info/forum/viewtopic.php?f=2&t=44944







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