ADKでモーターを制御する。(失敗の原因)
前回、ArduinoとAndroidの接続がすぐに切れてしまうという不具合があった。 とりあえず接続は切れなくなったので記録しておく。
モーターの消費電力
前回の構成では、モーターの駆動用電源はArduinoの3.3V出力ピンから取って、モータードライバーTA7291Pの8番ピンに接続していた。しかし、Arduinoのドキュメントをみると、3.3V出力ピンの最大電流は50mAとある。
A 3.3 volt supply generated by the on-board regulator. Maximum current draw is 50 mA.
これではモーターの動作には不十分。
切断の原因
おそらくArduino内の多くの電力をモーターに使われてしまい、Arduino自体が正常動作しなくなり、Androidとの接続が切断してしまったのだろうと思う。
ここで「おそらく」「だろうと思う」としたのは、私が持っているハードウェアと電気の知識では、本当の原因を調査するスキルが無いから。下にある通り、とりあえず正常動作したので、この問題はこれで解決とする。
正常動作
Arduino用とは別に電源を用意してTA7291Pの8番ピンに接続したところ、想定通りモーターの正転/逆転が制御出来た。
ADKでモーターを制御する。(失敗)
今作っている自立型充電スタンドは、モーターで重りを回してバランスをとる仕組み。そこでまずはArduinoでモーターを制御する。
モータードライバー
Arduinoでモーターを制御するためにモータードライバーを使う。なぜならArduinoから直接出力出来る電流は0V〜5Vのプラスの電流しか出力出来ない。つまり回転の強弱は制御出来るが、正転/逆転の切り替えが出来ない。これでは今回の使用目的には合わない。
そこでモータードライバーの出番。今回はTOSHIBAのTA7291Pを購入してみた。
このモータードライバーには2つの制御用入力が有り、それぞれのON/OFFを切り替える事によって正転/逆転/ストップ/ブレーキ用の電流を出力してくれる。また出力の強弱も付けられる。
LEDの代わりにモーターを動かす。
先のLチカのプログラムを少し改造して、LEDがONの時は正転、OFFの時は逆転するアプリを作成した。
配線はこんな感じ。
ソースは前回と同じくこちら github.com
上手く動かない
上記の構成でArduinoとAndroidをUSBで接続しADKアプリを起動すると、すぐにArduinoとAndroidの接続が切れてしまう。
ADKでLチカ
Arduino
これを購入した。
- 出版社/メーカー: GHEO SA
- メディア: エレクトロニクス
- この商品を含むブログを見る
Arduino Unoだと別途USBホストシールドが必要みたいなので、少々値が張るけどこちらを購入した。
ADK
ADKについてはyanzmさんのブログを参考にした。ただし、ソースは少し修正させてもらった。 y-anz-m.blogspot.jp
修正内容
ADKはAndroid 3.0から対応していて、それ以前のバージョンではバックポートされたadd-on libraryがあるのでそれを使用する必要がある。プラットフォームのAPIとadd-on libraryのAPIでは使い方が少々異なる。まずはUsbManager
の取得方法。
add-on libraryを使用する場合
UsbManager manager = UsbManager.getInstance(this);
プラットフォームAPIを使用する場合
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
また、UsbAccessory
の取得方法も異なる。
add-on libraryを使用する場合
UsbAccessory accessory = UsbManager.getAccessory(intent);
プラットフォームAPIを使用する場合
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
先のブログで紹介されているソースはadd-on libraryを使用するバージョンだったので、プラットフォームAPIバージョンに修正した。 ソースはGitHubにあげてみた。
動作の様子はこちら
プログラミングHaskell 第4章 関数定義
関数型プログラミング言語と言うだけあって、関数を定義する方法がいろいろある。
基本
-- 基本はこの形 関数名 引数 = 定義式 -- 例 isDigit :: Char -> Bool isDigit c = c >= '0' && c <= '9'
条件式
ifを使った式。
myAbs :: Int -> Int myAbs n = if n >= 0 then n else -n
- 入れ子に出来る。
then
の式とelse
の式は、同じ型でなければならない。else
は必須。
ガード
switch文に近い。上から順番に条件式を評価して、True
になった式の結果が適用される。
mySignum :: Int -> Int mySignum n | n < 0 = -1 | n == 0 = 0 | otherwise = 1
otherwise
は標準ライブラリ内でotherwise = True
と定義されている。switch文のdefaultとして使う。
(-1)?
mySignum -1
を試したら怒られた。
*Main> mySignum -1 <interactive>:353:10: No instance for (Num (Int -> Int)) (maybe you haven't applied enough arguments to a function?) arising from a use of ‘-’ In the expression: mySignum - 1 In an equation for ‘it’: it = mySignum - 1 *Main> mySignum (-1) -1
mySignum - 1
と解釈された?mySignum (-1)
で正しく動いた。
パターンマッチ
ガードに似ている。パターンと呼ばれる式とそれに対応する結果を列挙する。パターンを上から順に見ていって、合致するパターンの結果が採用される。
myAnd :: Bool -> Bool -> Bool True `myAnd` True = True True `myAnd` False = False False `myAnd` True = False False `myAnd` False = False -- パターンは上から順番に評価するから、ワイルドカード"_"を使うとこうも書ける。 True `myAnd` True = True _ `myAnd` _ = False -- 標準ライブラリではこの様に定義されているらしい。 -- 第1引数がFalseの場合、第2引数を評価する必要が無い。 True `myAnd` a = a False `myAnd` _ = False
タプル・パターン
要素がパターンであるタプルはパターンである。
myFst :: (a, b) -> a myFst (x, _) = x mySnd :: (a, b) -> b mySnd (_, x) = x
リスト・パターン
要素がパターンのリストはパターンである。
myTest :: [Char] -> Bool myTest ['a', _, _] = True myTest _ = False
String型は[Char]?
上のmyTestを実行してみた
*Main> myTest ['a', 'b', 'c'] True *Main> myTest ['a', 'b', 'c', 'd'] False *Main> myTest ['A', 'b', 'c'] False -- これでも同じ *Main> myTest "abc" True *Main> myTest "abcd" False *Main> myTest "Abc" False
文字列は[Char]型なの?
-- :tコマンドの結果 *Main> :t "hoge" "hoge" :: [Char] -- myTestの型宣言を変更してみたが、結果は同じ。 myTest :: String -> Bool myTest ['a', _, _] = True myTest _ = False *Main> myTest ['a', 'b', 'c'] True *Main> myTest ['a', 'b', 'c', 'd'] False *Main> myTest ['A', 'b', 'c'] False *Main> myTest "abc" True *Main> myTest "abcd" False *Main> myTest "Abc" False
同じだった。
*Main> :i String type String = [Char] -- Defined in ‘GHC.Base’
今回はここまで。
プログラミングHaskell 第3章 型とクラス
表題の通り型とクラスについて書かれていた。
何だかしっくりこない。簡単のために端折って書いているのか?以降の章を読めば理解できるのか?モヤモヤする。他の資料も参照してみる事にする。
特に3 :: Num a => a
のくだりがよくわからん。
練習問題の解答
1
['a', 'b', 'c'] :: [Char] ('a', 'b', 'c') :: (Char, Char, Char) [(False, '0'), (True, '1')] :: [(Bool, Char)] ([False, True], ['0', '1']) :: ([Bool], [Char]) [tail, init, reverse] :: [[a] -> [a]]
2
second :: [a] -> a swap :: (a, b) -> (b, a) pair :: a -> b -> (a, b) double :: Num a => a -> a -- 間違えた。リストの同等判定を行うので、Eqクラスの成約が必要だった。 -- 正解:palindrome :: Eq a => [a] -> Bool palindrome :: [a] -> Bool -- ここも間違えた。(f x)は再びfの引数になるので、f :: a -> aだった。 -- 正解:twice :: (a -> a) -> a -> a twice :: (a -> b) -> a -> b
3
-- 2の:tコマンドによる確認結果 *Main> :t ['a', 'b', 'c'] ['a', 'b', 'c'] :: [Char] *Main> :t ('a', 'b', 'c') ('a', 'b', 'c') :: (Char, Char, Char) *Main> :t [(False, '0'), (True, '1')] [(False, '0'), (True, '1')] :: [(Bool, Char)] *Main> :t ([False, True], ['0', '1']) ([False, True], ['0', '1']) :: ([Bool], [Char]) *Main> :t [tail, init, reverse] [tail, init, reverse] :: [[a] -> [a]] -- 2の:tコマンドによる確認結果 *Main> :t second second :: [a] -> a *Main> :t swap swap :: (t1, t) -> (t, t1) *Main> :t pair pair :: t -> t1 -> (t, t1) *Main> :t double double :: Num a => a -> a *Main> :t palindrome palindrome :: Eq a => [a] -> Bool *Main> :t twice twice :: (t -> t) -> t -> t
4
関数の同等性を検証するには、引数として取りうる全ての値に対して、関数を適用し結果が等しいか?を確認する必要があるから。これはとても面倒くさい。非現実的。
なので、適応結果が引数に依らない関数や、恒等関数idなら同等性の検証は実現可能。
プログラミングHaskell 第2章 はじめの一歩
リスト操作
takeとdropの第2引数は空リストでも良いらしい。
Prelude> take 3 [] [] Prelude> drop 3 [] []
なので、headとtake 1 とtailとdrop 1 は違う。
Prelude> head [] *** Exception: Prelude.head: empty list Prelude> take 1 [] [] Prelude> tail [] *** Exception: Prelude.tail: empty list Prelude> drop 1 [] []
他にどんな関数があるのかググってみたら、すんげ~たくさんあった。
https://downloads.haskell.org/~ghc/7.6-latest/docs/html/libraries/haskell98-2.0.0.2/List.html
だけど、知らない記号だらけで、中身はよくわからん。
xsの謎、解明
第1章で関数の定義に出てきた(x:xs)のxs。sって何だろう?と思っていたけど、複数形のsらしい。
Haskellでは慣習として、引数がリストである場合、名前の最後にsを付け、複数の値を表現できることを示す。たとえば、数値のリストはns、任意の値のリストはxs、そして文字のリストのリストはcssと名付けられるだろう。(2.4 Haskellプログラム 命名規則)
練習問題の解答
1
2^3*4 = (2^3)*4 2*3+4*5 = (2*3)+(4*5) 2+3*4^5 = 2+(3*(4^5))
2
ghciで実行した
3
- 関数名は小文字で始めなければならない。
- 関数名を括るのはシングルクォートではなくバッククォート。
- 同じレベルの定義は、行頭を揃えなければならない。
修正した定義
n = a `div` length xs where a = 10 xs = [1,2,3,4,5]
実行結果
Main> n 2
4
lastを定義したら、怒られた。GHC.Listにlastが既にある?
<interactive>:65:1: Ambiguous occurrence ‘last’ It could refer to either ‘Main.last’, defined at test.hs:9:1 or ‘Prelude.last’, imported from ‘Prelude’ at test.hs:1:1 (and originally defined in ‘GHC.List’)
myLastで定義した。
myLast1 xs = xs !! ((length xs) - 1) myLast2 [x] = x myLast2 (x:xs) = myLast2 xs myLast3 xs = head (drop ((length xs) - 1) xs) myLast4 xs = (drop ((length xs) - 1) xs) !! 0 myLast5 xs = head (reverse xs)
5
またまた怒られたので、myInitで定義した。
myInit1 xs = reverse (tail (reverse xs)) myInit2 [x] = [] myInit2 (x:xs) = [x] ++ (myInit2 xs) myInit3 xs = take ((length xs) - 1) xs
どうしても制御文が頭をよぎる。 (xs:x)って書けたら良いな。 whereを全然使ってなかった。