raspberry Pi のPWMでLEDの明るさ変更

raspberry Pi のPWMでLEDの明るさ変更

GPIOの出力は
0 つまり 0V
1 つまり 3.3V
だけなので
これだとLEDをつけるか消すしかできない

しかしPWMを使えば明るさの変更ができるようになる

デジタル信号は


だけだけど
高速で信号をON/OFF させることで
明るさを調整していかのように錯覚させることができる

これはLEDを人間では分からないくらいの早さで
ON/OFF にしていることで錯覚させている

この原理でONの状態が長いと明るく感じて
ONの状態が短いと暗く感じる

このON/OFF のパルスの幅を変える仕組みのことを
PWM
Pulse Width Modulation
といい
パルス幅変調とも言われる

そしてPWMの ON/OFF の長さの比率のことを
デューティー幅という

PWMは様々なところで使われていて
PCのファンの回転数のコントロールにも使われている

Raspberry Pi ではGPIO18だけ
PWM出力可能で
他のGPIOではできない

プログラムを組んで
他のポートでも擬似的にできるけど
CPU処理などで微妙な待ち時間ができるため
不安定な動作になってしまう

とりあえずLEDを使って実験

ハック ラズベリーパイ Raspberry Pi 電子工作入門キット。

の中から
赤のLED
ジャンパワイヤーのメスオスx2本
ブレッドボード
270Ωの抵抗
を使うことに

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

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

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

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

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

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

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

今回はGPIO18の部分を+にするので
Raspberry Pi の 
Pin1 右上から6番めのところへ+の抵抗とつけたジャンパケーブルをさして

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

これで配線準備は完了

URL中の特定の文字列の抽出

URL中の特定の文字列の抽出

これは、表示中のページからJavascriptコードを使うときに利用する

URL文字列を使っていると
ホスト部分や
クエリパラメーター部分だけ切り出して利用することがある

PHPのマッシュアップではおなじみのもの

これを実現するには
Uriクラスを使う

まずほ、Uriインスタンスの取得

Uriクラスの
parse()を使うことで、Uriインスタンスを取得する

Uri uri = Uri.parse("http://www.example.com/");

次に、取得したインスタンスのメソッドを取得
もし、ホスト部分を取得したいのなら
getHost()
を使う

String scheme = uri.getHost();

ほかのメソッドを使えば
様々な部分の値の取得が可能

例えばURLが
https://user:pass@www.example.com:8080/path/to/index.html?parameter1=value1&parameter2=value2#fragment

だったなら
getScheme()で
http:// とかhttps:// の判別

getSchemeSpecificPart()は
URL全部

getUserInfo()では
user:pass
みたいなユーザ名、パスワード

getAuthority()で
user:pass@www.example.com:8080
みたいに、
ユーザ名:パスワード@ドメイン:ポート番号

getHost()で
www.example.comというようにドメイン
取得

getPort()で8080というように、ポート番号の取得 

getPathSegment()で
ファイルまでのパス取得
今回なら
path/to/index.htmlを
配列で [path, to, index.html]と扱う

getLastPathSegment()で
パスの最後を取得
今回なら index.html

getQuery()で
URLの ? 以降のパラメーターを取得
今回なら
parameter1=value1&parameter2=value2

getFragment()で
fragmentの取得

表示中のページへJavascript発行

表示中のページへJavascript発行

これは、アプリでWebページを書き換えるときに使う

WebページへJavascriptを発行するには
WebViewクラスのloadUrl()を使う

このときに、引数として渡す文字列をhttp://とかのUrlではなく

javascript.
というようにして渡す

また
WebViewクラスの
setJavascriptEnabled(true)
を先に呼び出してJavascriptを使えるようにしておく必要がある

mWebView.loadUrl("javascript.document.getElementById('area').innerText = ('Javascript replace !');");

これで、Javascriptでテキストの置き換えができる

C言語でボタン状態の取得

C言語でボタン状態の取得

WiringPi のC言語ライブラリにある
digitalRead() を使うことで
指定したGPIOポートの値を取得できる

vim button.c

でファイルを作成

ソースは

#include<stdio.h>
#include<wiringPi.h>

#define BTN_PORT 25

int main(void){
        int data, i;

        //初期化
        if(wiringPiSetupGpio() == -1) return 1;

        //GPIO mode in
        pinMode(BTN_PORT,INPUT);

        //読み込み
        for(i=0; i<10;i++){
                //GPIO の値読み込み
                data = digitalRead(BTN_PORT);


                printf("GPIO%d = %d\n",BTN_PORT,data);
                
                //1秒まつ
                sleep(1);
        }
        return 0;
}

最初に
#include
でライブラリなどを読み込む

#define は定数の定義

wiringPiSetupGpio() は
wiringPi の初期化

pinMode(GPIOポート番号 , 入力モード)
でポートのモードを設定
今回なら in モードなので INPUT

pinMode(BTN_PORT,INPUT);

digitalRead(GPIOポート番号)
でポートの値を取得
今回は

data = digitalRead(BTN_PORT);

として結果を変数data に格納している

これで

cc -o button button.c -lwiringPi

でコンパイル

構文は

cc -o 任意の名前 Cソースファイル名 -lwiringPi

これで実行するけど
権利者権限で実行しないとエラーになるので

sudo ./button 

これでボタンをおすと1
ボタンを押していないと0
が10回まで表示される

結果は

GPIO25 = 0
GPIO25 = 0
GPIO25 = 0
GPIO25 = 1
GPIO25 = 1
GPIO25 = 0
GPIO25 = 1
GPIO25 = 0
GPIO25 = 1
GPIO25 = 0

となった

raspbery Pi でボタンからの入力を検知

raspbery Pi でボタンからの入力を検知

GPIOポートが out モードのときなら
値が0なら 0V
値が1なら 3.3V
の電圧が出力される

これに対して
inモード、つまり入力のときには
GPIOポートの電圧に応じた値を読み込める

電圧 0V なら 0
3.3V なら 1
となる

GPIOポートはデジタル入力のため
値が 0 と 1 しかない

例えば
3.3V の半分の1.65V の電圧を加えても 0.5 にはならず
0と1のどっちかという不安定な値になってしまう

このため Raspberry Pi のGPIOポートに入力する電圧は値を正しく検知できるように
3.3V

0V
にする

今回はボタンをおすと 3.3 V の電圧が加わるようにする

使うパーツは
10KΩの抵抗
タクトスイッチ
ジャンパーケーブル3本
ブレッドボード
そして Raspberry Pi 本体

部品に関しては Amazon で購入

電子部品についてはセットであったのでこれを購入

抵抗に関しては少し分かりにくいため
カラー抵抗値の写真早読み表!

を参考に
一番左が茶色のものが 10KΩということで使用

部品に関してはこれでOK

GPIOのヘッダピンになる Pin1
これは一番左上のピン

これは 3.3 V が出力されているので
ボタンが押されたら、この 3.3V が
GPIO25 の Pin22 に加わるようにする
この位置は右上3番めにある

そしてGNDとの間には
10KΩの抵抗を入れる

これがプルダウン抵抗
これがないと
ボタンをおすと GPIO25に 3.3 V が加わるけど
押していないと何もつながっていない状態になる
しかし
電圧は 0V にならずに不安定な状態になっている

これを防ぐために
高い抵抗値をもつ抵抗をいれることで
GND側に電圧を引っ張る

ちなみに
GND側に抵抗をいれることをプルダウンと呼ぶ

注意点として4本足のボタンを使うので
ボタンを押したときににどのピンとつながるのかを調べておく必要がある

これで準備できたので、まずはコマンドでボタンの状態を取得

LEDを光らせるのと同じ手順になるけど
今回は入力になるので
モードが in になる

まずはGPIO25を inモードで使用開始宣言

echo 25 > /sys/class/gpio/export 

で使用するポートを宣言

echo in > /sys/class/gpio/gpio25/direction 

でモードを in に指定

次に cat コマンドで値を読み込む

cat /sys/class/gpio/gpio25/value 

まずはボタンを押していない状態で実行すると

になる

ボタンを押しながら

cat /sys/class/gpio/gpio25/value 

を実行すると

になる

このように、信号の入出力もファイルを読み書きする感覚でGPIOポートを扱うことができる

そして、GPIOポートの使用が終了したら
unexport で終了宣言をする

echo 25 > /sys/class/gpio/unexport 

ちなみに、WiringPi を使えばもっと簡単に操作できる

gpio mode コマンドで in モードに設定して
gpio read コマンドで値を読み出せる

まずはポートの設定
構文は

gpio -g mode 使用するGPIOポート番号 in

今回なら GPIO25 なので

gpio -g mode 25 in

次に gpio read コマンドで値を読み込む

構文は

gpio -g read GPIOポート番号

今回は GPIO25 なので

gpio -g read 25

これでボタンを入れながら実行すると

と表示され、入れずに実行すると

となる

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
となる