■ブログを移動しました

WordPress を使ってみようと、新たな meyon's STUDY http://meyon.gonna.jp/study/ を作って移動しました。


■BlynkでArduinoを制御する

Blynk というアプリを使ってスマホから Arduino を制御し、L チカしてみました。

 

本来はイーサネットシールドを利用してインターネットに接続するのだそうですが、今回は Arduino をパソコンに USB 接続した状態で制御させます。

参考にさせていただいたサイトは以下です。ありがとうございました。

 

裸のArduino UNOでBlynk

Arduino over USB (no shield)

 

 

1. Blynk アプリの設定

 

俺は Android なので、Play ストアから Blynk アプリをインストール。

起動したらまずアカウントを作成します。

次に新しいプロジェクトを作ります。デバイスは「Arduino Nano」、接続タイプは「USB」としておきます。プロジェクトを作るとアカウントのメールアドレスへトークンが送られてきます。このトークンが制御する Arduino を識別することになります。

ウィジェットからボタンを選択し、アウトプットを「Digital D13」、モードを「SWITCH」とします。

 

 

2. Arduino の設定

 

GitHUB から blynk-library-master.zip をダウンロードし、IDE の「.ZIP 形式のライブラリをインストール」で取り込みます。

サンプルスケッチは /Arduino/libraries/blynk-library-master/examples/Boards_USB_Serial/ にある「Arduino_Serial_USB」です。この中の「YourAuthToken」を送られてきたトークンに書き換えて、Arduino に書き込みます。

 

 

3. パソコンの設定

 

USB 接続で Arduino を制御するために blynk-ser.sh を起動させる必要があります。blynk-ser.sh は /Arduino/libraries/blynk-library-master/scripts にあります。

まずこれに実行権限を与えます。

 

$ chmod +x blynk-ser.sh

 

実行してみます。

 

$ ./blynk-ser.sh

This script uses socat utility, but could not find it.

  Try installing it using: sudo apt-get install socat

 

socat がないぞと叱られました。インストールしましょう。

 

$ sudo apt update

$ sudo apt install socat

 

もう一度 blynk-ser.sh を実行してみましょう。

 

$ ./blynk-ser.sh 
Resetting device /dev/ttyUSB0...
[ Press Ctrl+C to exit ]
Connecting: FILE:/dev/ttyUSB0, ........

        :

        :

 

この状態でスマホ側の Blynk アプリからプロジェクトを起動すると、ボタン操作で Arduino の内臓 LED を点滅することができました。

blynk-ser.sh は Ctrl+C で中断できます。Arduino のスケッチを修正する場合などは中断して、USB を開放する必要があります。

 

ほんとの基本的なものでしたが、スマホから制御できるようになると一段と IoT 機器らしくなってきますね。

 


■Arduino スケッチ例 / State Change Detection

Arduino スケッチ例「State Change Detection」です。押しボタンを押した回数を検出します。

 

TUTORIALS Built-In Examples > 02.Digital > StateChangeDetection

 

フローチャートを書いてみました。

詳細な解説はしませんが、ボタンの状態によって分岐する流れが赤線のようになっています。

 


画像キャプション

 

スケッチを書き込んで起動すると、最初は点灯します。ボタンを押すと消灯し、4回目の押下で再び点灯します。

このスケッチでは、チャタリング防止 (デバウンス) は delay(50) で行なっています。前回の「Debounce」のような方法との使い分けってどうすれば良いのでしょう? 暇なときにでも考えてみます (^_^;)

 


■Arduino スケッチ例 / Debounce

Arduino スケッチ例「Debounce」を試してみましょう。

 

TUTORIALS Built-In Examples > 02.Digital > Debounce

 

Debounce

Pushbuttons often generate spurious open/close transitions when pressed, due to mechanical and physical issues: these transitions may be read as multiple presses in a very short time fooling the program. This example demonstrates how to debounce an input, which means checking twice in a short period of time to make sure the pushbutton is definitely pressed. Without debouncing, pressing the button once may cause unpredictable results. This sketch uses the  millis()  function to keep track of the time passed since the button was pressed.

 

2番ピンに接続されたスイッチを押すたびに 内蔵 LED が点灯と消灯に切り替わるというものですが、この場合に問題となるスイッチのチャタリングを防止するためのスケッチ例です。

 

スケッチをパッと見てもどうなっているのかよくわかりませんでしたので、フローチャートを書いてみました。


画像キャプション

赤い部分がデバウンスを行なっています。

