venerdì 3 gennaio 2014

Esperimenti con telefonia mobile ed Android

Per continuare gli esperimenti di questo post, ho creato una piccola applicazione (assolutamente non ottimizzata) che registra in continuita' la posizione GPS ed i dati di telefonia. I dati vengono registrati su in file testo per la successiva elaborazione




I dati registrati sono coerenti ed ho provato ad incrociare il segnale con la distanza dalle antenne ripresa dai database che sono disponibili su Internet (non e' dato sapere quale sia il grado di attendibilita' della posizione GPS dell'antenna)


Mettendo in grafico un po' di distanze dall'antenna contro il segnale misurato si ha una notevole dispersione dei punti

Per adesso il sistema e' stato provato solo in ambito urbano con una notevole densita' di antenne e di disturbi.Il suo uso reale sara' in aree lontane dall'ambiente urbano e sono previste prove nei prossimi giorni


Manifest
-------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.onrelease"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
    
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     

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

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

</manifest>
-------------------------------------------------
Layout
-------------------------------------------------
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Invia" />

    <TextView
        android:id="@+id/lat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button1"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="15dp"
        android:gravity="center_horizontal"
        android:text="TextView" />

    <TextView
        android:id="@+id/p1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/button1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="18dp"
        android:gravity="center_horizontal"
        android:text="TextView" />

    <TextView
        android:id="@+id/p2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/p1"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:text="TextView" />

    <TextView
        android:id="@+id/segnale"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/p2"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:text="TextView" />

    <TextView
        android:id="@+id/gpsfix"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/lat"
        android:layout_alignLeft="@+id/button1"
        android:layout_marginBottom="14dp"
        android:gravity="center_horizontal"
        android:text="TextView" />

    <TextView
        android:id="@+id/last_pos"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/gpsfix"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="18dp"
        android:gravity="center_horizontal" />

    <TextView
        android:id="@+id/tipo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/segnale"
        android:layout_centerHorizontal="true"
        android:text="TextView" />

</RelativeLayout>

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


Main
--------------------------------------------------
package com.test.onrelease;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Date;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.telephony.CellLocation;
import android.telephony.NeighboringCellInfo;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.*;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.location.LocationListener;

public class MainActivity extends Activity {

private Button pulsante;
//gestione dei tempi di pressione del pulsante
long lastDown;
long lastDuration;
//gestione del GPS
private double latitudine;
private double longitudine;
private double last_lat;
private double last_long;

private String tempo_gps;
private long old_time; //tempo ultima acquisizione
private long last_time;
    private boolean gps_fix; //true se si ha il fix del GPS

private LocationManager mlocManager;
private MyLocationListener mlocListener;
private TextView gpsfix;
private TextView posizione;
private String nr_phone;
    private int signalStrengthValue;

private int cid;
private int lac;
private int mcc;
private int mnc;
private int rssi;
private TextView ph1;
private TextView ph2;
private TextView segnale;
private TelephonyManager mTelephonyMgr;
private String networkOperator;
private GsmCellLocation cellLocation;
private TextView last_pos;
private TextView type;
private TextView vicini;
private WakeLock wl;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
gps_fix = false;
last_time = 0;
mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);

        // se il GPS non e' abilitato richiede l'intervento dell'utente
        if (!mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
        }

        //prende il numero di telefono se disponibile
        //TelephonyManager mTelephonyMgr;
        mTelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        // richiede le informazioni di cella
        networkOperator = mTelephonyMgr.getNetworkOperator();
        cellLocation = (GsmCellLocation) mTelephonyMgr.getCellLocation();
        //il numero di telefono non e' codificato nella SIM
        nr_phone = mTelephonyMgr.getLine1Number();
        cid = cellLocation.getCid();
        lac = cellLocation.getLac();
        if (networkOperator != null) {
            mcc = Integer.parseInt(networkOperator.substring(0, 3));
            mnc = Integer.parseInt(networkOperator.substring(3));
        }
        
        
        //definisce il tipo di connessione (UTMS/HDSPA/GPRS
        int tipo = mTelephonyMgr.getNetworkType();

        
        type = (TextView)findViewById(R.id.tipo);
        
        switch (tipo)
        {
        case 7:
            type.setText("1xRTT");
            break;
        case 4:
            type.setText("CDMA");
            break;      
        case 2:
        type.setText("EDGE");
            break;  
        case 14:
        type.setText("eHRPD");
            break;      
        case 5:
        type.setText("EVDO rev. 0");
            break;  
        case 6:
        type.setText("EVDO rev. A");
            break;  
        case 12:
        type.setText("EVDO rev. B");
            break;  
        case 1:
        type.setText("GPRS/GSM");
            break;      
        case 8:
        type.setText("HSDPA");
            break;      
        case 10:
        type.setText("HSPA");
            break;          
        case 15:
        type.setText("HSPA+");
            break;          
        case 9:
        type.setText("HSUPA");
            break;          
        case 11:
        type.setText("iDen");
            break;
        case 13:
        type.setText("LTE");
            break;
        case 3:
        type.setText("UMTS");
            break;          
        case 0:
        type.setText("Unknown");
            break;
        }
        
        
        //la ricerca delle celle vicine sembra funzionare solo in 2G
        List<NeighboringCellInfo> NeighboringList = mTelephonyMgr.getNeighboringCellInfo();
        String stringNeighboring = "Neighboring List- Lac : Cid : RSSI\n";
        for(int i=0; i < NeighboringList.size(); i++){
         
        String dBm;
        int rssi = NeighboringList.get(i).getRssi();
        if(rssi == NeighboringCellInfo.UNKNOWN_RSSI){
        dBm = "Unknown RSSI";
        }else{
        dBm = String.valueOf(-113 + 2 * rssi) + " dBm";
        }
 
        stringNeighboring = stringNeighboring
         + String.valueOf(NeighboringList.get(i).getLac()) +" : "
         + String.valueOf(NeighboringList.get(i).getCid()) +" : "
         + dBm +"\n";
        }
        
      
        AndroidPhoneStateListener phoneStateListener = new AndroidPhoneStateListener ();  
        mTelephonyMgr.listen(phoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
        
        
pulsante = (Button)  findViewById(R.id.button1);
pulsante.setText("In attesa posizione GPS");
pulsante.setEnabled(false);
posizione = (TextView)findViewById(R.id.lat);
gpsfix = (TextView)findViewById(R.id.gpsfix);
ph1 = (TextView) findViewById(R.id.p1);
ph2 = (TextView) findViewById(R.id.p2);
segnale = (TextView) findViewById(R.id.segnale);
last_pos = (TextView) findViewById(R.id.last_pos);
gpsfix.setText("00:00:00");
posizione.setText("0/0");
ph1.setText("CID:"+Integer.toString(cid)+" LAC:"+Integer.toString(lac));
ph2.setText("MCC:"+Integer.toString(mcc)+" MNC:"+Integer.toString(mnc));
//gestione della pressione del pulsante
pulsante.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
    // registra il tempo di pressione del pulsante
       if(event.getAction() == MotionEvent.ACTION_DOWN) {
          lastDown = System.currentTimeMillis();
       } else if (event.getAction() == MotionEvent.ACTION_UP) {
        // registra il rilascio del pulsante
          lastDuration = System.currentTimeMillis() - lastDown;
          // se il tasto e' stato premuto almeno 1 sec genera l'evento di invio SMS
          if (lastDuration > 1000)
          {
           pulsante.setBackgroundColor(Color.RED);
           pulsante.setText("Richiesta accettata. Invio in corso");
           
           // invio SMS
           try {
    SmsManager smsManager = SmsManager.getDefault();
    String testo_sms = Double.toString(latitudine)+"/"+Double.toString(longitudine)+"/"+tempo_gps+"/"+nr_phone+"/"+Integer.toString(cid)+"/"+Integer.toString(lac)+"/"+Integer.toString(mcc)+"/"+Integer.toString(mnc)+"/"+Integer.toString(signalStrengthValue);
    smsManager.sendTextMessage("xxxxxxxx", null, testo_sms, null, null);
    Toast.makeText(getApplicationContext(), "SMS Inviato",
    Toast.LENGTH_LONG).show();
     } catch (Exception e) {
    Toast.makeText(getApplicationContext(),
    "Ritento spedizione SMS",
    Toast.LENGTH_LONG).show();
    e.printStackTrace();
     }
           // fine invio SMS
          }
           else
           {
           pulsante.setBackgroundColor(Color.GREEN);
           pulsante.setText("Premere il pulsante per almeno 1 secondo");
           }
       }
return false;
    }
 });
}
public class MyLocationListener implements LocationListener
     {
  @Override
     public void onLocationChanged(Location loc)
     {
     latitudine = loc.getLatitude();
     longitudine = loc.getLongitude();
     long tempo = loc.getTime();
     
     // e' considerato di avere il fix gps se non ci sono piu' di 5 secondi
     // tra due letture consecutive
     if ((tempo-old_time < 5000) && (old_time > 0))
     {
             gps_fix = true;
            pulsante.setEnabled(true);
          pulsante.setBackgroundColor(Color.GREEN);
          pulsante.setText("Premere il pulsante per almeno 1 secondo");

             
             Date date = new Date(tempo);
             SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy HH:mm:ss zzz a");
             format.setTimeZone(TimeZone.getTimeZone("GMT"));
             tempo_gps= format.format(date);
             gpsfix.setText(tempo_gps);
             posizione.setText(loc.convert(longitudine, loc.FORMAT_SECONDS)+"/"+loc.convert(latitudine, loc.FORMAT_SECONDS));
             
             //se sono passati 10 minuti dall'ultimo scambio variabili
             //popolando le variabili dell'ultima posizione
             if (last_time - tempo > 600000)
             {
            last_time = tempo;
            last_lat=latitudine;
            last_long = longitudine;
            last_pos.setText(Location.convert(last_long, loc.FORMAT_SECONDS)+"/"+loc.convert(last_lat, loc.FORMAT_SECONDS));
             }
     }
     old_time = tempo;
     }


     @Override
     public void onProviderDisabled(String provider)
     {
     gps_fix = false;
     Toast.makeText( getApplicationContext(),R.string.gps_disabled,Toast.LENGTH_SHORT ).show();
     }


     @Override
     public void onProviderEnabled(String provider)
     {
     Toast.makeText( getApplicationContext(),R.string.gps_enabled,Toast.LENGTH_SHORT).show();
     }
     
     @Override
     public void onStatusChanged(String provider, int status, Bundle extras)
     {

     }
   }
 
   @Override
   protected void onStop()
   {
       //mlocManager.removeUpdates(mlocListener);
       super.onStop();
   }
   
   @Override
   protected void onDestroy()
   {
       mlocManager.removeUpdates(mlocListener);
       super.onStop();
   }
 
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public double FSPL(int db)
{
double distanza;
distanza = Math.pow(10,(-db - 98.89)/20);
return distanza;
}
public double FSPLDbm(int dbm)
{
double distanza;
double db1;
double Pm = 1000*Math.pow(10,(dbm/10)); 
db1 = 10*Math.log10(Pm);
distanza = Math.pow(10,(-db1 - 98.89)/20);
return distanza;
}
public class AndroidPhoneStateListener extends PhoneStateListener {

private double d;

public void ononCellLocationChanged(CellLocation location)
{
networkOperator = mTelephonyMgr.getNetworkOperator();
       cellLocation = (GsmCellLocation) mTelephonyMgr.getCellLocation();
       //il numero di telefono non e' codificato nella SIM
       nr_phone = mTelephonyMgr.getLine1Number();
       cid = cellLocation.getCid();
       lac = cellLocation.getLac();
       if (networkOperator != null) {
           mcc = Integer.parseInt(networkOperator.substring(0, 3));
           mnc = Integer.parseInt(networkOperator.substring(3));
       }
ph1.setText("CID:"+Integer.toString(cid)+" LAC:"+Integer.toString(lac));
ph2.setText("MCC:"+Integer.toString(mcc)+" MNC:"+Integer.toString(mnc));
       
       
       //definisce il tipo di connessione (UTMS/HDSPA/GPRS
       int tipo = mTelephonyMgr.getNetworkType();

       
       type = (TextView)findViewById(R.id.tipo);
       
       switch (tipo)
       {
       case 7:
           type.setText("1xRTT");
           break;
       case 4:
           type.setText("CDMA");
           break;      
       case 2:
        type.setText("EDGE");
           break;  
       case 14:
        type.setText("eHRPD");
           break;      
       case 5:
        type.setText("EVDO rev. 0");
           break;  
       case 6:
        type.setText("EVDO rev. A");
           break;  
       case 12:
        type.setText("EVDO rev. B");
           break;  
       case 1:
        type.setText("GPRS/GSM");
           break;      
       case 8:
        type.setText("HSDPA");
           break;      
       case 10:
        type.setText("HSPA");
           break;          
       case 15:
        type.setText("HSPA+");
           break;          
       case 9:
        type.setText("HSUPA");
           break;          
       case 11:
        type.setText("iDen");
           break;
       case 13:
        type.setText("LTE");
           break;
       case 3:
        type.setText("UMTS");
           break;          
       case 0:
        type.setText("Unknown");
           break;
       }
 
}
 
