2015/8/25 追記
ATtiny841を汎用的にArduino IDEで開発したい方は、SpenceKonde/arduino-tiny-841を利用すると良いと思います。
上記Githubは本記事でも紹介させていただいたshimniok/arduino-tinyのforkになります。
また、ATtiny841でI2C(slave)やMIDIを使ってみたい方は、私が進めているmi:muzも参照してみてください。
こちらはCoreを特別に用意していないのと、上記arduino-tinyとは異なるPINアサインとなっていて、Arduino IDEでATtiny他の開発(Arduino-ISP編)by kosakalabさんのATtiny84/44とアナログ/デジタルPIN互換になっています。
2015/4/14追記
本記事は、Arduino IDE 1.0.xで無理矢理 ATtiny841に対応させようというものでした。
しかし、時は移り、Arduino IDE 1.6.x系が登場しました。
Arduino IDE 1.6.x系ではavr-gcc v4.8.1がサポートされており、ATtiny841の対応が「一部」進んでいます。
これから始めようという方には、1.6.x系を使った方が楽かもしれません。
1.6.x系の内容は別途書きます。(いろいろやりかたが違うので)
ArduinoユーザーのためのATTiny入門でも紹介したATTiny841という高機能なATTinyを手に入れたけど、まだArduinoは対応してないみたい。
AVR StudioやAtmel Studioといった開発環境が対応してるみたいだけど、Arduinoで使いたいので、開発環境を構築してみることにした。
ただ、予想通りというか、なんというか、手順がややこしいので、明日には忘れてそうな自分への伝言用メモを残しておく。
試行錯誤しながら進んでるので、なんか余分・意味のない手順が含まれてるかもしれない。
奇遇にも読んでしまって、変なところや間違いに気付いてしまった方がいらっしゃいましたら、優しく教えて頂けるとうれしいです。
随時追記・修正する予定です。
現在の進捗 (2015/01/07)
Arduino UNOからISP経由で下記スケッチを書き込んで動いた。
# define LED 9
# define BUTTON 6
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
}
void loop() {
  int val = LOW;
  digitalWrite(LED, HIGH);
  delay(1000);
  val = digitalRead(BUTTON);
  if(val != HIGH){
    digitalWrite(LED, LOW);
  }
  delay(1000);
}
これにより、
- delay()
- digitalRead()
- digitalWrite()
- 
pinMode(INPUT)とpinMode(OUTPUT)
が動いていることは確認。
環境構築の手順
用意するもの
- Ardino IDE 1.0.6
- PC (本記事はMacのテスト結果をもとに書いています。WindowsやLinuxでもできると思います。) ※Macbook AIR 2013 OS 10.8.5で確認
- ATTiny841
- ATTiny841を書き込む環境 (ATTiny841はSOPなのでDIP変換基板+ブレッドボードなどが必要です)
 SOP14ピン用のテストプログラマ(こういうの)があると、超絶便利。