ボタンの状態が変化したことを検出したら lastDebounceTime をリセットし、debounceDelay (50ms) の間は LED 出力を変化させません。ボタンの状態が変化なく 50ms 経過したら LED の制御処理を実行しますが、変化があったときは再び lastDebounceTime をリセットし、変化がなくなるのを待っています。

こうしてデバウンス部分を分けてみると、とても単純な処理をしていることがわかりますね。

 

ちなみに、このスケッチ例では ledState を反転させるために「!」でブーリアン値の否定を利用しています。俺の好きな XOR によるビット操作 ledState ^= 1 よりわかりやすいです (^_^;)

 


■Arduino スケッチ例 / Blink Without Delay

Arduino のスケッチ例「Blink Without Delay」を試してみます。

 

TUTORIALS Built-In Examples > 02.Digital > BlinkWithoutDelay

 

回路図では外部に LED を接続するようになっていますが、内蔵 LED を点滅させるので必要はありません。スケッチ例をそのまま IDE にコピーアンドペーストし、Arduino へ書き込めば完成ですね。

スケッチ例はコメントが多くて見にくいので、必要な部分だけ抜き出してみました。

 

  1. const int ledPin = LED_BUILTIN;
  2. int ledState = LOW;
  3. unsigned long previousMillis = 0;
  4. const long interval = 1000;
  5. void setup() {
  6.   pinMode(ledPin, OUTPUT);
  7. }
  8. void loop() {
  9.   unsigned long currentMillis = millis();
  10.   if (currentMillis - previousMillis >= interval) {
  11.     previousMillis = currentMillis;
  12.     if (ledState == LOW) {
  13.       ledState = HIGH;
  14.     } else {
  15.       ledState = LOW;
  16.     }
  17.     digitalWrite(ledPin, ledState);
  18.   }
  19. }

 

delay を使わずに、millis() でインターバル時間を超えたかどうかをチェックする方法ですね。

俺が気になったのは、LED の点滅のために ledState を反転させる部分 (16〜20行) です。if() で判定するのはとってもわかりやすいですが、別の方法に変更してみましょう。

 

  1.     ledState = ~ledState;

 

ledState を NOT 演算で反転させてみました。この場合は LOW=0 、HIGH=-1 となります。ビットがすべて反転しているということ。LED の点滅は正常に行われていますので、たぶん 1 ビット目の値で制御しているのでしょう。

 

NOT はビット単位の否定ですが、次の例はブーリアン値で反転させます。

 

  1.     ledState = !ledState;

 

出力は 0 と 1 になりました。この場合は、変数をブール型にして値は true - false とするべきなのでしょうね。

 

次の例は、1 ビット目だけを反転させる方法です。XOR 演算でビット操作しています。

 

  1.     ledState = ledState^1;

 

これは複合演算子を使って、

 

  1.     ledState ^= 1;

 

のように書くことができます。個人的にはこの方法が好きですが、理論的にどれがよいのかは、俺にはわかりません (^_^;)

 


■linuxBean 16.04 / Pythonを最新バージョンにアップデート

最近 Python の学習を linuxBean 上でするようになっているので、Python を最新バージョンにアップデートしようと思います。

参考にさせていただいたサイトは「ubuntu 環境の Python」です。

linuxBean 16.04 に入っている Python のバージョンは、2系が 2.7.12 、3系が 3.5.2 です。最新バージョンは 3.7.4 で、これをインストールしてみましょう。

 

 

1. ビルドツール・ライブラリのインストール

 

$ sudo apt update
$ sudo apt install build-essential libbz2-dev libdb-dev ¥
  libreadline-dev libffi-dev libgdbm-dev liblzma-dev ¥
  libncursesw5-dev libsqlite3-dev libssl-dev ¥
  zlib1g-dev uuid-dev tk-dev

 

必要なツールとライブラリの準備です。個々の内容はわかりません (^_^;) build-essential はインストール済みだと思うけど、まぁコピー&ペーストでそのまま実行です。

GUI では、synaptic パッケージマネージャからインストールできると思います。

 

 

2. ソースコードのダウンロード

 

Gzipped source tarball から Python-3.7.4.tgz をダウンロードし、展開します。

 

$ tar xzf Python-3.7.2.tgz

 

コマンドでもいいんですが、ブラウザでダウンロードしたらダウンロードフォルダを開いて、アーカイブマネージャで展開するのが簡単ですよ。展開してできたフォルダ Python-3.7.4 に入ったら、「現在のフォルダを端末で開く」すれば次のコマンドの「cd Python-3.7.4」まで完了です。

 

 

3. ビルド

 

ビルドとインストールはコマンドで。

 

$ cd Python-3.7.4
$ ./configure --enable-shared
$ make
$ sudo make install
$ sudo sh -c "echo '/usr/local/lib' > /etc/ld.so.conf.d/custom_python3.conf"
$ sudo ldconfig

 

バージョンの確認は以下です。

 

$ python3 --version
Python 3.7.4

 

ということで、無事 3.7.4 にアップデートできました。

 


■Arduino / ubuntuとシリアル通信してみた -3-

シリアル通信を通してパソコンから Arduino へ数値を送りたいという話。

 

送られてくるのは文字列なので、そいつを数値に変換するためにいろいろ細工が必要になる。でもきっと何か、もっと簡単な方法があるはずだと思っていたわけですが、なんと、あるじゃないですか、数値をそのまま取り出してくれる関数が。

 

parseInt()

Description

parseInt() returns the first valid (long) integer number from the serial buffer. Characters that are not integers (or the minus sign) are skipped.

 

しかも附属のスケッチ例にこんなのがあります。

 

Read ASCII String

This sketch uses the Serial.parseInt() function to locate values separated by a non-alphanumeric character. Often people use a comma to indicate different pieces of information (this format is commonly referred to as comma-separated-values or CSV), but other characters like a space or a period will work too. The values are parsed into integers and used to determine the color of a RGB LED. You'll use the Arduino Software (IDE) serial monitor to send strings like "5,220,70" to the board to change the light color.

 

 

  1. /*
  2.   Reading a serial ASCII-encoded string.
  3.   This sketch demonstrates the Serial parseInt() function.
  4.   It looks for an ASCII string of comma-separated values.
  5.   It parses them into ints, and uses those to fade an RGB LED.
  6.   Circuit: Common-Cathode RGB LED wired like so:
  7.   - red anode: digital pin 3
  8.   - green anode: digital pin 5
  9.   - blue anode: digital pin 6
  10.   - cathode: GND
  11.   created 13 Apr 2012
  12.   by Tom Igoe
  13.   modified 14 Mar 2016
  14.   by Arturo Guadalupi
  15.   This example code is in the public domain.
  16. */
  17. // pins for the LEDs:
  18. const int redPin = 3;
  19. const int greenPin = 5;
  20. const int bluePin = 6;
  21. void setup() {
  22.   // initialize serial:
  23.   Serial.begin(9600);
  24.   // make the pins outputs:
  25.   pinMode(redPin, OUTPUT);
  26.   pinMode(greenPin, OUTPUT);
  27.   pinMode(bluePin, OUTPUT);
  28. }
  29. void loop() {
  30.   // if there's any serial available, read it:
  31.   while (Serial.available() > 0) {
  32.     // look for the next valid integer in the incoming serial stream:
  33.     int red = Serial.parseInt();
  34.     // do it again:
  35.     int green = Serial.parseInt();
  36.     // do it again:
  37.     int blue = Serial.parseInt();
  38.     // look for the newline. That's the end of your sentence:
  39.     if (Serial.read() == '¥n') {
  40.       // constrain the values to 0 - 255 and invert
  41.       // if you're using a common-cathode LED, just use "constrain(color, 0, 255);"
  42.       red = 255 - constrain(red, 0, 255);
  43.       green = 255 - constrain(green, 0, 255);
  44.       blue = 255 - constrain(blue, 0, 255);
  45.       // fade the red, green, and blue legs of the LED:
  46.       analogWrite(redPin, red);
  47.       analogWrite(greenPin, green);
  48.       analogWrite(bluePin, blue);
  49.       // print the three numbers in one string as hexadecimal:
  50.       Serial.print(red, HEX);
  51.       Serial.print(green, HEX);
  52.       Serial.println(blue, HEX);
  53.     }
  54.   }
  55. }

 

スケッチ例ではカラー LED を使用していますが、点灯を試すだけなら 3個の LED を使えばいいです。シリアルモニターから 3つの数値をカンマ区切りで送信すると、その値に応じた色 (明るさ) で LED が点灯します。

シリアルポートから送られてくるデータが文字列だの数値だの考えなくても、そのまま数値として出力できました。

 

なお、Serial.parseInt() はタイムアウトで終了しますので、cu のように入力した数値を即送信してしまう場合は、タイムアウトするまでにすべてのデータを送信する必要があります。シリアルモニターのようにデータをまとめて送信するものであれば問題はないです。

プログラムからなら、データをまとめて最後に改行コードをつけて送信すればよいので、なんとでもなると思います。

 

