ATtiny13a (AVR) に Arduino 経由でコードを書き込み、サーボモーターを動かす(MicroCore使用)

(2023年8月時点の情報です。以後はもっと楽な方法があるかもしれません)

# ATtiny13a について
電子部品の通販でメジャーな秋月電子で __150円で売っているマイコン(※)__ です。(2023年8月27日現在)。
これで、色んな電子部品 (LED、サーボモーター、各種スイッチ・センサ、などなど) を激安でたくさん使うことができます。

__※__ 他にも PIC や RL78 などもありますが、プログラミングのしやすさから、今回は AVR (ATtiny13a) を使っています。

初心者には micro:bit など、比較的プログラミングがしやすいマイコン (マイコンボード) がありますし、基本的にはそちらがオススメなのですが、、、

数個・数十個を量産したり、作ったものをそのまま使えるままの状態で保管する (=作った後に分解してマイコンボードを在庫に戻さない) とすると、予算の都合が出てくると思います。そこで ATtiny13a の出番になるかと思います。

## ATtiny13a とその仲間のスペック
詳細は、秋月電子のそれぞれの商品ページを探してみてもらいたいのですが、ざっくりまとめると

* [ATtiny13a](https://akizukidenshi.com/catalog/g/gI-02911/)・・・8ピン / 150円 / [MicroCore](https://github.com/MCUdude/MicroCore) を組み合わせて使用
* [ATtiny44a](https://akizukidenshi.com/catalog/g/gI-16466/)・・・14ピン / 190円 / [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) を組み合わせて使用
* [ATMEGA8](https://akizukidenshi.com/catalog/g/gI-02868/)・・・28ピン / 180円 / [MiniCore](https://github.com/MCUdude/MiniCore) を組み合わせて使用

あたりが秋月電子で買える格安のAVRマイコンです (2023年8月27日時点の価格)

## MicroCore について
* 「MicroCore」(MCUdude氏作) は、Arduino IDE で作ったコードを、150円程度で買えるマイコン ATtiny13a に書き込むためのプラグインのようなもの(正確には「ハードウェアパッケージ」）です。
    * 公式ドキュメント・ダウンロードはこちら

https://github.com/MCUdude/MicroCore


## ATtiny13a の利点

* 安いので気軽に使える
* ブレッドボードの穴の幅と合うので、使いやすい
* Arduino IDE でプログラミング・書き込みできるので楽

## ATtiny13a のちょっとめんどくさいところ
気にしない方が良いですが、、、

* 書き込み用に __Arduino UNO__ (もしくはその互換)を使います。
    * __USBasp__ というものでも書き込めるような気がしますが、、、まだうまくいっていません。ちなみに Arduino Leonard などは、ICSP・SPIの端子(MOSI、MISO、SCK、SS、RST、VCC、GND)が無かったりするらしく、使えないような気がします。)
    * いずれにせよ、マイコンに直接書き込むには、書き込み用のハードウェアが必要になるので。
* ちょっとピン配置で混乱するかも
    * 後で開設するのでご安心ください。

あ、でも、そんなもんですかね。



# ATtiny13a でサーボモーターを動かすまでの話


## できるものの例

https://twitter.com/b_lab_hakodate/status/1509768812316438529

https://twitter.com/b_lab_hakodate/status/1600093912525606912

https://twitter.com/b_lab_hakodate/status/1600095485162758145


## 手順

### ひとまず簡単なプログラムを書き込めるところまでやってみる 

0. 必要なものを揃える
0. Arduino から ATtiny13a にプログラムを書き込むための配線を行う
0. LED(電球) を 光らせるための ATtiny13a の配線を行う
0. 配線に合わせて、LED を光らすプログラムを書いてみる
0. Arduino IDE の設定を整える
0. プログラムを書き込む
0. 動作確認をする

配線手順など多いので、まずは「__Lチカ__」(=LEDの点滅) からやらないと混乱すると思うので、そちらから。(というよりも、Lチカができたら作業は半分以上終わっています)

正確な手順は、やはり __公式ドキュメント__ ( https://github.com/MCUdude/MicroCore )を読むのが一番良いです。ブラウザの翻訳機能で十分読みやすいです。使える関数(機能)の一覧も載っています。

上記の手順が上手くいったら、サーボモーターを動かす配線をし、プログラムを書きます。


#### 1. 必要なものを揃える
* __パソコン__
    * プログラムを書き込むために使います。
    * Arduino IDE 1.x系 (2.x系は2023年7月現在使用できません) が使えるPCであれば何でもOKです。
        * __Arduino 1.8.19__ で動作確認を行っております。
        * Arduino IDE 2.1.0 で試しましたが、やっぱり 2.x系 だと動きません。
* __ATtiny13a__ 
    * サーボモーター制御用の信号を出すための __マイコン__ 。秋月電子で150円くらいで買えます。何か作るごとに4,000円近くするArduino使ってたらお金が無くなるので。
* __ブレッドボード__
    * 上述の ATtiny13a を差し込んで、書き込み台として使用します。サイズは 4x5cm 程度のサイズのもので構いません。
* __ジャンパ線__ (10本くらい)
    * 配線用。10本くらいあれば余裕です。
* __電池ボックス__ (単三×3本 スイッチ付き ジャンパ線付き)
    * ATtiny13a を動作させるためのものです。1.8～5.5V の間で供給できれば良いので、ひとまず乾電池3本で 4.5V 供給する形ですね。 
* __Arduino Uno__ (もしくは互換品)
    * ATtiny13a にプログラムを書き込む際に、書き込み用の信号を送るのに使います。
    * Leonard でも Pro Mini は 端子の関係上NGっぽいです。
    * Nano なら端子があるので大丈夫そうですが、未確認です。
    * USBasp というのでも書き込めるらしいですが、こちらも未確認です。
* __コンデンサ__ (10～22μF)
    * ATMega328P (Uno や Nano) や ATMega2560 (Mega 2560) のマイコンを使っている Arduino を使う場合、内蔵している自動リセット回路をこれで無効にします。
    * なくても動作する場合もあるらしいのですが、念のため用意した方が良いです
    * 書き込み用の上記の Arduino には、先に "Arduino as ISP" のスケッチを書き込んでおく必要があるので、それが終わってからコンデンサを取り付けること。
* __板__ (カラープラ段ボール (プラダン) )
    * 上記のものがバラバラにならないように、台として使います。両面テープを付けて固定してしまいましょう。
* __LED と それに合わせた 抵抗 (220Ω～1kΩ あたり)__
    * 抵抗があれば使いましょう
        * ATtiny13a が流す電流量には上限があるので、抵抗はつけなくても (まぶしく) 光りはします。念のため持っている人は 220Ω～1kΩ あたり (正確な値が気になる人は調べてもらえると) の抵抗などをご用意ください。
* __サーボモーター__
    * ゴミ箱のフタを開くのに使います。
* __フォトリフレクタ__
    * 手をかざしたのを感知するセンサーとして使います。

#### 2. Arduino から ATtiny13a にプログラムを書き込むための配線を行う
まずは配線からやっていきましょう。

Arduino から ATtiny13a にプログラムを書き込む際は、 __SPI通信__ を使います。なので、そのための配線をしていきます。 __Arduino__ と、__ブレッドボード__ と __ATTiny13a__ と __ジャンパ線__ と __コンデンサ__ と __電池ボックス__ をご用意ください。

こんな感じで配線します

| Arduino側ピン (ピン番号) |   | ATtiny13a側ピン (ピン番号) |
|:-----------------------:|:-:|:------------------------:|
| SS (10)                 |⇔ | RESET (1)                |
| -                       | - | (2)                      |
| -                       | - | (3)                      |
| (GND)                   |⇔ | GND (4)                  |
| MOSI (11)               |⇔ | MOSI (5)                 |
| MISO (12)               |⇔ | MISO (6)                 |
| SCK (13)                |⇔ | SCK (7)                  |
| (5V)                    |⇔ | VCC (8)                  |
| (RESET)                 |⇔ __コンデンサの(+)側__   |   |
| (GND)                   |⇔ __コンデンサの(-)側__   |   |

* ATtiny13a の凹みのマークを上にして、左上から反時計回りに(1)～(8)番ピンとしています、
    * Arduino 系だと、SPI用に6個の(オス)ピンがまとまったセット(ISCPピン)も使えるようです。その際はピンに合わせて オス-メス のジャンパ線をご利用ください。
    * SPI通信 の各端子の機能については、ここに端的にまとまっています ⇒  http://www.musashinodenpa.com/arduino/ref/index.php?f=1&pos=539
* コンデンサは、__線の書かれている方・脚の短い方がマイナス側__ です。
* 内部リセット防止用にコンデンサを取り付けますが、タイミングに注意です。
    * Arduino 自体に Arduino ISP のスケッチサンプルを書き込み直す際には、コンデンサを外してください。
    * 逆に、Arduino から ATtiny13a に書き込むときには、コンデンサを装着してください。
* ~~書き込み時は、ATtiny13a への電源供給(1.8～5.5V) は別途行うこと(Arduinoからの電源供給だと失敗します)~~ ⇒ Arduinoからの給電(5V)でも大丈夫でした 
    * 出典: https://akizukidenshi.com/catalog/g/gI-02911/
* SPI通信 の配線パターンは大きく分けて2つあります
  * SPI通信 で使われるピンは次のとおりです、
      * Arduino Uno (ATmega168 か ATmega328 を搭載しているマイコンボード)
          * 10(SS)、11(MOSI)、12(MISO)、13(SCK)
      * Arduino Mega
          * 50(MISO)、51(MOSI)、52(SCK)、53(SS)
      * ※SSピンは出力状態のままにしておく必要があります。そうしないと、SPIインターフェイスがスレーブモードに移行し、ライブラリが動作しなくなります。
    * Arduino の場合は、通常のピン位置に加え、SPI接続 に特化したピンのセットがありますので、そちらに繋いでも良いです。



#### 3. LED(電球) を 光らせるための ATtiny13a の配線を行う

ATtiny13a の ピン配置は、Arduino の配置と違うので結構ややこしいです。
改めて画像と共に確認しましょう。

![Arduino から MicroCore を使って ATtiny13 に書き込む際のピン情報](https://camo.githubusercontent.com/d416e9fc0353bdb04a36adde608298f29f1c303d511bb76805a287e57d2a42bc/68747470733a2f2f692e696d6775722e636f6d2f364c367262534f2e706e67 "ATtiny13 Pinout(ピン配列)")

今回つかうのに役立ちそうな、主要なピン情報を抜き出しました。

| ATtiny13a のピン番号 (凹みを上にしたとき、左上から反時計回りに1～8番ピン) | Arduino IDE 上でのポートピン番号(PB○) | Arduino IDE 上であつかう Arduino Pin 番号 (0～5 / A0～A3) | その他 |
|:-:|:---:|:------:|:----------------:|
| 1 | PB5 | __5__ / __A0__ | __^RESET__, ADC0 |
| 2 | PB3 | __3__ / __A3__ | ADC3             |
| 3 | PB4 | __4__ / __A2__ | ADC2             |
| 4 | --- | ------         | __GND__          |
| 5 | PB0 | __0__ / --     | __MOSI__, TXD    |
| 6 | PB1 | __1__ / --     | __MISO__, RXD    |
| 7 | PB2 | __2__ / __A1__ | __SCK__, ADC1    |
| 8 | --- | ------         | __VCC__          |

今回 LED に繋ぐのは、__Arduino IDE 上の「2」番ピン__ (= Arduino IDE 上での Arduino Pin 番号「PB2」) ( __= ATtiny13a の「7」番ピン__ )
要は、LEDのアノード(脚の長い(+)側)は、ATtiny13a の 7番ピンと繋いで、カソード(脚の短い(-)側)は、ATtiny13a の GNDピンと繋いでください。

...かなり紛らわしいですが、上記の表を見ながら確認していただきたいです。


#### 4. 配線に合わせて、LED を光らすプログラムを書いてみる

いよいよ Lチカ のプログラムを書いてみましょう。

```LedTickOnAttiny13a.cpp
// 本当のファイル名は "LedTickOnAttiny13a.ino"
// マイコンは ATtiny13a を使用
// ハードウェアパッケージは MicroCore を使用
// 設定は底部に書きます

#define PIN7 2                   //ATtiny13a 7番ピン (MicroCore 上では 2番ピンとなっているので、わかりやすいように PIN7 としておきます)

void setup() {
  pinMode(PIN7, OUTPUT);         //PIN7 (ATtiny13a 7番ピン)を、出力モード(=OUTPUT)に設定
}

void loop() {                    //2秒ごとに、点滅を10回繰り返し、ループを抜け終了するプログラム
  for(int i=0; i<=10; i++){      //10回点滅するために、ループを作ります。
    digitalWrite(PIN7, HIGH);    //7番ピン、通電(LED点灯)。
    for(int j=0; j<100; j++){    //100 * 10ms = 1秒 としたいので、ループを作ります。
      delayMicroseconds(10000);  //10ms。delayMicroseconds()は、16383マイクロ秒以内の値を指定したとき、正確に動作。
    }
    digitalWrite(PIN7, LOW);     //7番ピン、遮断(LED消灯)。
    for(int k=0; k<100; k++){    //100 * 10ms = 1秒 としたいので、ループを作ります。
      delayMicroseconds(10000);  //10ms。delayMicroseconds()は、16383マイクロ秒以内の値を指定したとき、正確に動作。
    }
  }
  exit(0);                       //ループを抜ける
}

// ## ボード設定
// * [ボード] > [MicroCore] > [ATtiny13] を選択
// * [BOD] > [BOD disabled] を選択
// * [EEPROM] > [EEPROM retained] を選択
// * [Clock] > [9.6 MHz internal osc.] を選択
// * [Bootloader] > [No bootloader] を選択
// * [シリアルポート] > (選択肢の中から、接続している Arduino の COMポート を選択してください)
// * [書込装置] > [Arduino as ISP] を選択
//
// 上記の設定・変更をしたら、毎回必ず以下の手順を行ってください
// * [ツール] > [ブートローダを書き込む] を選択

```

とりあえず、名前を付けてファイルを保存しておきましょう。


#### 5. Arduino IDE の設定を整える

Arduino を ATtiny13a の書き込み機として使用する場合、使用する Arduino にそれ (Arduino書き込み機) 用のスケッチ (プログラム) ( __ArduinoISP__ ) を書き込んでおく必要があります。以下の手順で書き込みます。

* パソコンに Arduino IDE (1.x系) をインストールする
    * https://www.arduino.cc/en/software にてダウンロードしてください。(※2.x系は2022年現在うまく動作しませんでしたので、画面下にある「Legacy IDE (1.8.X)」にあるバージョンをインストールしてください。)
    * 2023年7月2日現在の最新バージョンは「Arduino IDE 1.8.19」です。
* Arduino IDE の言語設定を日本語にしておく
* Arduino と パソコンを USBケーブル で接続する (ジャンパ線とかコンデンサなどは取り付けない)
* [ボード選択 (Arduino Uno など、繋いでいる機種名を選択)] と [ポート選択 (USBを繋いたCOMポートの番号設定)] の両方を済ませる
* [ファイル] > [スケッチ例] > [11.ArduinoISP] > [ArduinoISP] の順番に選択
* [→](マイコンボードに書き込み) を選択
* これで、ATtiny13a や色々なマイコンへプログラムを書き込むための通信 ( ISP通信 ) ができるようになりました。

次に、Arduino IDE で書いたプログラムを、ATtiny13a で使えるプログラムに変換して書き込むための「ハードウェアパッケージ」(プラグイン、プログラムのようなもの) である「MicroCore」を Arduino IDE に取り込みます。

※参考:8ピンAVRマイコン ATtiny13AのプログラムをArduinoで作る方法) 

https://kohacraft.com/archives/202110241211.html

* [Arduino] ⇒ [設定] で環境設定を開く
* 環境設定画面の「追加のボードマネージャのURL」欄に https://mcudude.github.io/MicroCore/package_MCUdude_MicroCore_index.json を貼り付け、OKを押す
* [ツール] > [ボード] > [ボードマネージャ] の順に進み、ボードマネージャを開く
* ボードマネージャー の画面にある検索窓に「MicroCore」と入力
* 検索結果に、MCUdude の MicroCore が表示されたら、「インストール」のボタンを押す
* 一度 Arduino を終了させ、Arduinoを再起動する

次に、ATtiny13a に、基本的な設定項目と Arduino IDE からちょこちょこプログラムを書き換えるために必要なプログラムがセットになった __ブートローダー__ を書き込んでいきます。
まずは以下の通り、ブートローダーと一緒に ATtiny13a に書き込む基本的な項目を設定してください。
* パソコンと Arduino は接続したままにして...
* [ツール] > ...(以下の項目を設定してください)
    * [ボード] > [MicroCore] > __[ATtiny13]__ を選択
    * [BOD] > __[BOD disabled]__ を選択
        * ATtiny13a に供給されている電圧を監視して、設定以下の電圧になると電源が切れる(電圧が復活すると再起動する)機能です。
        * 今回はモーターを使った瞬間に電圧が下がるので、この機能は切って( BOD disable にして)おきましょう。
    * [EEPROM] > __[EEPROM retained]__ を選択
        * 不都合が無ければデフォルトのこの値のままで。
    * [Clock] > __[9.6 MHz internal osc.]__ を選択
        * 不都合が無ければデフォルトのこの値のままで。
    * [Bootloader] > __[No bootloader]__ を選択
        * [はい] や 他の項目を選んでしまうと、プログラミング書き込み時に、以下のようなエラーが出ます。
            * "avrdude warning: attempt 10 of 10: not in sync"
            * "avrdude warning: programmer is not responding; try -xstrict and/or vary -xdelay=100"
            * "avrdude error: unable to open programmer urclock on port COM4" など
    * [シリアルポート] > (選択肢の中から、接続している Arduino の COMポート を選択してください)
    * [書込装置] > [Arduino as ISP] を選択
* __上記の設定・変更をしたら、毎回必ず以下の手順を行ってください__
    * [ツール] > [ブートローダを書き込む] を選択

これで Arduino IDE で ATtiny13a をプログラミングをするための準備はできました。
プログラミングを書き込みましょう。

#### 6. プログラムを書き込む

* [スケッチ] > __[書き込み装置を使って書き込む]__ で書き込んでみましょう

#### 7. 動作確認をする

* LEDが点滅すれば成功です


# Lチカ のコードを書き換えて、サーボモーター制御 のプログラムを書き込み
https://github.com/hakodate-laboratory-inc/ServoMotorTestCodeForAttiny13aViaArduino_2022/blob/main/221209_ServoMotorTestCodeForAttiny13aViaArduino_2022_01.ino

```ServoMotorTestCodeForAttiny13aViaArduino_2022.cpp
//"ServoMotorTestCodeForAttiny13aViaArduino_2022.ino" from @deckeye
//Arduino から、”Arduino as ASP（MicroCore）” を使って、ATtiny13a に書き込みをして、サーボモーターを動かすプログラムです。
// マイコンは ATtiny13a を使用
// ハードウェアパッケージは MicroCore を使用
// 設定は底部に書きます

#define PIN7 2
  // ATtiny13a 7番ピン (MicroCore 上では 2番ピンとなっているので、わかりやすいように PIN7 としておきます)
  // 7番ピンにサーボモーターの信号線(黄)を、(赤)は電池ボックスの＋側に、(茶)は－側と ATtiny13a の GND に繋ぎます
  // 供給電流不足になるので ATtiny13a から電流供給はしないこと。ただし GND は繋ぐこと
unsigned int ServoHighMicroSec = 500; // 500-2400μs。パルス長。

void setup() {
  pinMode(PIN7, OUTPUT);
}

void loop() {
  // しばらく同じ長さのパルスを出し続けるコードです
  for(int i=0; i<30; i++){
    // しばらく(30ループ分)同じパルスを出し続ける。
    // パルスを出している間しかサーボモーターが動いてくれない(10ループだと回転途中で終わる)
    // ので、気持ち多めの30ループにしました。
    digitalWrite(PIN7, HIGH);
      delayMicroseconds(ServoHighMicroSec);
        // パルスをHIGHで指定の時間(ServoHighMicroSecの値)継続
        // delayMicroseconds()は、16383μs以内の値を指定しないと正常動作しないので、以下では10000μsずつに分割してます。
    digitalWrite(PIN7, LOW);
      // パルス周期を18000μs(18ms)として、以下のdelayを設定する。
      delayMicroseconds(8000);
        // パルスをLOWで指定の時間継続
        // 仕様上16383μs以内しか入れられないので、10000μs単位に分割。
      delayMicroseconds(10000-ServoHighMicroSec);
        // 周期長から、HIGHの時間分引いている感じですね。
  }

  // パルスを出した後、念のためLOWのまましばらく待たせてみてます(ここのコードは無くても動作します)
  delay(10); //10ms

  // パルス長(HIGHの時間)を300μsずつ増やしていきます(ループするごとに、サーボの角度がちょっとずつ変わります)
  ServoHighMicroSec = ServoHighMicroSec + 300;

  // パルス長(HIGHの時間)が2400μsを超えたら、500μsにリセット
  if(ServoHighMicroSec > 2400){
    ServoHighMicroSec = 500;
  }
}

// ## ボード設定
// * [ボード] > [MicroCore] > [ATtiny13] を選択
// * [BOD] > [BOD disabled] を選択
// * [EEPROM] > [EEPROM retained] を選択
// * [Clock] > [9.6 MHz internal osc.] を選択
// * [Bootloader] > [No bootloader] を選択
// * [シリアルポート] > (選択肢の中から、接続している Arduino の COMポート を選択してください)
// * [書込装置] > [Arduino as ISP] を選択
//
// 上記の設定・変更をしたら、毎回必ず以下の手順を行ってください
// * [ツール] > [ブートローダを書き込む] を選択
```


# 思ったようにプログラムが動かない時に、確認したいこと
プログラムの書き込み前に、以下の項目も念のため確認しておいてください。

* 2023年7月時点では、Arduino IDE Ver.1.8.19 で動作確認済み。MicroCore (MicroCore v2.3.0) が IDEのVer.2系 には対応してないみたいです(エラーが出る。異論は募集中。)
* 周波数は"9.6MHz internal osc."でやってます。
* タイミングは"micros enablaed"でやってます。
* 動作確認時は、ATtiney13a の電源は、Arduinoではなく、別電源からの供給にしてみてください


# こぼれ話
本当はサーボ周りのライブラリを使いたかったのですが、どうにも上手く扱えなかったので、digitalWrite() とdelayMicroseconds() のゴリ押しPWMでやっています。


# 参考資料
* 配線と ArduinoISP の設定 https://ht-deko.com/arduino/bootloader.html
    * 「ファイル → スケッチ例 → ArduinoISP → ArduinoISP」
* 同じく配線など。図はこちらの方が見やすいです。 https://burariweb.info/electronic-work/attiny-chip-arduino-summary.html
* MicroCore 以外にも、SpenceKonde氏の「ATTinyCore」もあるようですが、ATtiny13a には対応していないようです。 https://rephtone.com/electronics/attinyandarduino/
* ネット上の謎のパーツの使い道がこれで分かりました https://ht-deko.com/arduino/attiny85.html
* Leonard系ではSS端子がTX用のLEDから引き出すしかなさそう(だけど、SSに繋がなくてもマスターとしてSPI接続している説明も見た気がする) https://ht-deko.com/arduino/leonardo.html


まずはこの辺で。