最初に絶対にバックアップを取ろう!
現時点でArduino IDE 1.0.6は、そのままではATTiny841には対応していない。
なので、本稿では試行錯誤しながら、かなり乱暴にArduino.appの環境を書き換えています。
ビルド環境である、avr-gccや、ファームアップロードに使うavrdudeの環境を変更しているので、いろんな不具合がでる可能性がある。
本稿を読んでトライしてみよう、という方は、くれぐれもバックアップを取って、すぐに戻せるようにしながら実験をすすめるように!
** ※これまで動作していた別のスケッチが動作しなくなる現象を確認しています! **
手順0: 配線。ArduinoとATTiny841(ATTiny84/44/24も共通)の繋ぎ方
ArduinoとATTiny841はISPで書き込みします。
ATTiny841のデータシートを見るとはMOSIとかMISOとかSCKとか2つづつくらいあって混乱するけど、下記のように繋いで書き込み成功した。
| Arduino (UNO) | ATTiny841 | 
|---|---|
| 5V | PIN1:(VCC) | 
| GND | PIN14:(GND) | 
| D10 | PIN4(RESET) | 
| D11 | PIN7(MOSI) | 
| D12 | PIN8(MISO) | 
| D13 | PIN9(SCK) | 
- RESET : PB3
- MOSI : PA6
- MISO : PA5
- SCK : PA4
尚、Arduino UNO側のRESETとGNDの間に10uFくらいのコンデンサが必要っぽい。
参考:Arduino IDEでATtiny他の開発(Arduino-ISP編) (kosakalabさん)
手順1. ClossPack For AVRを入れる(Macの場合)
Arduino IDEの1.0.6に同梱されているavr-gccは4.3.2でかなり古い。(タイムスタンプを見ると2008年?)
このため、最近リリースされたAVRには対応できておらず、対応しているバージョンを利用しないとビルドできない。2013年にリリースされたばかりのATTiny841/441にももちろん未対応。
avr-gccの最近のバージョンを入手するには、ClossPack For AVR (CrossPack-AVR-20131216.dmg)を利用するのが良さげ。
avr-gcc 4.8.1がベースの2013/12/16版が現時点(2015/01/07)の最新で、ATTiny441/841に対応している模様。
実は1つ前のavr-gcc 4.7.2がベースの2013/12/05版にも、ATTiny841の定義が追加されてるけど、こちらは最終的にビルドエラーに。一部定義ファイルに不具合があるようで、2013/12/16版で同時に修正されている模様。
というわけで、少々乱暴なやり方だけど、ClossPack For AVRのavr-gccを下記手順でArduino内部にコピー。
- まず最初にClossPack For AVRをインストール
- Arduino側のAVR開発環境を必ずBackup
- 下記コマンドで、Arduino側に上書きコピー
sudo cp -R /usr/local/CrossPack-AVR-20131216/* /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/
これで、avr-gccのversionが更新されたはず。
下記コマンドで確認できる。
avr-gcc --version
4.8.1と表示されれば成功。
実はavr-gcc+Arduino 1.0.6だとROM容量が増える問題があり、暫定対処方法を下に記載。カツカツを狙いたい方は試してみる価値あり。
手順2. arduino-tinyのATTiny841対応版(shimniokさんのライブラリ)を入れて、いろいろ修正
ATTiny841は、shimniokさんが公開してくれているarduino-tinyで対応が進められているので、これを利用させていただく。
但し、shimniokさんもまだWIPだと言っているライブラリなので、作りかけの部分がいろいろある。
最低限Lチカまでに必要な修正をやってみることに。
※Lチカ以外は試してないので、他にもいろいろ直さなければならないはず。hardwareSerialとか。
修正点① pins_arduino.h
手抜きだけど、同じ14ピンのATTiny44/84とコンパチの機能だけでも有効になるように、__AVR_ATtinyX4__と同じところに__AVR_ATtinyX41__も追加。
pins_arduino.cの方は追加されているので、おそらく追加を忘れてるだけだと思われ。
これで、(Lチカだけなら)エラーが一部取れて先に進めるようになる。
もちろん、こんな感じの修正だけだとせっかくのATTiny841が84同等に。。。。。
修正点② boards.txtを修正
boards.txtも、2014/12/25時点だといろいろと作りかけなので、何カ所か修正。
ライター設定
今回は、Arduino ISPで書き込みたいので、
attiny841at16.upload.using=tiny:arduinoisp
を有効にして、
attiny841at16.upload.using=tiny:avrispv2
をコメントアウト。
ブートローダー設定(Fuse)
ブートローダーの設定は下記のように修正。
** 外付け16Mhzクリスタルを付ける場合 **
attiny841at16.bootloader.low_fuses=0xee
attiny841at16.bootloader.high_fuses=0xdf
attiny841at16.bootloader.extended_fuses=0xFF
** 内部発振で8Mhzで動かす場合 **
attiny841at16.bootloader.low_fuses=0xe2
attiny841at16.bootloader.high_fuses=0xdf
attiny841at16.bootloader.extended_fuses=0xFF
手順3. avrdude.confにATTiny841の設定を追加
Arduino IDEの「マイコンボードに書き込む」ボタンを押すと、手順1.と手順2.が成功していると、おそらくLチカのスケッチであればビルドできるようになったはず。
しかし、次の書き込みの段階で下記エラーが出る。
Arduinoのavrdude.confにATTiny841の設定を追加することで対処。
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avdude.conf
のファイル最後尾に、下記定義を追加。
# ------------------------------------------------------------ 
# ATtiny841 
# ------------------------------------------------------------ 
part 
id = "t841"; 
desc = "ATtiny841"; 
has_debugwire = yes; 
flash_instr = 0xB4, 0x07, 0x17; 
eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, 
0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, 
0x99, 0xE1, 0xBB, 0xAC; 
## no STK500 devcode in XML file, use the ATtiny45 one 
stk500_devcode = 0x14; 
## avr910_devcode = ?; 
## Try the AT90S2313 devcode: 
avr910_devcode = 0x20; 
signature = 0x1e 0x93 0x15; 
reset = io; 
chip_erase_delay = 4500; 
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", 
"x x x x x x x x x x x x x x x x"; 
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", 
"x x x x x x x x x x x x x x x x"; 
timeout = 200; 
stabdelay = 100; 
cmdexedelay = 25; 
synchloops = 32; 
bytedelay = 0; 
pollindex = 3; 
pollvalue = 0x53; 
predelay = 1; 
postdelay = 1; 
pollmethod = 1; 
hvsp_controlstack = 
0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, 
0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, 
0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, 
0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; 
hventerstabdelay = 100; 
hvspcmdexedelay = 0; 
synchcycles = 6; 
latchcycles = 1; 
togglevtg = 1; 
poweroffdelay = 25; 
resetdelayms = 0; 
resetdelayus = 70; 
hvleavestabdelay = 100; 
resetdelay = 25; 
chiperasepolltimeout = 40; 
chiperasetime = 0; 
programfusepolltimeout = 25; 
programlockpolltimeout = 25; 
ocdrev = 1; 
memory "eeprom" 
size = 512; 
paged = no; 
page_size = 4; 
min_write_delay = 4000; 
max_write_delay = 4500; 
readback_p1 = 0xff; 
readback_p2 = 0xff; 
read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", 
"a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; 
write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", 
"a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; 
loadpage_lo = " 1 1 0 0 0 0 0 1", 
" 0 0 0 0 0 0 0 0", 
" 0 0 0 0 0 0 a1 a0", 
" i i i i i i i i"; 
writepage = " 1 1 0 0 0 0 1 0", 
" 0 0 x x x x x x", 
" x a6 a5 a4 a3 a2 0 0", 
" x x x x x x x x"; 
mode = 0x41; 
delay = 6; 
blocksize = 4; 
readsize = 256; 
; 
memory "flash" 
paged = yes; 
size = 8192; 
page_size = 16; 
num_pages = 512; 
min_write_delay = 4500; 
max_write_delay = 4500; 
readback_p1 = 0xff; 
readback_p2 = 0xff; 
read_lo = " 0 0 1 0 0 0 0 0", 
" 0 0 0 0 a11 a10 a9 a8", 
" a7 a6 a5 a4 a3 a2 a1 a0", 
" o o o o o o o o"; 
read_hi = " 0 0 1 0 1 0 0 0", 
" 0 0 0 0 a11 a10 a9 a8", 
" a7 a6 a5 a4 a3 a2 a1 a0", 
" o o o o o o o o"; 
loadpage_lo = " 0 1 0 0 0 0 0 0",
" 0 0 0 x x x x x",
" x x x x x a2 a1 a0",
" i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0",
" 0 0 0 x x x x x",
" x x x x x a2 a1 a0",
" i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0",
" 0 0 0 0 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 x x x",
" x x x x x x x x";
mode = 0x41; 
delay = 6; 
blocksize = 32; 
readsize = 256; 
; 
# ATtiny841 has Signature Bytes: 0x1E 0x93 0x15. 
memory "signature" 
size = 3; 
read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", 
"x x x x x x a1 a0 o o o o o o o o"; 
; 
memory "lock" 
size = 1; 
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", 
"x x x x x x x x x x x x x x i i"; 
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", 
"0 0 0 0 0 0 0 0 o o o o o o o o"; 
min_write_delay = 9000; 
max_write_delay = 9000; 
; 
memory "lfuse" 
size = 1; 
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", 
"x x x x x x x x i i i i i i i i"; 
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", 
"x x x x x x x x o o o o o o o o"; 
min_write_delay = 9000; 
max_write_delay = 9000; 
; 
memory "hfuse" 
size = 1; 
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", 
"x x x x x x x x i i i i i i i i"; 
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", 
"x x x x x x x x o o o o o o o o"; 
min_write_delay = 9000; 
max_write_delay = 9000; 
; 
memory "efuse" 
size = 1; 
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", 
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", 
"x x x x x x x x o o o o o o o o"; 
min_write_delay = 9000; 
max_write_delay = 9000; 
; 
memory "calibration" 
size = 1; 
read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", 
"0 0 0 0 0 0 0 a0 o o o o o o o o"; 
; 
;
コピペで良い。
** 情報元: **
@morecat_labさんより情報提供いただいて修正しました。ありがとうございました!
手順4. ダミーのブートローダーを入れる(※もっと良い方法を探し中)
手順3.までで、書き込みまで成功するはず。
喜んで、Lチカの回路を組んで実行すると。。。
遅!
ということになるかも。(たぶんなるw)
ATTiny841は出荷状態だと内部発振の1Mhzで動作する設定になってるので、boards.txtのF_CPUに8Mhzとか16Mhzを書いてる場合、合わなくなる。
boards.txtのF_CPUに記載したクロックに併せるには、一度Fuseを更新する必要がある。
今回はArduino IDEからFuseも変更したいので「ブートローダーを書き込む」からFuseを変更できるようにする。
これで動作クロックなどを変更したい。
というわけで、できるようにする。
ライターをarduinoispに変更して「ブートローダーを書き込む」を実行すると、Arduinoは/coresの同列にあるbootloadersの下のattiny841at16.bootloader.pathに指定したフォルダの下のattiny841at16.bootloader.fileに指定したブートローダーファイルを読み行く模様。
ただ、そこにはファイルがない。
このファイルはダミーのhexファイルで良いっぽいので、暫定対処として、いつも他のATTiny開発に使わせて頂いているkosakalabさんの「Arduino IDEでATtiny他の開発(Arduino-ISP編)」で配布されているhardware.zipの中にあるdummy.hexをコピーしていれておく。
arduino-tiny/bootloaders/dummy/dummy.hex
な感じで置く。
boards.txtも下記のように書き換える。
attiny841at16.bootloader.path=dummy
attiny841at16.bootloader.file=dummy.hex
これで、Arduino IDEから「ブートローダーを書き込む」を選ぶと 一応* FUSEの書き換えができるようになる。
ただ、さすがに別の環境から適当に持って来たhexファイルを使ってるためか、「ブートローダーを書き込む」の結果としてエラーが。
エラーが出ても、Fuseの値は変わっているようですので、もういちどスケッチを開いて「マイコンボードに書き込む」で書き込みすると、ちゃんとした速さで動くようになったはず。
おつかれさまでした。
既知の問題と対処方法(WIP。随時追加予定)
これまでに見つかった(というかハマったw)問題について書いておく。
随時追加する予定
1. PROGMEMでエラー出るようになった!
avr-gccをversion upすることで発生する問題。
PROGMEMを付与する変数は、変数型にconstを付与しよう。
2. アセンブラのファイル(.S)がビルドできなくなった!
これもavr-gccを更新することによる問題。
avr-gcc側でコマンドラインオプション-assembler-with-cppの指定の方法が変更された。
Arduino IDE 1.0.5は、変更前のコマンドをavr-gccに指定してビルドを実行してしまいエラーになっている。
(詳細情報)Assembly files not working with newer gcc, -assembler-with-cpp option does not exist? #1807
Arduino IDE 1.0.6には上記問題のFixが反映されているので、本問題にひっかかった方は一度Arduino IDEのバージョンを確認してみると良い。→ Arduino IDE 1.0.6を利用しよう。
3. avr-gccを更新後、既存のスケッチをビルドするとROMサイズが増えてしまった!
たぶん、avr-gccがどこかのバージョンでビルド時の最適化オプションの指定方法が変わったのかもしれない。詳細はわからない。
とにかくArduino IDEからavr-gcc 4.8.1経由でビルドするとサイズが増えることがあるようだ。
実際にROMサイズギリギリを狙ったいくつかのプロジェクトのファームが収まらなくなり焦った。
いろいろやってみたけど、avr-gcc 4.7.2の方だと今のところサイズの問題は発生していない。
ただ、avr-gcc 4.7.2はClossPack For AVR (CrossPack-AVR-20131205.dmg)に入ってるけど、上の方に書いたように、この環境だとATTiny841のビルドが通らない。
そこで、下記のように4.8.1と4.7.2をムリヤリマージする。
- 最初にClossPack For AVR (CrossPack-AVR-20131216.dmg)をダウンロードして、インストールする。
- Arduinoにコピーする。> sudo cp -R /usr/local/CrossPack-AVR-20131216/* /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/を実行
- 次にClossPack For AVR (CrossPack-AVR-20131205.dmg)をダウンロードして、インストールする。
- もういちどArduinoにコピーする。 > sudo cp -R /usr/local/CrossPack-AVR-20131205/* /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/を実行
ふざけてんのか!という手順ですので、あまりオススメしない。
何か問題が起こる可能性大。
私ももっと良い方法があれば乗り換えると思うw
4. あれ?board.txtのfuse設定直さずに試したら書き込めなくなった!Fuse壊れた?
shimniokさんが公開してくれているarduino-tinyは、Fuseの値がコピペして修正忘れてる風。(作者には報告した)
全くATTiny841に設定する値と違う値なので、このまま不用意にArduino IDEから「ブートローダーを書き込む」とかやっちゃうと、FUSEの値がおかしくなって、Fuseリセットするまで、そのICには以降ファームが書き込めなくなってしまう。(やっちまったw)
運悪く?Fuseリセットが必要になってしまった慌て者は、面倒だけど下記のようにして救出しよう。
Fuseリセットの方法
基本は、Arduino UNOでATTiny開発してるときに書き込めない!AVR壊れた!?その前にで紹介したATTiny Fuse Reset (Wayne's Tinkering Page)の方法でFuseリセットができる。
上記サイトのATTiny13の回路をATTiny841へ置き換える方法を書いておく。
回路
ATTiny Fuse Reset (Wayne's Tinkering Page)の回路図に登場するATTiny13は、ATTiny841に下記のように置き換えて配線する。
| ATTiny13 | ATTiny841 | 
|---|---|
| PIN1(RESET) | PIN4(RESET) | 
| PIN2(CLKI) | PIN2(CLKI) | 
| PIN4(GND) | PIN14(GND) | 
| PIN5(MOSI) | PIN7(MOSI) | 
| PIN6(MISO) | PIN8(MISO) | 
| PIN7(SCK) | PIN9(SCK) | 
| PIN8(VCC) | PIN1(VCC) | 
たぶんATTiny84/44でも一緒っぽい。試してないけど。
スケッチ
ATTiny Fuse Reset (Wayne's Tinkering Page)のスケッチは、各ICのシグネチャを見て適切なFuse値を書き込むようになっているので、ATTiny841への対応が必要になる。
シグネチャを定義しているところに、下記を追加。
# define  ATTINY841  0x9315  // L: 0x62, H: 0xDF, E: 0xFF   14 pin
次に、loop()の中で、
    } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
               sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) {
となっているところに、先ほどのATTINY841も追加。
    } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
               sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85 ||
               sig == ATTINY841) {
Fuseの値(デフォルト値)は、どうやらATTiny84や85も共通の模様なので、上記条件追加だけで行ける。
これで、救出できたはず。
課題など
とりあえずLチカには成功したけど、まだATTiny841の様々な機能は全然使えてない。
- pins_arduino.hにもう少しまじめに対応
- 各種ライブラリに対応(たぶん自分が使うのしかやらない)
- FUSE変更の方法、これ(「ブートローダーを書き込む」)でいいの?
何かお気づきの点がありましたら教えてください!