ということで、シリアル通信で数値を送ることも難しく考える必要なんてないことがわかりました。やっぱりなぁ、日本語リファレンスだけじゃなくて、ちゃんと REFERENCE を読まないといけないんだよなぁ (^_^;)

 


■Arduino / ubuntuとシリアル通信してみた -2-

Arduino / ubuntuとシリアル通信してみた」で試してみたターミナルコマンド cu による LED の PWM 制御を、少し改良してみました。

前回は数字を 3つ入力すると LED の明るさが変わるというものでした。これを 0 から 255 までの数字を入力して Enter を押すと、その値に従って LED の明るさを変えるようにしたいと思います。

そのために、桁数の異なる数字をシリアル通信で Arduino に送り、数値として PWM 制御に渡す必要があります。少しググってみたのですが、シリアル通信で数値を送るには、文字列を数値に替えるだけでなく、桁数の違いをどう処理するかなど、けっこう面倒な雰囲気です。単純な処理なのでもっと簡単な方法がないかなと探していたところ、こんなチュートリアルを見つけました。

 

String to Int Function

The toInt() function allows you to convert a String to an integer number.

In this example, the board reads a serial input string until it sees a newline, then converts the string to a number if the characters are digits. 

 

ドンピシャです。文字列を数値に変換する、まさに求めていた内容ですよ。

toInt() は String オブジェクトの関数です… よくわかりません (^_^;) でもこうやって使うとこういう結果が出るということは、簡単に理解できます。なお、このチュートリアルにあるサンプルコードは、IDE のスケッチ例「08.String」に「StringToint」として附属しています。

 

さて、そのサンプルコードを参考にした、cu から送信するデータに従って 3番ピンに接続した LED を PWM 制御するスケッチです。

 

  1. // PWM control LED from cu 2019/09/09 meyon
  2. const int ledPin = 3;
  3. String inStr = "";
  4. void setup()
  5. {
  6.   pinMode(ledPin, OUTPUT);
  7.   Serial.begin(9600);
  8. }
  9. void loop()
  10. {
  11.   while(0 < Serial.available()) {
  12.     int inChar = Serial.read();
  13.     Serial.write(inChar);
  14.     if(isDigit(inChar)) {
  15.       inStr += (char)inChar;
  16.     }
  17.     if(13 == inChar) {
  18.       int ledBri = inStr.toInt();
  19.       ledBri = constrain(ledBri, 0, 255);
  20.       analogWrite(ledPin, ledBri);
  21.       Serial.print("¥nBrightness: ");
  22.       Serial.println(ledBri);
  23.       inStr = "";
  24.     }
  25.   }
  26. }

 

16行目は cu へのエコーです。Serial.write() はデータを byte 型で出力するので、受け取った数字の ASCII コードをそのまま cu へ送り返し、入力した数字を表示させることができます。

18行目で入力データが数字かどうかを判断し、数字なら文字列として inStr に追加していきます。

22〜25行目。入力データが Enter の場合 ASCII コード (13) が届きますので、それまでに届いた文字列を数値に変換して 3番ピンへアナログ出力します。

数値は 0〜255 の範囲に制限し、256 以上の場合は 255 としています。int 型なので 32767 を超えると出力は 0 になってしまいますね。また、入力に数字以外が含まれていると無視されます。数字だけを抽出して制御値になります。

 

これでかなりエクセレントになった気がします (^_^;)

 


■Arduino / ubuntuとシリアル通信してみた

ubuntu と Arduino 間でシリアル通信してみます。

ubuntu では cu コマンドを利用します。まずはインストール。

 

$ sudo apt install cu

 

起動・接続は以下。切断・終了は「~.」ですが、Arduino で受信したデータを送り返すスケッチを動かしていると ~. も折り返されてくるだけで終了できません (^_^;) 正しい方法かどうかわからないのですが、Ctrl+c 押した後に ~. で終了できました。

 

$ cu -s 9600 -l /dev/ttyACM0

 

シリアルモニタとは動作が異なります。

シリアルモニタでは入力した文字列が「送信」ボタンを押すことで一括して送られましたが、cu では入力ごとに即送信され、たとえば「A」キーを押すとすぐに「65」が返ってきます。

 

そこで、数字を 3つ入力するとその値で LED の明るさを制御するようなスケッチを書いてみました。