         @Override
         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
             super.onSignalStrengthsChanged(signalStrength);
             
networkOperator = mTelephonyMgr.getNetworkOperator();
       cellLocation = (GsmCellLocation) mTelephonyMgr.getCellLocation();
       //il numero di telefono non e' codificato nella SIM
       nr_phone = mTelephonyMgr.getLine1Number();
       cid = cellLocation.getCid();
       lac = cellLocation.getLac();
       if (networkOperator != null) {
           mcc = Integer.parseInt(networkOperator.substring(0, 3));
           mnc = Integer.parseInt(networkOperator.substring(3));
       }
ph1.setText("CID:"+Integer.toString(cid)+" LAC:"+Integer.toString(lac));
ph2.setText("MCC:"+Integer.toString(mcc)+" MNC:"+Integer.toString(mnc));
       
       
       //definisce il tipo di connessione (UTMS/HDSPA/GPRS
       int tipo = mTelephonyMgr.getNetworkType();

       
       type = (TextView)findViewById(R.id.tipo);
       
       switch (tipo)
       {
       case 7:
           type.setText("1xRTT");
           break;
       case 4:
           type.setText("CDMA");
           break;      
       case 2:
        type.setText("EDGE");
           break;  
       case 14:
        type.setText("eHRPD");
           break;      
       case 5:
        type.setText("EVDO rev. 0");
           break;  
       case 6:
        type.setText("EVDO rev. A");
           break;  
       case 12:
        type.setText("EVDO rev. B");
           break;  
       case 1:
        type.setText("GPRS/GSM");
           break;      
       case 8:
        type.setText("HSDPA");
           break;      
       case 10:
        type.setText("HSPA");
           break;          
       case 15:
        type.setText("HSPA+");
           break;          
       case 9:
        type.setText("HSUPA");
           break;          
       case 11:
        type.setText("iDen");
           break;
       case 13:
        type.setText("LTE");
           break;
       case 3:
        type.setText("UMTS");
           break;          
       case 0:
        type.setText("Unknown");
           break;
       }
             
             if (signalStrength.isGsm()) {
                 if (signalStrength.getGsmSignalStrength() != 99)
                     signalStrengthValue = signalStrength.getGsmSignalStrength() * 2 - 113;
                 else
                     signalStrengthValue = signalStrength.getGsmSignalStrength();
             }
             
             if (!signalStrength.isGsm()){
                 signalStrengthValue = signalStrength.getCdmaDbm();
                 if (signalStrength.getCdmaDbm() < signalStrength.getEvdoDbm())
                 {
                signalStrengthValue = signalStrength.getCdmaDbm();
                 }
                 else
                 {
                signalStrengthValue = signalStrength.getEvdoDbm();
                 }
                 
             }
             if (signalStrength.isGsm())
             {
            d = FSPL(signalStrengthValue);  
             }
             else 
             {
            d = FSPLDbm(signalStrengthValue);
             }
             
             DecimalFormat df = new DecimalFormat("#.##");
             segnale.setText("Segnale : "+Integer.toString(signalStrengthValue)+"dB / "+df.format(d)+"Km");

             // salva su file
             File root = Environment.getExternalStorageDirectory();
             if (root.canWrite()){
                 File data_file = new File(root, "onrelease.txt");
                 FileWriter data_file_writer = null;
try {
data_file_writer = new FileWriter(data_file,true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
                 BufferedWriter out = new BufferedWriter(data_file_writer);
                 try {
out.write(gpsfix.getText().toString()+";"+Double.toString(longitudine)+";"+Double.toString(latitudine)+";"+type.getText().toString()+";"+Integer.toString(mnc)+";"+Integer.toString(mcc)+";"+Integer.toString(lac)+";"+Integer.toString(cid)+";"+Integer.toString(signalStrengthValue)+";"+df.format(d)+"\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
                 try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}        
             }
             
         }
     }
}


mercoledì 1 gennaio 2014

ENC28J60 Ethernet Shield

In un precedente post avevo segnalato che uno dei due miei shield non funzionava con Arduino Due. In realta' i due shield presentati sono profondamente differenti in quanto basati su due chip differenti.

Il chip W5100 e' quello montato dallo shield supportato direttamente da Arduino e che quindi funziona direttamente con gli sketch presenti nell'IDE mentre il secondo chip e' denominato ENC28J60 non ha un supporto diretto con la necessita' quindi di installare una libreria apposita. Quale e' la differenza tra i due: il W5100 gestisce in modo nativo lo stack TCP/IP mentre ENC28J60 usa il processore dell'Arduino per le operazioni di rete. Ovviamente il secondo costa decisamente meno del primo a causa delle capacita' piu' limitate

A sinistra lo shield ENC28J60,a destra lo shield W5100



Ho provato differenti librerie ma l'unica che sembra funzionare e' questa. piuttosto limitata nelle funzioni
Secondo alcuni dovrebbe funzionare la libreria Ethercard ma per le mie prove gli sketch si compilano ma la scheda non assuma mai l'IP (sia che statico che dinamico)
Per la cronaca la scheda e' stata acquistata qui

CC1101 su Arduino

Mi e' stata prestata questa coppia di trasmettitori/ricevitori basati su chip Texas CC1101.
Questo componente promette bene perche' sulla scheda tecnica e' riportato un range di trasmissione di 300-500 metri in aria libera


I collegamenti sono a 7 fili (a destra i pin del CC1101,a sinistra i pin dell'Arduino)

GND / GND
VCC / VCC (3.3V)
CSN / D10
MOSI /D11
MISO / D12
SCK / D13
GD0 / D2

E' riportato che il componente lavori sia con le librerie di PanStamp che ElecHouse
Dalle mie prove (fatte su una Debian Box con l'ultima IDE di Arduino) non sono riuscito a compilare gli esempi di PanStamp (sembra a causa di un variabile definita in un header che non viene gestita dal compilatore, commentando la definizione di questa variabile relativa al risparmio energetico, lo sketch si compila ma non funziona)

Usando invece gli esempi della libreria ElecHouse tutto si compila correttamente ma da un paio di prove non sono mai riuscito a superare i 25 m di distanza di trasmissione in aria libera (a 25 m i pacchetti arrivano completi, da 25 a 30 m di distanza arrivano corrotti, oltre i 30 metri non arriva niente).
Sicuramente e' un mio errore perche' le librerie Pamstamp permettono di definire il livello di potenza della trasmissione (cosa che sembra assente in ElecHouse)

Interrupt su Arduino

Supponiamo il seguente scenario con protagonista un microcontrollore Arduino
1) Il compito e' quello di effettuare un compito ripetitivo (perfetto per il loop) ma di lunga durata.
2) All'interno di questo compito di lunga durata devono essere intercettati eventi (quale puo' essere un sistema di allarme od un sistema di protezione) in realtime che forzi Arduino ad agire immediatamente

