Help us understand the problem. What is going on with this article?

Arduinoで、小っちゃいIC(ATTiny)を使う方法

More than 5 years have passed since last update.

ArduinoUNO

Arduinoで、小っちゃいIC(ATTiny)を使う方法

ちっちゃいICを使いたい!

Arduino、始めたばかりですが超楽しいです。(いや始めたばかりだから楽しいのかw)

お金が無いせいで、シールドとかにはまだ手を出してなくて、Arduino UNOとブレッドボード、それと安く手に入る部品だけを使って遊んでいます。
ブレッドボードで動作確認したら、ICをUNOから引き抜いて、ユニバーサル基盤に作った回路に組み込んでみたり。こうした使い方をしていることもあり、ATmega328Pを追加で買ったりしてるのですが、ATmega328Pは1コ250円もして、少々お高いのが気になってました。

それに28PIN-DIPって簡単な用途には大きくて配線もたいへん。
将来量産(なにを?!いや何か絶対!w)を見据え、もっと物理的にちっちゃいICを試してみたい。でも表面実装(SMD)版とかハンダ付け超ムリ!

ATTinyはDIPでもちっちゃい!

というわけで目をつけたのがATTinyシリーズ。DIP版でも足の数が少ないので、ちっちゃいです。特に13A!
Writer

上からATTiny13A、ATTiny2313、一番下がATmega328P

試しに20本足のATTiny2313-20PUと、8本足のATTiny13Aを購入してみました。

ざっくりSPEC表

SPEC ATmega328P ATTiny2313 ATTiny13A
価格
(2014.1.26現在)
250円 150円 50円
DIP PIN数 28 20 8
ROM 32Kbyte 2Kbyte 1Kbyte
RAM 2Kbyte 128byte 64byte

ATTinyは大きさだけでなく、性能も、ちっちゃい!w
どこまで使えるかわかりませんが、ちょっと触ってみようと思います。

1. Arduino UNOで、ちっちゃいIC(ATTiny)を開発する

Arduino UNOがあれば(それが互換機でも)ATTinyの開発ができます。UNO以外に必要なのは、ブレッドボードと抵抗、コンデンサ、ジャンパーピン、LEDなど。Arduino入門編をやってる方は持っているものばかりだと思います。

Arduino UNOでATTinyなどを開発するやり方は、kosakalabさんの、下記記事で超詳しく紹介されています。
Arduino IDEでATtiny他の開発(Arduino-ISP編)

私も記事の通りに進めることでATTiny13AとATTiny2313でのLチカに成功しました。
素晴らしい記事を書いてくれたkosakalabさんには、本当に感謝です!

2. ROM/RAM使用量を確認できるようにする

ROM使用量はIDEでビルドするだけで表示される

ATTinyはROM(正確にはFLASHROM)やRAM(正確にはSRAM)が小さいので、プログラムも小さくしなければ入らなくなります。
Arduinoのプログラムが、どのくらいROMやRAMを消費するか、Arduinoのいわゆる「Lチカ(blink)」を使って確かめてみましょう。

** Arduino IDEに付属のBLINKのコード (コメントは外してあります) **

(ATTiny対応にPIN番号だけ変更してあります。)

    int led = 0;    // ATTiny2313用に変更
    void setup() {                
      pinMode(led, OUTPUT);
    }

    void loop() {
      digitalWrite(led, HIGH);
      delay(1000);
      digitalWrite(led, LOW);
      delay(1000);
    }

これをビルドしてみます。すると、下記のような表示が。
910byte

910byte。え!Lチカだけで?こんなに大きいんだ。。。13A、Lチカ以外できないんじゃ?
と、一抹の不安を感じつつ。。
910byteというのはFLASH ROMの使用量です。まだRAMはどのくらい使ってるのかは解りません。

RAM使用量の調べ方

というわけで、RAM使用量も確認してみます。

ArduinoのRAM使用量の調べかたは、下記で紹介されています。
Arduinoでのメモリ使用率の調べ方

なんと、elfファイルからdumpしろ。ということらしいですね!
いきなり組み込み系な感じになって来ました。なんかArduinoの可愛さが薄れていくような。。。w

いえいえ、ちっちゃいATTinyのためです。やってみましょう。
> avr-objdump -h プロジェクトファイル名.elf
と実行してみます。

objdump

Lチカのプログラムだけですと、.textと.bssしか出てきませんでした。よく見るとconstデータがありませんね。
これだとちょっと説明にならないので、少しプログラムを改造して、もう1度やってみます。
(Lチカのタイミングを少しおかしくしただけのものです)

    int cnt;
    const int led = 0;
    const int a[] = {200,400,800,1000}; // Lチカのタイミング

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

    void loop() {
      int v;
      v = a[cnt];
      cnt++;
      if(cnt == 4){
        cnt = 0;
      }
      digitalWrite(led, HIGH);
      delay(v);
      digitalWrite(led, LOW);
      delay(v);
    }

今回は、LEDのピン番号の変数と
このスケッチをビルドすると、Lチカタイミング用のテーブルをconstに追加してみました。
これをビルドしてみますと、

982byte
objdump

となりました。const変数を追加したので、今度は.dataというものが出てきました。
長くなりましたが、ROMとRAMの容量をまとめると、

ROM使用量 = .textと.dataの合計 (今回の例では 982byte)
RAM使用量 = .bssと.dataの合計  (今回の例では  19byte)

となります。
(RAMはもう少し複雑で、ヒープやスタックと共有で利用していますので、正確に言うと上記以外にも使われています)
RAMの使われ方については、下記サイトの説明がとても参考になります!
Arduino Unoのメモリ

3. プログラムをちっちゃくする!

さて、いよいよプログラムをちっちゃくするのに挑戦します!
そんなんかんたんにできるんか〜?と気になるところですが、さすがはArduino、さすがはインターネット!
いろいろな手法があるようです。

ROMを減らす方法。単純に処理する関数をつくろう。

簡単にやれることから

Arduinoでは、いろいろな関数やライブラリが利用できます。
これらは、とても「書きやすく、とっつきやすい」ものですが、中を覗いてみると、様々なケースに対応できるようにするためか、結構なコード量だったりします。
先ほどのLチカにも出て来たpinMode()digitalWrite()を置き換えるだけでも結構削減できるので、やってみたいと思います。

pinMode()digitalWrite()がどのような処理を行っているかについては、下記サイトで詳細に解説されています。

Arduionoソフトウェアの内部構造: pinMode()
Arduionoソフトウェアの内部構造: digitalWrite()

上記サイトの情報をもとに、pinMode()とdigitalWrite()を書き換えてみます。
実はポート叩いてるだけなんで、マクロを作ります。

    // ATTiny2313用。D0ピンIOマクロ
    #define PMD0_OUTPUT() (DDRD |= _BV(0))    // pinMode(0,OUTPUT)
    #define DWD0_HIGH()   (PORTD |= _BV(0))   // digitalWrite(0,HIGH)
    #define DWD0_LOW()    (PORTD &= ~_BV(0))  // digitalWrite(0,LOW)

あとは、pinMode()やdigitalWrite()と置き換えるだけ。

    int cnt;
    // const int led = 0; // ←マクロにしたので要らなくなりました。
    const int a[] = {200,400,800,1000}; // Lチカのタイミング

    void setup() {                
      PMD0_OUTPUT();     // pinMode(0,OUTPUT)
    }

    void loop() {
      int v;
      v = a[cnt];
      cnt++;
      if(cnt == 4){
        cnt = 0;
      }
      DWD0_HIGH(); // digitalWrite(0,HIGH)
      delay(v);
      DWD0_LOW();  // digitalWrite(0,LOW)
      delay(v);
    }

でビルドしてみると。
624byte
982→624byte!300byte以上も削減できました。

トレードオフできることはトレードオフしてみる。

