C言語でLED操作

C言語でLED操作

WiringPi のC言語用ライブラリを使えば
C言語でGPIOポートを制御するプログラムをかける

C言語の基礎は
ドットインストールを参考にするとわかりやすい

http://dotinstall.com/lessons/basic_c
で基礎の動画みれます

基本文法はこれでいいけど
Wiring Pi の関数も覚える必要があるので
https://projects.drogon.net/raspberry-pi/wiringpi/functions/
を参考に
(英語のサイトになります)

この中で使うのとしては

wiringPiSetupGpio()
これで WiringPi の初期化
gpio -g を使ったのと同じようにGPIOポートで指定するために宣言する

pinMode(GPIOポート番号, モード)
指定したGPIOポートのモードを設定
出力なら OUTPUT になる

pinMode(4,OUTPUT);

というように書く
ほとんどの場合はポート番号は定数にする

digitalWrite(GPIOポート番号, 値)
指定したGPIOポート番号に値を出力する
値は


のどちらかになる

digitalWrite(4,1);

これらを元にC言語ファイルを作成

vim led.c

内容は

#include<wiringPi.h>

#define LED_PORT 4

int main(void){
        int i;

        //初期化
        if(wiringPiSetupGpio() == -1) return 1;
        pinMode(LED_PORT,OUTPUT);

        for(i=0;i<10;i++){
                //LED ON
                digitalWrite(LED_PORT,1);
                delay(500);

                digitalWrite(LED_PORT,0);
                delay(500);
        }
        return 0;
}

がソースになる

なお定数の宣言で ; を最後につけるとエラーになる
#define LED_PORT 4
に注意

次にコンパイル

cc -o led led.c -lwiringPi

構文は

cc -o 好きな名前 ソースファイル名 -lwiringPi

となる

実行するには

sudo ./led 

とする

管理者権限が必要なので sudo をつける必要がある

これをつけないと

wiringPiSetup: Must be root. (Did you forget sudo?)

と言うエラーがでてくるので注意

実行するとLEDの点灯と消灯を10回繰り返す

WiringPi でLEDの制御

WiringPi でLEDの制御

仮想ファイルにアクセスすればGPIOを制御できるけど
手順が複雑になる

このため WiringPi に付属している gpio ユーティリティを使うことで簡単に操作できる

まず gpio mode コマンドで
GPIOポートのモード

つまり入出力の方向を設定する

引数の mode の後に設定したいGPIOのポート番号と
in out などのモードを設定する

信号を出力してLEDを光らせるのなら
モードは out になる

また、オプションの -g をつけることで
GPIOポート番号で指定できる

-g オプションをつけないと
WieingPi の独自の番号になる

つまり、モードの構文は

gpio -g mode GPIOポート番号  モード

となる

今回はLEDを光らせるので

gpio -g mode 4 out

となる

これでモードの指定はできたので
gpio write コマンドで出力する

引数の write の後に
GPIOのポート番号

出力する値
を設定する

構文は

gpio -g write GPIOポート番号 値

となる

今回なら

gpio -g write 4 1

これを実行するとLEDが点灯する

また
gpio export コマンド
gpio unexport コマンド
を使うことで
GPIOポートの仮想ファイルの読み書きができる

これらは -g オプションをつけずに実行する

構文は

gpio export GPIOポート番号 モード
[/shell
と

gpio unexport GPIOポート番号 

となる

今回なら

gpio export 4 out
[/shel]
と

 gpio unexport 4 

となる

AndroidでCookieの利用

AndroidでCookieの利用

Cookieは、Webサイト側がブラウザを利用している端末に一時的にデータを保存する仕組み

端末へcookieを設定すれば
設定した端末のブラウザからWebサイトへアクセスしたときに
自動的にCookieの値を送信する

これは、ログイン情報の保持に使われる

AndroidのWebViewでもCookieが使えるので
これを使って自動ログインの仕組みの実装
アプリ内ブラウザか、それともそれ以外のブラウザかをサーバーで判定できる

Cookieを使うには
アプリの開始直後に
CookieSyncManagerクラスの
createInstance()を呼び出す

そして、
onResumeハンドラ
onPauseハンドラ

startSync()
stopSync()
を記述する

そして、CookieManagerクラスの
setAcceptCookie()を呼び出せば
Cookieの利用ができる

まず、メンバ変数の宣言

private WebView mWebView;

次に、onCreate()の中へCookieを使うための設定

CookieSyncManager.createInstance(getApplicationContext());

CookieManager cm = CookieManager.getInstance();

//Cookie利用開始
cm.setAcceptCookie(true);

//期限切れのCookie削除
cm.removeExpiredCookie();

setCookie();

途中に書いた resumeExpiredCookie()は
期限切れのCookieを削除するメソッド

次に、onResume()へ
startSync()を追加

@Override
protected void onResume(){
super.onResume();
CookieSyncManager.getInstance().startSync();
}

onPause()には、stopSync()を追加

@Override
protected void onPause(){
super.onPause();
CookieSyncManager.getInstance().stopSync();
}

次に、Cookieの設定
独自のCookieを設定するには
CookieManagerクラスのsetCookie()を使う

setCookie()の第1引数にはURL
第2引数には、Cookieとして設定する文字列を指定する

まずは、setCookie()の実装

private void setCookie(){

CookieManager cm = CookieManager.getInstance();
BasicClientCookie cookie = getSampleCookie();
cm.setCookie(cookie.getDomain(), toHeaderCookie(cookie));
CookieSyncManager.getInstance().Sync();
}

サンプルのCookieのURLを作成

private BasicClientCookie getSampleCookie(){

BasicClientCookie cookie = new BasicClientCookie("CookieSampleKey", "CookieSampleValue");
cookie.setDomain("サーバーのドメイン");
cookie.setPath("/");
return cookie;
}

そして、Cookieの値の作成

private String toHeaderCookie(BasicClientCookiec){

StringBuilder sb = new StringBuilder();
sb.append(c.getName()).append("=").append(c.getValue()).append(";");

sb.append("domain").append("=").append(c.getDomain()).append(";");

sb.append("path").append("=").append(c.getPath()).append(";");

return sb.toString();
}

GPIOポートからLED制御

GPIOポートからLED制御

Raspberry pi のGPIOポートは
値が0なら 0V
値が1なら 3.3V
の電圧が出力される

値が1のときにLEDが光るようにすれば
GPIOポートの信号が正しく出力されているかわかる

今回も270Ωの抵抗とLEDを使用

今回は
GPIO 04 を+
GND をーにする

ジャンパケーブルをさすのは
+が左上から4番め
ーは前回と同じく右から3番め

これで配線準備は完了
電源をいれても、今回は最初からLEDは点灯しない

次に、コマンドからLEDを制御する

現在動かしているOS Raspbianは
/sys/class/gpio/
の中にある仮想ファイルにアクセスすることで
GPIOポートを制御できる

GPIOポートを使う手順は
使用開始を宣言
入出力設定
値の入出力
使用終了の宣言
となる

これにアクセスするには root 権限を得るか
pi ユーザが gpioグループに所属していることが条件

 id -Gn pi

で所属しているグループをみることができる

pi adm dialout cdrom sudo audio video plugdev games users netdev input spi gpio

というように結果の中に gpio があればOK

これが確認できたら、操作開始

まずはGPIOの使用するポートを宣言
今回はGPIO 04 を使うので

echo 4 > /sys/class/gpio/export 

構文は
echo ポート番号 /sys/class/gpio/export
となる

これを実行すると
/sys/class/gpio/

の下に gpio4 という仮想ディレクトリができる

GPIO 04 の制御はここで行うことになる

次に、出力方向の指定
今回は信号を出力してLEDを光らせたいので
out を使う

出力方向の設定は

echo out > /sys/class/gpio/gpio4/direction 

構文は
echo out > /sys/class/gpio/使用するGPIOポート番号/direction
[/shell]

ここまででGPIO 04 の制御の準備ができたので
/sys/class/gpio/使用するGPIOポート番号/value
に値を書き込むと操作できる
点灯なら1
消灯なら0

今回は点灯なので

echo 1 > /sys/class/gpio/gpio4/value 

で点灯する

消したいのなら

echo 0 > /sys/class/gpio/gpio4/value 

とりあえずこれで操作は終了となるので
使用収量を宣言する必要がある

使用終了は

echo 4 > /sys/class/gpio/unexport 

というように

echo 終わりたいポート > /sys/class/gpio/unexport
とする

位置情報を利用したページの表示

位置情報を利用したページの表示

位置情報を利用したページは
アプリ利用者の位置情報を必要とするページのこと

JavascriptにGeolocation APIがあるので
これを使えるようにする

まずは、AndroidManifest.xmlへ権限を追加する

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

次に、JavaでGeoLocation APIの有効化
まずは、位置情報の取得の有効化
これで、Webページが位置情報をリクエストしてきたときに
アプリ側でリクエストを許可するかを決めることができる

まず、メンバ変数の定義

private WebView mWebView;

次に、onCreate()へWebView関連の処理追加

mWebView = new WebView(this);
setContentView(mWebView);

//Javascript有効化
mWebView.getSettings().setJavascriptEnabled(true);

setupGeoLocation(mWebView);
mWebView.setWebViewClient(new WebViewClient());

setupGeoLocation()は、ユーザー関数
つまり自作でつくる関数なので
これを追加する

private void setupGeoLocation(WebView webview){

WebSettings ws = webview.getSettings();

//位置情報取得の有効化
ws.setGeoLocationEnabled(true);

//DB保存場所の指定
File databaseDir = getDir("databases", Context.MODE_PRIVATE);

//保存場所がないなら新規作成
if(!databaseDir.exists()){
databaseDir.mkdirs();
}
ws.setGeoLocationDatabasePath(databaseDir.getPath());
}

次に、位置情報取得許可を表示するためのダイアログ作成

Webページが位置情報のリクエストをすると
WebChromeClientクラスの
onGeoLocationPermissionShowPrompt()
が呼ばれる

このタイミングでダイアログを表示して
ユーザーに位置情報取得許可を促す

これで、許可されたら
GeoLocationPermissions.Callbackインスタンスの
invoke()を呼ぶことで
Webページは位置情報を取得できるようになる

このダイアログ作成処理をonCreate()へ追加する

mWebView.setWebChromeClient(new WebChromeClient(){

@Override
public void onGeoLocationPermissionsShowPrompt(String origin, Callback callback){
GeoLocationPermissionDialog.newInstance(callback, origin).show(getFragmentManager(), GeoLocationPermissionDialog.FRG_TAG);
}

@Override
public void onGeoLocationPermissionsHidePrompt(){
FragmentManager fm = new FragmentManager();
Fragment f = fm.findFragmentByTag(GeoLocationPermissionDialog.FRG_TAG);

if(f != null){
GeoLocationPermissionDialog d = (GeoLocationPermissionDialog)f ;
d.dismissAllowingStateLoss();
}
}
});

mWebView.loadUrl("http://位置情報取得許可するページのURL");

次に、ダイアログフラグメントの作成

public static class GeoLocationPermissionDialog extends DialogFragment{

public static final String FRG_TAG = GeoLocationPermissionDialog.class.getSimpleName();

public static final String EXTRA_ORIGIN = "extra.ORIGIN";

private GeoLocationPermissionDialog newInstance(GeoLocationPermissions.Callback callback, String origin){
GeoLocationPermissionDialog f = new GeoLocationPermissionDialog();
f.mCallback = callback;
Bundle args = new Bundle();
args.putString(EXTRA_ORIGIN,origin);
f.setArguments(args);
return f;
}

次に、ダイアログの設定
はい、いいえボタンの動作を定義

@Override
public Dialog onCreateDialog(Bundle savedInstanceState){

AlertDialog.Builder = new AlertDialog.Builder(getActivity());

builder.setTitle("位置情報の要求");
builder.setMessage(String.format("このページはあなたの位置情報を求めてます¥n許可しますか?", getArguments().getString(EXTRA_ORIGIN)));

builder.setPositiveButton("はい",
new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which){
if(mCallback != null){
mCallback.invoke(
getArguments().getString(EXTRA_ORIGIN),true, false);
}
mCallback = null;
}
});

builder.setNegativeButton("キャンセル", null);

return builder.create();
}
}
@Override
public void onDismiss(DialogInterface dialog){

super.onDismiss(dialog);

if(mCallback != null){
mCallback.invoke(getArguments().getString(EXTRA_ORIGIN), false, false);

mCallback = null;
}
}

このクラスのinvoke()の引数は3つ

1つは、オリジン
オリジンとは、URLのうちの
スキーム
ホスト
ポートの組み合わせ
JavascriptやPHPやっているとわかりやすい

オリジンには
onGeoLocationPermissionsShowPromptハンドラの引数 origin を指定する

2つめの引数は、位置情報提供の許可、
拒否を表す真偽値
つまり許可ならtrue
拒否ならfalse

そして、3つめの引数が
今後も位置情報提供を記憶するかどうかの真偽値
つまり記憶するならtrue
記憶しないならfalse
となる

Raspberry Pi に WiringPi のインストール

Raspberry Pi に WiringPi のインストール

WiringPi は Raspberry Pi 用GPIOライブラリで
GPIOを利用するプログラムをC言語で作成するときに使える

またC言語だけでなく
Python
PHP
Ruby
Perl
などでも使えるラッパーがあるのでC言語以外でも使える

WiringPi にはC言語ライブラリ以外に
gpioユーティリティが付属している

これを使うことで
コマンドでGPIOの制御ができる

まずは準備
WiringPi を使うには
lib2c-dev という I2C の開発ライブラリが必要

 sudo apt-get install libi2c-dev

次に WiringPi のインストールだけど
apt-get でインストールはできない

ソースファイルのダウンロード
コンパイル
インストールという手順になる

まずはパッケージ管理ソフトで
ソースファイルを入手するために
git をインストールする

sudo apt-get install git-core 

次にソースファイルのダウンロード

git clone git://git.drogon.net/wiringPi

これで wiringPi ディレクトリが作成され
この中にファイルが展開される

次にコンパイル

 cd wiringPi/
./build 

コンパイルが完了すると
ライブラリやgpioユーティリティがインストールされる

念のためバージョンも確認

gpio -v


確認できる

結果は

gpio version: 2.20
Copyright (c) 2012-2014 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty

Raspberry Pi Details:
  Type: Model B, Revision: 2, Memory: 512MB, Maker: Sony 

これで、WiringPi はインストールできたけど
注意点としては
GPIOポートの指定方法が2つあること

1つはGPIOのポート番号を使う方法

もう1つは
WiringPi が独自に決めた番号で設定する方法

GPIOポートの場合だと
順番にならんでいないし番号もとびとび

WiringPi のほうだと0から順番に指定できるけど
配線作業のときに置き換える必要があるので面倒

というようにどちらがいいとは言えない

ある意味好みなのと
ソースを読むときに、この種類の違いを覚えておくと
動かない理由を探ることができる

Raspberry Pi とGPIOポート

Raspberry Pi とGPIOポート

raspberry pi のGPIOポートに
LED
スイッチ
モーターを制御するICなど様々な電子部品を接続することができる

なおGPIOポートは
デジタル出力なので
0か1のデジタル信号になる

各端子に出力する電圧が0Vなら0
3.3Vなら1になる

電圧の高低でデジタル情報を表すので
0ならL、つまり Low
1ならH つまりHigh
となる

Raspberry Pi には複数のGPIOポートがあるけど
ピン番号とGPIOポートの番号は一致していないので注意

GPIOポートについては
http://elinux.org/RPi_Low-level_peripherals#GPIO_hardware_hacking
にまとめられてるので参考に

そして
私の場合、ハンダ付けができないため
ブレッドボードを使用

ブレッドボードはユニバーサル基盤みたいにたくさん穴があるけど
さすだけで使えるのでこれを使う

基本的にはんだができないので
はんだを使わないものから実践

なお、秋葉原にハンダ付けカフェというものがあり
そこでも使えるみたい

営業日については
https://www.google.com/calendar/hosted/switch-science.com/embed?src=switch-science.com_adlqek3ketk3pl2sqjufv1fcos@group.calendar.google.com&ctz=Asia/Tokyo
を参考に

ブレッドボードは、ハンダ付けはいらない代わりに
ジャンパーワイヤーを使うことになる

書籍には
秋葉原とかで買えますって書いてあるけど
基本的に私の場合オンラインで購入したい

これは、引越しとかもあるし
東京在住でない人も実践できるから

あと、抵抗を買うときにはΩだけではダメで
何に使うかによっていろいろ変わるらしい

まずはLEDを光らせる通称Lチカに挑戦

一番迷うのが抵抗

これは
カラー抵抗値の写真早読み表!

を参考にさせてもらいました

抵抗については
150~330Ω程度
となっているので
ハック ラズベリーパイ Raspberry Pi 電子工作入門キット。

を購入し、その中から
赤のLED
ジャンパワイヤーのメスオスx2本
ブレッドボード
270Ωの抵抗

を使いました

抵抗は色で判断するしかないので
http://part.freelab.jp/s_regi_list.html
を参考に

見分けの方法ですが
金色の線をを右側にして
左側から3番めの線が橙色なのが 10KΩです

入っている部品は
10KΩ が4本
270Ω が4本
となっているので消去法で270Ωをみつけました

さらに、LEDにも極性
つまり+と-があります

LEDは足の長いほうが+で
アノードと呼ばれ
足の短いほうがーで
カノードと呼ばれます

ちなみに、抵抗には極性がないらしいです

これでブレッドボードを実践します

Raspberry Pi の 
Pin1 左上のところへ+の抵抗とつけたジャンパケーブルをさして

Pin 6 右上から3番めがGNDになるので
ここへLEDの-部分にさしたジャンパケーブルをさします

これで Raspberry Pi の電源を入れると
LEDが点灯します

次回は WiringPi を入れてLEDの操作をしていこうと思います

なお書籍で部品まで詳しく掲載されているものとして
Raspberry Piクックブック (Make:PROJECTS)

がありました

機会をみてショップのリンクなどを書いていこうと思います

AndroidでHTML5 のWebStorageの利用

AndroidでHTML5 のWebStorageの利用

HTML5からは、WebStorageAPIがあり
Javascriptを使うことでページを更新してもデータを永続化できるのがメリット

AndroidのWebViewの中でWebStorageを使うには
WebSettingsクラスの
setDatabaseEnabled()
setDomStorageEnabled()
を使う

これらにtrueをセットすることで
WebStorageの有効化ができる

さらに
setDatabasePath()へ保存先を指定すれば
データの保存も可能になる

private void setupWebStorage(WebView webview){

WebSettings ws = WebView.getSettings();

//DB有効化
ws.setDatabaseEnabled(true);
ws.setDomStorageEnabled(true);

//DB保存場所の指定
if(Build.VERSION_CODES.JELLY_BEANS_MR2 <= Build.VERSION_SDK_INT){
File databaseDir = getDir("databases", Context.MODE_PRIVATE);

保存場所がないなら新規作成
if(!databaseDir.exists()){
databaseDir.mkdirs();
}
ws.setDatabasePath(databaseDir.getPath());
}
}

assetsフォルダのHTML表示

assetsフォルダのHTML表示

アプリにHTMLやCSS
Javascriptや画像などのリソースを含めておき、WebViewで表示することができる

これをやるには
loadUrl()の引数に指定するURLを
file:///android_asset/ファイル名
とする

mWebView.loadUrl("file:///android_asset/index.html");

というかんじ

これは、利用規約やプライバシーポリシーの表示
アプリの解説やFAQなどに使うことが多い

また、PhoneGapなどでもこの方法は使われる

ただし、追加するごとにアプリサイズが大きくなるので注意

ファビコンの取得

ファビコンの取得

ファビコンは、WebページやWebサイトのシンボルマークとして設置できるアイコンのこと

Webサイトを閲覧していると
ブラウザのURL欄の左側にでているのがわかる

ファビコンを取得するには
WebIconDatabaseクラスに
ファビコンの保存先を指定して
WebChromeClientクラスの
onReceivedIconハンドラ経由で取得する

onCreate()の中へ処理を追加

setupWebIconDatabase();

mWebView = (WebView)findViewById(R.id.web);
mFaviconView = (ImageView)findViewById(R.id.imgFavicon);
mTitleView = (TextView)findViewById(R.id.title);

mWebView.getSettings().setJavascriptEnabled(true);
mWebView.setWebViewClient(newWebViewClient());
mWebView.setWebChromeClient(new WebChromeClient(){

@Override
public void onReceivedTitle(WebView view, String title){
mTitleView.setText(string);
}

@Override
public void onReceivedIcon(WebView view, Bitmap icon){
Log.d(TAG, "onReceivedIcon");
mFaviconView.setImageBitmap(icon);
}

@Override
public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed){
Log.d(TAG,"onReceivedTouchIconUrl, url = "+ url);
}
});
mWebView.loadUrl("アイコンのURL");

次に、ファビコンアイコンの保存先を
setWebIconDatabase()で指定

@SupportWarnings("deprecation")
private void setWebIconDatabase(){
if(Build.VERSION_SDK_INT <= Build.VERSION_CODES.JELLY_BEANS_MR2){
//アイコンを保存するディレクトリを取得
File databaseDir = getDir("icon", Context.MODE_PRIVATE);

if(!databaseDir.exists()){
//ディレクトリがないなら作成
databaseDir.mkdirs();
}

//正常につくれたら、WebIconDatabase保存先として指定
android.webkit.WebIconDatabase.getInstance().open(databaseDir.getAbsolutePath());

Log.d(TAG,"IcondatabaseDir = "+ databaseDir);
}
}

Android 4.4からは
WebIconDatabaseクラスは非推奨になったけど
それ以下のバージョンだと、使わないと
onReceivedIconUrlハンドラが呼ばれなくなる

onReceivedTouchIconUrl()は
ファビコンではなく
apple-touch-iconを取得するためのハンドラ

apple-touch-iconは
Appleの独自仕様で、大きなファビコンみたいなもの

Webサイトがこれに対応してると
このイベントハンドラが動作するので
そのURLから画像を取得することになる