Questo e' un campo di applicazione degli interrupt

Per semplificare diciamo che il compito ripetitivo e' quello di far blinkare il led in porta D13 con un ciclo di 10 secondi mentre l'evento extra e' dato dalla pressione di un pulsante collegato al pin D02 (interrupt 0 su Arduino UNO) che accenda il led in porta D12


Nel video si osserva come nel caso di accensione del led non determinato dall'interrupt si deve attendere che il loop effettui il suo ciclo completo (vedi sorgente sottostante, un ciclo completo e' di 10 secondi), nella seconda parte gestita dall'interrupt l'accensione e' istantanea

Come e' fatto il circuito



L'aspetto importante di questo esempio e' la possibilita' di effettuare operazioni all'interno di un interrupt (l'esempio del sito di Arduino mostra come cambiare il valore di una variabile ma l'azione di interpretare la variabile ed agire di conseguenza era sempre demandata al loop, cosi' se questo era occupato in una operazione lunga, non c'e' nessun vantaggio)


con gestione interrupt
-----------------------------------------------
int pin = 13;
volatile int state = LOW;
int led = 12;



void setup()
{
  pinMode(pin, OUTPUT);
  pinMode(led, OUTPUT);  

  attachInterrupt(0, blink, CHANGE);
}

void loop()
{
  digitalWrite(led, HIGH);  
  delay(1000);               
  digitalWrite(led, LOW);    
  delay(1000);               
}

void blink()
{
  state = !state;
  digitalWrite(pin, state);

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


senza gestione interrupt
-------------------------------------------------------------------------
#define led 13               
#define led2 12
#define BUTTON 2           
int  val = 0;                 

void setup() {
  pinMode(led, OUTPUT);       
  pinMode(BUTTON, INPUT);     
  pinMode(led2, OUTPUT);
}

void loop() {
  val = digitalRead(BUTTON);  // legge il valore dell'input e lo conserva

  // controlla che l'input sia HIGH (pulsante premuto)
  if (val == HIGH) {
    digitalWrite(led, HIGH);  //accende il led
  }
  else {
    digitalWrite(led, LOW);   //spegne il led
  }
  digitalWrite(led2, HIGH);   
  delay(5000);               
  digitalWrite(led2, LOW);    
  delay(5000);           
}

lunedì 30 dicembre 2013

Aggiornamento PN51T

In occasione dello scadere del contratto Internet annuale con TIM e nell'incertezza se rinnovare con la stessa societa' o passare a Vodafone (che allo stesso prezzo fornisce anche l'access point mobile) ho provato ad aggiornare il firmware del PN51T per farlo funzionare con la Arduino Yun (il motivo principale per cui mi tornerebbe comodo usare il PN51T, vedi precedente post)

da una visita sul sito http://www.ondacommunication.com/it/software_manuals.html ho visto che e' disponibile all'aggiornamento alla versione 10 del firmware mentre il mio dispositivo monta ancora la versione 6 (link a file di aggiornamento)

Firmware originale
L'aggiornamento si puo' eseguire solo sotto Windows e solo dopo aver installato i driver del dispositivo


La procedura dura circa 7 minuti


Al termine il dispositivo ha aggiornato il software


Attenzione: al riavvio si deve reinserire il codice PIN dall'interfaccia Web (altrimenti l'icona di rete rimane rosssa e non si accede ad Internet)

Adesso il PN51T funziona correttamente con Arduino Yun

venerdì 27 dicembre 2013

Distanza da antenna di telefonia mobile

UPDATE:
c'e' un errore di fondo nel calcolo della distanza impiegato in questo post
Le api di Android riportano la potenza del segnale in modo differente se si tratta di GSM o UMTS. Nel primo caso il valore viene espresso in dB mentre nel secondo in Dbm
Nei prossimi post cerchero'  di correggere l'errore
------------------------------------------------------------------------

Utilizzando la funzione signalStrength.getGsmSignalStrength() di Android e' possibile stimare la potenza del segnale della rete GSM e convertirla nel suo valore espresso in dB

Utilizzando la formula di FSPL (Free Space Path Loss) e' possibile inoltre risalire alla distanza tra l'antenna della telefonia mobile ed il proprio dispositivo mobile

Riprendendo da Wikipedia, la FSPL espressa per valori in GHz e' la seguente

dove
d = distanza tra l'antenna ed il dispositivo mobile
f = frequenza (2.1 GHz per la rete GSM italiana)
FSPL = il valore riportato dalla funzione Android

invertendo per ottenere la distanza e semplificando i calcoli (dato che la frequenza e' sempre la stesssa) si ha che
distanza = 10E((FSPL-98.89)/20)

Questa formula e' stata implementata in un semplice programma che mostra i dati di telefonia correlati ai dati derivanti dal GPS per una verifica (grossolana) dell'efficacia del sistema. Possono inseriti anche fattori di attenuazione e guadagni delle antenne ma nel caso in esame sono dati non disponibili


(la massima copertura di una antenna di telefonia e' di circa 24 Km)
Per la posizione delle antenne di telefonia mobile sono stati presi i dati da http://www.opencellid.org o da developer.opensignal.com
-----------------------------------------------------
Caso 1:
il telefono e' ubicato in posizione
Long : 11°17'27,32'' (ovvero 11.290922)
Lat : 43°45'33,05" (ovvero 43.759181)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 27988244
Long : 11.291428
Lat : 43.757431



La distanza stimata mediante il metodo FSPL e' di 0.16 Km mentre la distanza reale e' di Km 0.2


-----------------------------------------------------
Caso 2:
il telefono e' ubicato in posizione
Long : 11°18'38,73'' (ovvero 11.310758)
Lat : 43°50'1,61" (ovvero 43.833781)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 27997133
per una posizione dell'antenna di
Long : 11.304655
Lat : 43.8257665



La distanza stimata mediante il metodo FSPL e' di 0.2 Km mentre la distanza reale e' di Km 1.017


 -----------------------------------------------------
Caso 3:
il telefono e' ubicato in posizione
Long : 11°13'47,94'' (ovvero 11.229983)
Lat : 43°47'2,92" (ovvero 43.784144)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 27988287
per una posizione dell'antenna di
Long : 11.2312
Lat : 43.7845993



La distanza stimata mediante il metodo FSPL e' di 0.04 Km mentre la distanza reale e' di Km 0.11


 -----------------------------------------------------
Caso 4:
il telefono e' ubicato in posizione
Long : 11°18'38.73'' (ovvero 11.229983)
Lat : 43°50'1.5" (ovvero 43.784144)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 27997133
per una posizione dell'antenna di
Long : 11.304655
Lat : 43.825766






La distanza stimata mediante il metodo FSPL e' di 0.2 Km mentre la distanza reale e' di 4.7 Km 

 -----------------------------------------------------
Caso 5:
il telefono e' ubicato in posizione
Long : 11°18'38.73'' (ovvero 11.310758)
Lat : 43°50'1.5" (ovvero 43.83375)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 27988276
per una posizione dell'antenna di
Long : 11.245845
Lat : 43.79564150






La distanza stimata mediante il metodo FSPL e' di 0.05 Km mentre la distanza reale e' di Km 6.7
-----------------------------------------------------
Caso 6:
il telefono e' ubicato in posizione
Long : 11°16'48.99'' (ovvero 11.28)
Lat : 43°48'22.2" (ovvero 43.806167)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 27988315
per una posizione dell'antenna di
Long : 11.272541
Lat : 43.793081






La distanza stimata mediante il metodo FSPL e' di 1.27 Km mentre la distanza reale e' di Km 1.54
-----------------------------------------------------
Caso 7:
il telefono e' ubicato in posizione
Long : 11°17'32.39'' (ovvero 11.292222)
Lat : 43°48'58.15" (ovvero 43.816153)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 28021137
per una posizione dell'antenna di
Long : 11.2440335
Lat : 43.787733


La distanza stimata mediante il metodo FSPL e' di 0.02 Km mentre la distanza reale e' 4.9 di Km
-----------------------------------------------------
Caso 8:
il telefono e' ubicato in posizione
Long : 11°17'41.9'' (ovvero 11.294972)
Lat : 43°49'9.97" (ovvero 43.819436)

La cella agganciata ha identificativo
MCC : 222
MNC :88
LAC : 36057
CID : 28021135
per una posizione dell'antenna di
Long : 11.295127
Lat : 43.818963



La distanza stimata mediante il metodo FSPL e' di 0.16 Km mentre la distanza reale e' di 0.054 Km

In conclusione si osserva in alcuni casi un ottimo accordo tra la distanza calcolata e la distanza reale mentre in altri il valore e' sensibilmente differente. Probabilmente presumere la frequenza fissa e' un assunto non valido

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