さきほどのpinMode()とdigitalWrite()の例は、もとある機能を変えずにコード圧縮を実現していました。
しかし、全ての機能を正確に実現することは、そんなに大事でないかもしれません。
たとえば、さきほどのLチカ。
Lチカであれば、LEDの間隔が多少ずれても、そんなにたいしたことではないはずです。
精密なタイマーの場合は大問題ですが、そもそも精密なタイマーにdelay()は使わないでしょうw
というわけで、delay()にもメスを入れてみます。かなり大胆にw

    extern volatile unsigned long timer0_millis;
    void deeeelay(unsigned long ms) {
      unsigned long exptim = timer0_millis+ms;
      while (timer0_millis < exptim){}
    }

もう、あまり人におススメできる内容から脱線している気がしますw
冒頭で外部参照しているtimer0_millisは、hardware/arduino/cores/arduino/wiring.c
などで宣言されているグローバル変数で、起動時からの経過時間(但し限界まで行くと0に戻りまたカウント)をmsで記録しています。millis()を使っても良いのですが、関数呼ぶ分オーバーヘッドがあるので、直接参照しています。
で、中は見ての通りで、指定された時間が来るまで永久ループしてるだけです。
で、コレの何が「トレードオフ」なのかと言うと、delay()の1/1000の精度しかありません。気になる方はdelay()側のコードを見てください。

上記を使うコード部は、delay(v)deeeelay(v)にするだけなので、割愛します。
ビルドしてみると、
530byte
530byte!
さらに100byte近く削減できました!

これ以上は、違うところ(本来触ってはいけないところ)を触らなければいけなさそうな気がします。。ので、そろそろ止めときます。(ここに書くのではなく、自分で勝手にコッソリ進めますw)

※実は今、ATTiny13AでTone()ぽいものを無理矢理動かしたくて、wiring.cを改造しまくってたり。。。

RAMを減らす方法。.dataを減らしてROMへ。PROGMEMを使う。

さて、最後に.dataが使用するRAM容量を減らす方法を紹介して、この記事をしめたいと思います。
.dataはROMにも入ってるくせにRAMにも入っているという邪魔者です。
「データは入れときたいけど、使うときすぐに使いたいから起動するときROMからRAMに読み込んどく」ということをやってるかららしいです。
でも、大きなデータって主に配列だと思うのですが、これ、全部の要素を頻繁に上から下まで順番に読み込む、なんて使い方するんでしょうか。普通はあまりしないと思います。
通常は、何番目のデータを読むか?という指定をして、ダイレクトに使う部分のデータだけを読み込むことの方が多いと思います。こうした使い方だと、PROGMEMという方法が使えます。

使い方は、下記ページでとても詳しく教えてくれます。教わりました。
Arduino Unoのメモリ
※上記記事はArduino UNOを例に記載されていますので、ATTinyだとメモリ量やアドレスなどが異なります。

まとめ

ATTinyに入れられるのは、ちっちゃいプログラムだけ!ちっちゃいは正義!ということでした。

最後まで読んでいただき、ありがとうございました!
間違いなど、ありましたら教えて頂けたらうれしいです。どうかよろしくお願いします〜。

オマケ
Arduinoで作ったBeep音楽器です。(これはATTinyではなくATmega168P使いました)
beepSynth
[InstagramにショートMovie Upしてます!]http://instagram.com/p/inYeIpnCkl/

つづき

2014.12.17更新
つづきを書きました!いろいろあるATTinyを何点かピックアップして紹介してみました〜!

tadfmac
aka D.F.Mac. 実験音楽家。TripArts Music主宰。ハンディーレコーダーでの音集めが趣味。 Web技術、フィジカルコンピューティングなどにも興味があります。
http://soundcloud.com/tadfmac
kddi
KDDIは、通信を中心に周辺ビジネスを拡大する「通信とライフデザインの融合」をより一層推進し、国内はもとよりグローバルにおいても、5G/IoT時代における新たな価値創造を実現し、お客さまの期待を超える新たな体験価値の提供を追求してまいります。
http://www.kddi.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした