lunedì 9 settembre 2013

XBee Shield e WiFly su Arduino Uno

Per dotare di connessione WiFi una scheda Arduino, in attesa dell'uscita di Arduino Yum,  ho preso su una schedina WiFly RN-VX

La scheda WiFly necessita di sole 4 connessioni : Vcc 3.3 V(Pin 1) , GND (Pin 10), Rx (Pin 3) ,Tx (pin 2)

Attenzione: la scheda non tollera le tensioni superiori a 3.3. V per cui il collegamento diretto dei Pin 2 e 3 ai pin digitali di una Arduino Uno brucia la scheda (esperienza diretta) per cui deve essere presente un regolatore di tensione. Sullo shield sono presenti delle resistenze di protezione

La WiFly e' stata connessa su uno shield XBee. Studiando lo shield si vede chiaramente che i Pin 2 e 3 della WiFly vengono connessi con i Pin D0 e D1 dell'Arduino. Cio' crea problemi perche' questi pin sono deputati alla trasmissione della seriale via USB. Per questo motivo i piedini del Pin D0 e D1 sono stati piegati verso l'esterno e tramite una patch sono stati connessi ai pin D2 e D3 dell'Arduino

D0 => D3
D1 => D2

Si notino i cavi arancioni che escono lateralmente dai Pin D0 e D1

Da notare che sulla scheda vi sono anche due Jumper in Blu. La posizione corretta e' quella sulla scritta USB

A questo punto per far funzionare la modalita' WiFi dell'Arduino e' sufficiente scaricare la libreria WiFlyHQ  e caricare l'esempio httpclient modificando la riga come segue la riga sulla SoftwareSerial oltre alle proprie impostazioni della rete WiFi
SoftwareSerial wifiSerial(2,3);
----------------------------------------------

#include <WiFlyHQ.h>

#include <SoftwareSerial.h>
SoftwareSerial wifiSerial(2,3);

//#include <AltSoftSerial.h>
//AltSoftSerial wifiSerial(8,9);

WiFly wifly;

/* Change these to match your WiFi network */
const char mySSID[] = "TIM_PN51T_C0D1"; // Wifi network name
const char myPassword[] = "50276337"; // Wifi network password

//const char site[] = "arduino.cc";
//const char site[] = "www.google.co.nz";
const char site[] = "hunt.net.nz";

void terminal();

void setup()
{
    char buf[32];

    Serial.begin(115200);
    Serial.println("Starting");
    Serial.print("Free memory: ");
    Serial.println(wifly.getFreeMemory(),DEC);

    wifiSerial.begin(9600);
    if (!wifly.begin(&wifiSerial, &Serial)) {
        Serial.println("Failed to start wifly");
terminal();
    }

    /* Join wifi network if not already associated */
    if (!wifly.isAssociated()) {
/* Setup the WiFly to connect to a wifi network */
Serial.println("Joining network");
wifly.setSSID(mySSID);
wifly.setPassphrase(myPassword);
wifly.enableDHCP();

if (wifly.join()) {
   Serial.println("Joined wifi network");
} else {
   Serial.println("Failed to join wifi network");
   terminal();
}
    } else {
        Serial.println("Already joined network");
    }

    //terminal();

    Serial.print("MAC: ");
    Serial.println(wifly.getMAC(buf, sizeof(buf)));
    Serial.print("IP: ");
    Serial.println(wifly.getIP(buf, sizeof(buf)));
    Serial.print("Netmask: ");
    Serial.println(wifly.getNetmask(buf, sizeof(buf)));
    Serial.print("Gateway: ");
    Serial.println(wifly.getGateway(buf, sizeof(buf)));

    wifly.setDeviceID("Wifly-WebClient");
    Serial.print("DeviceID: ");
    Serial.println(wifly.getDeviceID(buf, sizeof(buf)));

    if (wifly.isConnected()) {
        Serial.println("Old connection active. Closing");
wifly.close();
    }

    if (wifly.open(site, 80)) {
        Serial.print("Connected to ");
Serial.println(site);

/* Send the request */
wifly.println("GET / HTTP/1.0");
wifly.println();
    } else {
        Serial.println("Failed to connect");
    }
}

void loop()
{
    if (wifly.available() > 0) {
char ch = wifly.read();
Serial.write(ch);
if (ch == '\n') {
   /* add a carriage return */ 
   Serial.write('\r');
}
    }

    if (Serial.available() > 0) {
wifly.write(Serial.read());
    }
}

/* Connect the WiFly serial to the serial monitor. */
void terminal()
{
    while (1) {
if (wifly.available() > 0) {
   Serial.write(wifly.read());
}


if (Serial.available() > 0) {
   wifly.write(Serial.read());
}
    }

}

Conteggio Like mediante Arduino

In questo post viene descritto come effettuare il conteggio dei Like di una pagina Facebook mediante Arduino

Sono sono stati utilizzati
Arduino UNO
Shield Ethernet
Bridge Ethernet-WiFi Vonets
Display LCD 1602 (modalita' I2C)



Il montaggio e' piuttosto semplice.
Il bridge e' stato usato per dare capacita' wireless all'Arduino senza utilizzare il costoso shield apposito
Il montaggio dei cavi del display e' spiegato in questo post


Di fatto l'Arduino efffettua una richiesta ad uno script Php che e' su server remoto, legge e mette a display il risultato (il tutto e' basato sull'Esempio WebClient della libreria Ethernet di Arduino)
-------------------------------------
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display


String currentLine = "";            
String fbcount = "";                


byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "m.xxxx.unifi.it";    

IPAddress ip(192,168,0,177);
EthernetClient client;

void setup() {
   lcd.init();    
   lcd.backlight();
   lcd.print("Facebook");
   lcd.setCursor(0,1);
   lcd.print("Like counter");
   
  Serial.begin(9600);
   while (!Serial) {
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    Ethernet.begin(mac, ip);
  }
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.println("GET /xxxxxxx/like3.php HTTP/1.1");
    client.println("Connection: close");
    client.println();
  } 
  else {
    Serial.println("connection failed");
  }
}

void loop()
{
  if (client.available()) {
    char c = client.read();
    //Serial.print(c);

    currentLine += c; 


      if ( currentLine.startsWith("Like:")) {
         
        fbcount += c;
        Serial.println(fbcount);
        lcd.clear();
        lcd.print("Like"+fbcount);

      }

     if (c == '\n') {
        currentLine = "";
        fbcount = "";
      } 

    
  }

  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    while(true);
  }
}
--------------------------------------------------
Script PHP
--------------------------------------------------
<?
require_once '../src/facebook.php';

$appid = '673135956047578';
$appsecret = 'dde6cfb07dbb769c7efe949c20afd73d';

$facebook = new Facebook(array(
 'appId' => $appid,
 'secret' => $appsecret,
 'cookie' => false,
 ));

$like = array(
    'method' => 'fql.query',
    'query' => 'select fan_count from page where page_id=266068113416863;'
);

$result = $facebook->api($like);

print "Like:".$result[0]['fan_count'];
?>


Lettura di RFID Mifare con API di Android

In questo post viene descritto come leggere i tag Rfid Mifare Classic (13.56 MHz) disponendo di un telefono con antenna NFC come il Nexus S (attenzione che per leggere



L'interno con l'hardware NFC di un Nexus S (IFixIt)


Si parte da un progetto vuoto (Hello World) e si effettuano le modeste modifiche indicate in giallo nel listato seguente


Per prima cosa si deve modificare il file Manifest per dichiarare l'uso del sensore NFC e si deve dichiare una nuova intent che si apre quando viene passato un tag sotto il lettore

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

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.NFC"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.test4.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>


        <activity android:label="@string/event_verify" android:name="verifytagscanact">
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED"/>
            </intent-filter>
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/filter_nfc"/>
        </activity>

    </application>

</manifest>
------------------------------------------------
Si deve creare poi una nuova cartella xml nelle risorse e si crea un nuovo file filter_nfc

/xml/filter_nfc.xml
------------------------------------------------
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
    </tech-list>
</resources>
------------------------------------------------

la Main Activity e' composta da un solo Adapter che apre una nuova intent. A questo punto si apre la funzione OnNewIntent che legge il contenuto del tag

MainActivity.java
------------------------------------------------
package com.example.test4;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.nfc.Tag;
import android.nfc.NfcAdapter;
import android.nfc.tech.MifareClassic;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.util.Log;
import android.widget.Toast;
import java.math.BigInteger;

public class MainActivity extends Activity {

    NfcAdapter adapter;
    PendingIntent pendingIntent;
    IntentFilter writeTagFilters[];
    String[][] techListsArray;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        adapter = NfcAdapter.getDefaultAdapter(this);

        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
        try {
            tagDetected.addDataType("*/*");
        }
        catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        writeTagFilters = new IntentFilter[] { tagDetected };

        techListsArray = new String[][] { new String[] { MifareClassic.class.getName() } };

    }

    static String bin2hex(byte[] data) {
        return String.format("%0" + (data.length * 2) + "X", new BigInteger(1,data));
    }

    @Override
    protected void onNewIntent(Intent intent){
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        byte[] tagId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
        Toast.makeText(getApplicationContext(), bin2hex(tag.getId()), Toast.LENGTH_SHORT).show();


    }

    public void onPause() {
        super.onPause();
        adapter.disableForegroundDispatch(this);
    }

    public void onResume() {
        super.onResume();
        adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, techListsArray);
    }


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


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


Primi passi con Android Studio

Ho decisi di provare a sviluppare una piccola App completamente su Android Studio.

Una prima difficolta': come gia'  visto qui al primo avvio viene scaricato dalla rete Gradle. Se si e' dietro ad un proxy si deve andare nei Settings (si trovano spulciando la prima finestra di installalazione) e cercare Proxy Server ma attenzione l'indirizzo non deve essere del tipo http://mioproxy.it ma semplicemente mioproxy.it senza http://)

L'altra differenza che salta immediatamente agli occhi rispetto ad Eclipse e' la mancanza della finestra di Logcat (dove vengono mostrati i messaggi di debug)..si puo' attivare mediante la combinazione Alt+6



Per avere il completamente automatico si puo' usare Ctrl+Maius+Barra spaziatrice
Per l'help Maiusc+F1

giovedì 5 settembre 2013

Creazione di post automatici su Facebook con RFID (6)


Riprendendo il filone degli esperimenti precedenti in questo caso il lettore Rfid e' legato ad una Arduino che si occupa del carico di lavoro per l'interfaccia Web
Le connessioni per il lettore RFID sono

MOSI: Pin 11 / ICSP-4
MISO: Pin 12 / ICSP-1
SCK: Pin 13 / ISCP-3
SS: Pin 6 
RST: Pin 7

La scheda Arduino ha ovviamente montato lo Shield Ethernet



----------------------------------------
#include <SPI.h>
#include <Ethernet.h>
#include <RFID.h>


#define SS_PIN 6
#define RST_PIN 7
RFID rfid(SS_PIN, RST_PIN); 

int serNum0;
int serNum1;
int serNum2;
int serNum3;
int serNum4;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "m.xxxxxnifi.it";    


IPAddress ip(192,168,0,177);
EthernetClient client;

void setup() {
  Serial.begin(9600);
   SPI.begin(); 
  rfid.init();
  
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    Ethernet.begin(mac, ip);
    }
    else
    {
      Serial.println("IP Acquisito");
    }
  delay(1000);
  


}

void loop()
{
 if (rfid.isCard()) {
        if (rfid.readCardSerial()) {
                serNum0 = rfid.serNum[0];
                serNum1 = rfid.serNum[1];
                serNum2 = rfid.serNum[2];
                serNum3 = rfid.serNum[3];
                serNum4 = rfid.serNum[4];
                String Id = String(rfid.serNum[0],HEX)+String(rfid.serNum[1],HEX)+String(rfid.serNum[2],HEX)+String(rfid.serNum[3],HEX)+ String(rfid.serNum[4],HEX);
                Serial.println(Id);
                if (client.connect(server, 80)) {
                        Serial.println("connected");
                        client.println("GET /luca/xxxxxxx/rfid_server2.php?rfid="+Id+" HTTP/1.1");
                        client.println("Host: www.google.com");
                        client.println("Connection: close");
                        client.println();
                        } 
                        else {
                        Serial.println("connection failed");
                        }
              } 
          }
 rfid.halt();
 }
