できたらいいなAndroidアプリ

Androidに限らずいろいろ書いていく。

ADKでモーターを制御する。(失敗の原因)

前回、ArduinoAndroidの接続がすぐに切れてしまうという不具合があった。 とりあえず接続は切れなくなったので記録しておく。

モーターの消費電力

前回の構成では、モーターの駆動用電源はArduinoの3.3V出力ピンから取って、モータードライバーTA7291Pの8番ピンに接続していた。しかし、Arduinoのドキュメントをみると、3.3V出力ピンの最大電流は50mAとある。

store.arduino.cc

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を購入してみた。

toshiba.semicon-storage.com

このモータードライバーには2つの制御用入力が有り、それぞれのON/OFFを切り替える事によって正転/逆転/ストップ/ブレーキ用の電流を出力してくれる。また出力の強弱も付けられる。

LEDの代わりにモーターを動かす。

先のLチカのプログラムを少し改造して、LEDがONの時は正転、OFFの時は逆転するアプリを作成した。

配線はこんな感じ。 f:id:u_sub:20180317125940p:plain

ソースは前回と同じくこちら github.com

上手く動かない

上記の構成でArduinoAndroidをUSBで接続しADKアプリを起動すると、すぐにArduinoAndroidの接続が切れてしまう。

ADKでLチカ

ArduinoのLEDをAndroidから操作する。

Arduino

これを購入した。

Arduino ADK Rev3

Arduino ADK Rev3

Arduino Unoだと別途USBホストシールドが必要みたいなので、少々値が張るけどこちらを購入した。

ADK

ADKについてはyanzmさんのブログを参考にした。ただし、ソースは少し修正させてもらった。 y-anz-m.blogspot.jp

修正内容

ADKAndroid 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にあげてみた。

github.com

動作の様子はこちら


AndroidとArduinoをADKで接続してLチカ

自立型充電スタンド作る

これの続き。 nyandroid.hatenablog.com

モーターで重りを回して、その反動でバランスをとる自立ロボットを作る。

仕組みと構成はこんな感じ

  • AndroidArduinoADKでつなぐ。
  • Arduinoに接続したモーターをAndroidから制御する。
  • ロボットの傾きや加速度はAndroidのセンサーで取得する。
  • Androidはセンサーで取得した値からバランスを取るのに必要なモーターの動きを計算する。

ADKAndroid側がホストになるらしいので、Androidへ給電される。そこで、タイトルにある通り自立型の充電スタンドを作る事にした。

まずは、AndroidArduinoADKでつなげてLチカをやってみる。

プログラミング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を全然使ってなかった。