LED は 3番ピンに繋ぎますが、最大で 20mA 程度流しますので LED 駆動用にトランジスタを 1個入れてます。まぁ毎度の回路です。電源は USB を刺しているので、Arduino の 5V 出力を利用しました。

 

  1. const int ledPin=3;
  2. void setup() {
  3.   pinMode(ledPin, OUTPUT);
  4.   Serial.begin(9600);
  5. }
  6. void loop() {
  7.   while(0 < Serial.available()) {
  8.     int data = Serial.read();
  9.     Serial.println(data);
  10.   
  11.     static int val[3];
  12.     static int i=0;
  13.     val[i]=data-48;
  14.     i++;
  15.     if(2<i) {
  16.       int bri = val[0]*100+val[1]*10+val[2];
  17.       bri = constrain(bri, 0, 255);
  18.       Serial.print("Brightness: ");
  19.       Serial.println(bri);
  20.       analogWrite(ledPin, bri);
  21.       i=0;
  22.     }
  23.   }
  24. }

 

Arduino へ書き込んだら IDE を終了します。

cu を起動し接続。数字を 3つ押すごとに LED への出力が変化します。「255」 と押すと LED が 100% で点灯します。「128」なら 50% 、「000」で消灯です。入力値が 255 を超える場合は 255 にしますが、contrain() なんて便利な関数があったので使ってみました。

受信したデータは 48 を引くことで数値に変換しています。3つデータを受けたら 3桁の数字に計算しているだけですが、このあたりがどうもエクセレントじゃないですよねぇ (^_^;)

 


■Arduino シリアル通信 Serial.read() を試してみる

Arduino シリアル通信 Serial.print() を試してみる」で、Arduino からシリアルモニタへデータを送るときはすべて文字列として扱っていることがわかりました。文字は ASCII コードとしてシリアルポートへ送られ、シリアルモニタ側では受け取った ASCII コードに対応した文字を表示しています。

 

では、シリアルモニタから Arduino へ送信する場合はどうでしょうか。簡単なスケッチで試してみます。

 

  1. void setup() { 
  2.   Serial.begin(9600); 
  3. void loop() { 
  4.   if(Serial.available() > 0) { 
  5.     int data = Serial.read(); 
  6.     Serial.println(data, DEC); 
  7.   } 

 

シリアルモニタから「A」と送信すると、

 

65
10

 

と表示されました。

シリアルモニタ側で「A」と入力すると、文字「A」の ASCII コード (65) がシリアルポートへ送られるはずです。

Arduino 側では、Serial.read() で読み取ったデータを数値変数 data に代入し、Serial.println() で 10 進数のフォーマットで出力しています。そこで表示されたのが「65」ということは、Serial.read() がシリアルポートから送られてきた ASCII コードそのものを読み取っている、ということです。

 次に表示されている「10」は、シリアルモニタから送信されるときに付加された改行コード LF のASCII コードです。シリアルモニタでは、入力されたデータは「送信」ボタンを押したときに改行コードを付加してまとめて送出されています。

 

ということはですよ、入力した文字をそのまま表示させるには、読み取った ASCII コードを文字に変換すればいいんじゃないですか?

 

  1.     char data = Serial.read();
  2.     Serial.println(data);

 

スケッチの一部を上のように書き換えます。シリアルモニタで「A」と入力すると、

 

A

 

と出力されました。ASCII コード (65) を文字変数 data に代入すると、その中身は文字「A」となりますね。そーゆーことです (^_^;)

ところで、「ABC」と入力するとどうなりますか?

 

A
B
C

 

となってしまいます。スケッチをちょっと工夫しましょう。

 

  1. void loop() {
  2.   if(Serial.available() > 0) {
  3.     char data = Serial.read();
  4.     if(10 == data) {
  5.       data = '¥n';
  6.     }
  7.     Serial.print(data);
  8.   }
  9. }

 

末尾に改行コード LF がついてくるのですから、LF のときだけ改行するようにしました。これで出力は、

 

ABC

 

となりました。

 

  1. Arduino → シリアルモニタでは、データは文字列としてそのまま送信される。
  2. シリアルモニタ → Arduino では、データは文字列として送られ、Serial.read() は文字の ASCII コードを読み取る。

 

これでシリアル通信の状況がわかりました。わかってしまえば、まぁなんてことないですよねぇ (^_^;) たぶん、ね。

 


| 1/61PAGES | >>

■calendar

S M T W T F S
     12
3456789
10111213141516
17181920212223
24252627282930
<< November 2019 >>

■search this site.

■recommend

毎日貯まるポイントサイト ECナビ

■recommend

* 楽天ROOM *

■Twitter

■recommend

■recommend

■selected entries

■categories

■archives

■recent comment

■recent trackback

■links

■profile

■others

■mobile

qrcode

■powered

無料ブログ作成サービス JUGEM