----------------------------------------


----------------------------------------
<?
require_once '../src/facebook.php';
//Luca
if ($_GET["rfid"] == "f479abb492")
    {
    $accessToken = "CAAJkNq2LttoBAJywtmNSbVHqFPubOjYmQ2yyUG4kpibD75BHid9J7xsvif8osSOc4ewgK4aYerrLZBsZCQM5wykRTYVLDkCJXlXYl3gi8WFRQ8U4p4y4ZAXYsdamz6RVdRJZAe4vZA80mWBayuG0qc4IAj2TMDmQXKiv1OrKp8CwKjD6Rz2ZCAqp8yxxxxxxxx";
    print "Luca<br>";
    }

$appid = '673135956xxxxxx';
$appsecret = 'dde6cfb07dbb769c7efe949xxxxxx';
$msg = $_GET["msg"];
$title = 'Dove sono ??';
$uri = 'http://debiaonoldcomputers.blogspot.com/';
$desc = 'Sono ad Arcetri';
$pic = 'http://wwxxxxxxxxxxxxxxxxxmes/Boozook/images/testa.gif';
$action_name = 'Link';
$action_link = 'http://www.geo.unifi.it/';

$facebook = new Facebook(array(
 'appId' => $appid,
 'secret' => $appsecret,
 'cookie' => false,
 ));
 $user = $facebook->getUser();
$attachment = array(
'access_token' => $accessToken,
'message' => $msg,
'name' => $title,
'link' => $uri,
'description' => $desc,
'picture'=>$pic,
'actions' => json_encode(array('name' => $action_name,'link' => $action_link))
);
$status = $facebook->api("/me/feed", "post", $attachment);
print "Ok";
?> 


Ethernet Shield e SPI

Cercando di accoppiare il lettore di Rfid presentato qui con una Arduino Uno dotata di Shield Ethernet, lo sketch gia' visto in precedenza ha smesso di funzionare


Il fatto e' dovuto (come spiegato qui) che lo shield utilizza il protoccolo SPI ed il PIN D10 risulta essere non disponibile per altri usi differenti da quelli della scheda di rete.
Per questo motivo lo sketch e' stato modificato come segue modificando la posizione dei Pin 9-10 in 6-7

------------------------------------------
#include <SPI.h>
#include <RFID.h>

#define SS_PIN 6
#define RST_PIN 7

RFID rfid(SS_PIN, RST_PIN); 

// Setup variables:
    int serNum0;
    int serNum1;
    int serNum2;
    int serNum3;
    int serNum4;

void setup()

  Serial.begin(9600);
  SPI.begin(); 
  rfid.init();
  
}

void loop()
{
    
    if (rfid.isCard()) {
        if (rfid.readCardSerial()) {
                serNum0 = rfid.serNum[0];
                serNum1 = rfid.serNum[1];
                serNum2 = rfid.serNum[2];
                serNum3 = rfid.serNum[3];
                serNum4 = rfid.serNum[4];
                String Id = String(rfid.serNum[0],HEX)+String(rfid.serNum[1],HEX)+String(rfid.serNum[2],HEX)+String(rfid.serNum[3],HEX)+ String(rfid.serNum[4],HEX);
                Serial.println(Id);
             } 
          }
        
    rfid.halt();
}

Ricerca dell'ID I2C su Arduino


Molti dispositivi da accoppiare ad Arduino si basano sul canale I2C e vengono identificati mediante un Id unico

Nel caso in cui non sia disponibile la documentazione si puo' trovare l'Id effettuando una scansione del bus mediante questo sketch derivante direttamente dal sito Arduino




// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// 
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknow error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

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