[[Arduino勉強会]]

#contents

2015/12/24からのアクセス回数 &counter;



[[「8pino」ではじめるミニマム電子工作>https://www.kohgakusha.co.jp/books/detail/978-4-7775-1915-6]]
(以下ミニマム本と書きます)に触発されて、ブレッドボードで作るATtiny85を使ったワンコインArduinoで
電子工作を楽しんでみました。


例題の多くは、ミニマム本を参考にさせて頂き、これをlbedライブラリを使ってmbed風に書き替えています。


** ちょっと軽めのmbedライクなライブラリlbed [#m7269653]
mbedはとても使い易いライブラリを提供していますが、mbedが提供されていないボードやArduinoなどで、
mbed風のプログラミングを楽しんでもらうために、lbedライブラリを作成しました。



今回は、ブレッドボードで作るATtiny85を使ったワンコインArduino(lbedGemmaと呼びます)
を使ってmbed風のプログラミングを体験してみましょう。


lbedGemmaの作り方は、
[[Arduino勉強会/16-ワンコイン・マイコンlbedGemma]]
を参照してください。




*** 開発環境のインストール [#keb3f9fc]
Arduino IDE 1.6.xを以下のURLからダウンロードし、インストールしてください。
- https://www.arduino.cc/en/Main/Software



lbedGemmaとTinyWireMは、以下のURLからダウンロードできますが、

- TinyWireM: https://github.com/adafruit/TinyWireM
- lbedGemma:  https://github.com/take-pwave/lbed

以下にTinyWireMとlbedGemmaをまとめましたので、こちらをダウンロードし、
展開したTinyWireM, lbedGemma, lbedGemmaUserをユーザのホームディレクトリ/書類/Arduino/libraries
に入れてください。

- &ref(lbedGemma.zip);

** デジタル入力 [#k1dcf1a1]
*** プルダウン抵抗を使ったスイッチ回路 [#x73f484b]
デジタル入力はスイッチのオン・オフのように0と1だけを入力値とします。
以下の様なスイッチをもちいた回路をlbedGemmaで作ってみましょう。

&ref(SwitchButton_sch.png);

VCCは、電池のプラスを表しlbedGemmaではUSBからの5Vに相当します。その下にタクトスイッチSWが接続され、
10KΩの抵抗を通り、GND(電池のマイナス)につながっています。途中Switchというピンがタクトスイッチと抵抗の間につながれています。


この抵抗のあることで、スイッチが押されたときに電源のプラスとマイナスが直結し、ショートすることを防いでくれます。
この抵抗はスイッチがオフの時に、Switchピンの電圧をマイナス付近に落としてくれるので、プルダウン抵抗と呼ばれています。


この回路をlbedGemmaのブレッドボードに追加してみます。


&ref(SwitchButton-pullDown_brd.png);







*** Arduinoでスケッチを書く [#lad963aa]
「8pinoではじめるミニマム電子工作」のスイッチ・ボタンのスケッチでは、
以下の様に書いています。

#pre{{
int led_pin = 1;  // GPIO # LED on board
int sw_pin = 2;  // GPIO #2

void setup() {
  pinMode(led_pin, OUTPUT);
  pinMode(sw_pin, INPUT);
}

void loop() {
  if (digitalRead(sw_pin) == HIGH) {
    digitalWrite(led_pin, HIGH);
    delay(250);
    digitalWrite(led_pin, LOW);
    delay(250);
  }
}
}}

*** lbedを使ってスケッチを書く [#y7fd645a]
上記のスケッチをlbedを使ったスケッチは以下の様に入力します。
最初の#includeはこれから、TinyWireMとlbedGemmaというライブラリを使うことを
表します。((今回はTinyWireMは直接使うことはありませんが、この2つをセットで宣言するようにしてください))

DigitalOutは、デジタル出力のクラス名で、led(1)は1番ピンをデジタル出力するledという変数を宣言しています。
DigitalInは、デジタル入力のクラス名で、sw(2)は2番ピンをデジタル入力するswという変数を宣言しています。

setup関数では特に処理を行いません。

loop関数では、swがHIGHの時にledにHIGHをセットし、250ミリ秒待ち、
ledにLOWをセットし、250ミリ秒待つように処理します。
これで、スイッチが押されている間、LEDが250ミリ秒間隔で点灯と消灯を繰り返します。


mbed風の変数を参照するとピンから値が読まれ、変数に代入するとピンに値が書き込まれる
書き方の方が直感的で分かりやすいと思うのです。

#pre{{
#include "TinyWireM.h"
#include "lbedGemma.h"
 
DigitalOut  led(1);  // GPIO #1 LED on board.
DigitalIn   sw(2);   // GPIO #2

void setup() {                
}

void loop() {
  if (sw == HIGH) {
    led = HIGH;
    wait_ms(250);
    led = LOW;
    wait_ms(250);
  }
}
}}

実際にブレッドボードでこのスケッチを動かしてみましょう。

スイッチを押すと電源のプラスとSwitchピン2番が接続され、swの値がHIGHになるので、
if文の中の処理が実行され、LEDが点滅します。

&ref(SwitchButton.png);





*** プルアップ抵抗を使ったスイッチ回路 [#p7d71b6e]
次に、以下の様な抵抗を電池のプラス側につないだスイッチ回路を作ってみましょう。

&ref(SwitchButton-pullUp_sch.png);




ブレッドボードでは、マイナスにつながっていた抵抗をプラス(赤い線)につなぎ、
スイッチのプラスにつながっていた線をマイナスにつなぎます。

&ref(SwitchButton-pullUp_brd.png);





スケッチは、スイッチが押されたときにGND(電池のマイナス)につながるので、
if文のHIGHからLOWに変更します。
これで、先ほどと同じ動作をします。

#pre{{
#include "TinyWireM.h"
#include "lbedGemma.h"
 
DigitalOut  led(1);  // GPIO #1 LED on board.
DigitalIn   sw(2);   // GPIO #2

void setup() {                
}

void loop() {
  if (sw == LOW) {
    led = HIGH;
    wait_ms(250);
    led = LOW;
    wait_ms(250);
  }
}
}}

*** 抵抗を使わないスイッチ回路 [#lc6c078e]
スイッチを追加するたびに抵抗をつなぐと部品点数が増えるので、
Arduinoなどの最近のマイコンにはデジタル入力端子にプルアップ抵抗を内部で付けてくれる
機能があります。

この機能を使うと回路は以下の様にとても簡単になります。

&ref(SwitchButton_sch.png);

ブレッドボードも抵抗を外します。

&ref(SwitchButton_brd.png);



デジタル入力ピンにプルアップ抵抗をセットするには、
setup関数内で、swのmodeをINPUT_PULLUPにセットします。

#pre{{
#include "TinyWireM.h"
#include "lbedGemma.h"
 
DigitalOut  led(1);  // GPIO #1 LED on board.
DigitalIn   sw(2);   // GPIO #2

void setup() {
  sw.mode(INPUT_PULLUP);
}

void loop() {
  if (sw == LOW) {
    led = HIGH;
    wait_ms(250);
    led = LOW;
    wait_ms(250);
  }
}
}}

実際に動かしてみましょう。

&ref(SwitchButton.png);



もし、modeでPULL_UPの設定をしなかったらどうなるのでしょう。
setupのmodeの設定部分を//でコメントアウトして動かしてみてください。
スイッチを押さなくても点滅しますね。


これはスイッチ端子の電圧が不定となりスイッチを押していなくてもLOWに近い値になっているからです。


** アナログ出力(PWM) [#l3aed98e]
Arduinoでは電圧を変えるアナログ出力機能はありません。その代わりに一定の周期のパルス幅の割合(デューティ比)
を変えるパルス幅変調方式を使ってアナログ出力を行っています。

Wikiの[[デューティ比>https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E6%AF%94]]
からデューティ比の説明図を引用します。

デューティ比が大きいと電圧が掛かっている時間が長く、
デューティ比が小さいと電圧が掛かっている時間が短くなります。
これで、LEDやモータに流れる電流の量を調整することで、明るさや回転の強さをコントロールしています。
また、抵抗とコンデンサーを使った低周波フィルターを通すとデューティ比の変化が波の形で出力します。

&ref(https://upload.wikimedia.org/wikipedia/commons/3/34/Dutycycle.png,30%);

ATtiny85でPWMが使えるのは、3番ピンの#4、5番ピンの#0、6番ピンの#1の3つです。

PWMの回路は、以下の様にします。

&ref(PWMOut_sch.png);



LED出力には、5番ピンの#0を使用します。抵抗値は470Ωにしました。

&ref(PWMOut_brd.png);

lbedのPWMOutクラスを使ったスケッチを以下に示します。

PwmOutはのクラス名で、led(1)で1番ピンにアナログ出力(PWM)するledという変数を宣言しています。
ledへの代入する値は、デューティ比を実数で与えます。とてもすっきりしたスケッチになります。

#pre{{
#include "TinyWireM.h"
#include "lbedGemma.h"
 
PwmOut led(0); // PWM LED

void setup() {  
}

void loop() {
  for (led = 0.0; led < 1.0; led = led + 0.02)
    wait_ms(20);
  for (led = 1.0; led > 0.0; led = led - 0.02)
    wait_ms(20);
}
}}

電子工作の回路をみるとLEDにつなぐ抵抗の値が330Ωだったり、今回のように470Ωだったりしますが、
この値はどのようにして決めるのでしょうか。

LEDの場合、どの程度の電流を流すかによって抵抗の値が変わります。
LEDに流す電流はデータシート呼ばれる部品の規格を説明した資料で調べます。


秋月のサイトから赤色LED(OSDR3133A)をみると、
[[「抵抗の計算方法>http://akizukidenshi.com/download/led-r-calc.pdf]]
があります。これに沿って説明します。

赤色LEDの順方向電圧(VF)は、2.0Vであり、LEDに電流が流れたときに電圧が2.0V下がることを意味しています。
順方向電流IF(DC Forward Current)30mAとあります。



通常LEDの電流はIFの半分以下の10mA程度で使うのがよいとされおり、
最近のLEDは輝度も高いので5mA程度でも十分と思われます。


470Ωでは、抵抗による電圧降下はオームの法則から抵抗×電流ですから、
以下の等式から電流は6.3mAと求まります。


$$
5V = 2.0 + 470 \times 6.3mA
$$

スケッチを実際に動かしてみましょう。LEDの明るさが、もわもわっと変わります。

&ref(PWMOut.png);


** シリアル通信 [#jc61e8d8]
シリアル通信には、UART(調歩同期方式)方式が使われています。
UARTでは、送信(TX or TDX)と受信(RX or RDX)と呼ばれる2本の信号線を使って、
双方向に通信します。


UARTのつなぎ方は特徴的でPC側のTXとArduino側のRX、PC側のRXとArduino側のTX
を接続します。


*** USBシリアル変換モジュール [#sc0b71ab]
Arduinoとのシリアル通信には、5Vと3.3Vのどちらでも使える
[[https://www.switch-science.com/catalog/1032/]]
が便利です。
アマゾンで検索すると、同じ機能のモジュールがワンコイン程度であります。
((通信チップがFT232RLのものを使ってください))

- http://www.amazon.co.jp/dp/B00YMDN2Z6/

&ref(http://ecx.images-amazon.com/images/I/71QK0doXcNL._SL1001_.jpg,25%);




USBシリアル変換モジュールとATtiny85(Gemma)をつないだ回路を作ります。


&ref(USBSerial_sch.png);




これをブレッドボードで組み立てると以下の様になります。

&ref(USBSerial_brd.png);





*** スケッチを書く [#y5566616]
ミニマム本に習って、Arduino IDEのシリアルモニターから数値を入力し、その回数分
LEDを点滅させる例題を作ってみましょう。


ATtiny85にはシリアル通式の機能がないので、ArduinoのSoftwareSerialクラスを使って、
ソフトウェアでシリアル通信を処理します。

- #include "SoftwareSerial.h"は、これからSoftwareSerialを使うことを宣言しています
- SoftwareSerial pc(4,3)は、RXに#4、TXに#3を使ってシリアル通信を行うpc変数を宣言しています
- pc.begin(4800) で通信速度を4800ボー(かなり遅い)にセットします
- pc.available()は、PCからデータ送られているか確認します
- pc.read()は、PCから1バイトのデータを読み込みます
- pc.write()は、PCに1バイトのデータを送ります
- value = recv_value - '0'は、読み込んだでーたrecv_valueの値(ASCIIコード)から数値に変えています


#pre{{
#include "TinyWireM.h"
#include "lbedGemma.h"
#include "SoftwareSerial.h"
 
DigitalOut led(1); // Gemmaに付属のLED
SoftwareSerial pc(4, 3);  // RX=4, TX=3

void setup() {  
  pc.begin(4800);
}

void loop() {
  if (pc.available()) {
    // PCから受信した値
    int recv_value = pc.read();
    // PCにそのまま送信
    pc.write(recv_value);
    // 数字'0'〜'9'を数値の0〜9に変える
    int value = recv_value - '0';
    if (0 < value && value <= 9) {
      for (int i = 0; i < value; i++) {
        led = HIGH;
        wait_ms(250);
        led = LOW;
        wait_ms(250);
      }
    }
  }
}

}}



*** 動作確認 [#s7d0d290]
電源は、USBシリアルモジュールから取りますので、スケッチを書き込む時にはUSBシリアルを外しておいて、
書き込みが終わったら、lbedGemmaのUSBケーブルを外し、USBシリアルモジュールに付け直してください。

&ref(USBSerial.png);



Arduino IDEのシリアルモニターを起動し、ボーレートを4800baud、改行なしにセットして、
数字を入力して「送信」ボタンをおしてみてください。

数値がシリアルモニターにエコーバックされ、数値の回数だけLEDが点滅します。

&ref(USBSerial_monitor.png);

** まだ途中ですが公開します。 [#u9a5afa2]


** コメント [#lf637d77]
#vote(おもしろかった[0],そうでもない[0],わかりずらい[0])


皆様のご意見、ご希望をお待ちしております。勉強会で分からなかったこと等、お気軽に問い合わせて下さい。

スパム防止に画像の文字列も入力してください。
- アナログ出力を追加しました。 -- [[竹本 浩]] &new{2015-12-26 (土) 15:00:42};

#comment_kcaptcha

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc