Beaglebone(1)

とりあえずメモ

(1) MacOSXにUSBで接続する

USBに接続->BEAGLE_BONEがマウントされる。
OSX10.7 LionではFTDIドライバが動かない。

http://waxpraxis.tumblr.com/post/16772215153/talking-to-the-beaglebone-with-osx-10-7-lion

64ビットのドライバをインストールして、Info.plistを更新。

cd /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/
mv Info.plist Info.plist.old
cp ~/Downloads/Info.plist .
chmod 644 Info.plist
kextutil ../../FTDIUSBSerialDriver.kext

/dev/tty.usbserial-*B が見えたらOK。

screen /dev/tty.usbserial-*B 115200

GPIOの番号の対応がややわかりにくい。
GPIOの各ポートは32ピンあるので、GPIO1_0~GPIO1_31,GPIO2_0~GPIO2_31,…
ユーザが使えるのはexpansion headerP8,P9のヘッダであるが、
マニュアルBONESRM_latest.pdf p.54, table 8によると
1 GND
2 GND
3 GPIO1_6
4 GPIO1_7
5 GPIO1_2

のようになっている。これを次のように読み替える。
GPIO1_6 -> 32*1+6 = 38
GPIO1_7 -> 32*1+7 = 39
GPIO1_2 -> 32*1+2 = 34

この辺はcloud9を使う場合は別のマクロで処理されているので意識する必要はない。
しかし、ファイルシステムの対応を理解する上では、ある程度UNIXに慣れていると次のようにシェルで動かした方が理解は早いと思うのだが。

(2)shellによるLチカ

# gpio38を開放する
echo 38 > /sys/class/gpio/export
# gpio38をoutputポートにする。 pinMode(38, OUTPUT)みたいな
echo out > /sys/class/gpio/gpio38/direction
# ポートを開放
echo 70 > /sys/class/gpio/export
# gpio70をinputポートにする。
echo in > /sys/class/gpio/gpio70/direction
# 以下にアクセスすると状態を得ることができる high:1, low:0
/sys/class/gpio/gpio38/value
/sys/class/gpio/gpio70/value

LEDを10回点滅させるだけのshell script

#!/bin/sh
# use P8 3pin -> GPIO1_6
# GPIO1_6 = 32*1 + 6 = 38
echo 38 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio38/direction
for i in {1..10}
do
echo 1 > /sys/class/gpio/gpio38/value
sleep 1
echo 0 > /sys/class/gpio/gpio38/value
sleep 0
done
echo 38 > /sys/class/gpio/unexport

(参考)

BeagleBone GPIO (youtube)
http://www.adafruit.com/blog/2012/03/06/beaglebone-gpio

pythonのスクリプト
https://gist.github.com/1986926

C言語による例
https://github.com/nunoalves/BeagleBone-GPIO-in-C

Make: How-To: Get Started with the BeagleBone
http://blog.makezine.com/2012/03/14/how-to-get-started-with-the-beaglebone/

Hardware Interfacing on the BeagleBone
http://www.nathandumont.com/node/250

カテゴリー: BeagleBone

ubuntuでのarduino (3)

昨年書いた「ubuntuでのarduino(2)」から進展があるので追記。
ubuntu-12.04 beta on dynabook AZ(ac100) で主にやりましたが、i386 on virtualboxでも同様。

AC100については以下
https://wiki.ubuntu.com/ARM/TEGRA/AC100
http://cdimage.ubuntu.com/daily-preinstalled/current/

apt-cache search arduino
で検索すると、arduino-mk というパッケージが増えていた。
これは”ubuntuでのarduino(2)”で紹介したMakefileの雛形だが、ard-parse-boardsというperlスクリプトで
boards.txtからボード毎の変数を取り出すようになっている。

プロジェクトのデイレクトリhelloを作り、ソースはhello.ino(hello.pde)に書いて、
make, make uploadとするのは前と同じ。

●Linuxの場合は
Makefileに

BOARD_TAG = uno
ARDUINO_PORT = /dev/ttyACM3 # dmesgなどで調べる
ARDUINO_DIR = /usr/share/arduino
AVRDUDE_ARD_PROGRAMMER = arduino
include /usr/share/arduino/Arduino.mk 

と書くだけで動いた。
ubuntu-12以前の場合は以下のmacの場合と同様にインストールして、Makefileは上と同じでよいはず。

●Macの場合は
http://mjo.tc/atelier/2009/02/arduino-cli.html
からversion 0.8をダウンロードして展開し、ard-parse-boardsを適当な場所にインストールする。

ARDUINO_DIR = /Applications/Arduino.app/Contents/Resources/Java
BOARD_TAG = uno
ARDUINO_PORT = /dev/cu.usb*
include ../Arduino.mk

とするだけでよく、去年よりも自動化が進んだ。

(追記)ライブラリを使う場合は
例:Ethernetライブラリ
ARDUINO_LIBS = Ethernet Ethernet/utility SPI
などを加える。

カテゴリー: Arduino

AVR timer(1)

タイマーについてまとめてみる。タイマーにはノーマルモード、CTCモード、PWMなどあるが今回はノーマルモードに限定する。
参考になるのはLUFAの作者であるDean Camera氏のチュートリアルで
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106
および
http://www.fourwalledcubicle.com/AVRArticles.php
にPDF化された文書もある。

_delay_ms(), _delay_us()などがあるので、遅延するだけなら不要だが、
割り込みを使ってマイコンらしい効果的な使い方ができる。

Timer0 (8bit)

AVRのタイマーには8ビットのタイマー(通常はTimer0)と16ビットのタイマー(Timer1,etc)がある。
まず8ビットタイマーTimer0を使ってみる。
tiny13にはTimer0しかない。(tiny10もTimer0しかないが、16bitで他のCPUではTimer1に相当する。)
また、ArduinoではTimer0はmillis()などで使われている。
以下ではtiny13のFUSEを変更していない状態で考える。デフォルトではクロックを内蔵9.6MHzの8分周で使うので、TCNT0というレジスタは1/1.2MHz=83us毎に増えていき、255の次にオーバーフローして0に戻るということを繰返す。
まず、この仕組みだけを使って最も単純なコードを書いてみる。
256/1200000=21.33msのタイマー(4.7kHz)にしかならないので、Lチカでは点滅しているかどうかわからない。(オシロがあれば確認できる)

割り込みベクタはgrep vect iotn13.hとかで調べると、TIM0_OVF_vectである。(世代によってTIMER0だったり、TIM0だったりするので注意)
他の動作によらずTCNT0がオーバーフローしたときに割り込みが実行される。

タイマーに関するレジスタはTCCR0A, TCCR0B, TIMSK, TIFRなどである。

TCCR0A: Timer/Counter Control Register A

bit 7 6 5 4 3 2 1 0
TCCR0A COM0A1 COM0A0 COM0B1 COM0B0 WGM01 WGM00
default 0 0 0 0 0 0 0 0

TCCR0B: Timer/Counter Control Register B

bit 7 6 5 4 3 2 1 0
TCCR0B FOC0A FOC0B WGM02 CS02 CS01 CS00
default 0 0 0 0 0 0 0 0

TIMSK: Timer/Counter Interrupt Mask Register

bit 7 6 5 4 3 2 1 0
TIMSK TOIE1 OCIE1A OCIE1B ICIE1 OCIE0B TOIE0 OCIE0A
default 0 0 0 0 0 0 0 0

TIFR: Timer/Counter Interrupt Flag Register

bit 7 6 5 4 3 2 1 0
TIFR TOV1 OCF1A OCF1B ICF1 OCF0B TOV0 OCF0A
default 0 0 0 0 0 0 0 0

設定すべきことは
(1)timerのモード(ノーマル、CTC、PWMなど)
(2)クロック分周比
(3)タイマー割り込みの許可(TIMSK0: Timer Interrupt Mask RegisterのTOIE0:Timer/Counter0 Overflow Interrupt Enable)
(4)全ての割り込みの許可(sei)

(1)についてはWGM02:0で行なう。

Waveform Generation Mode Bit

Mode WGM02 WGM01 WGM00 Timer/Counter Mode operation TOP update OCRx at TOV flag set on
0 0 0 0 normal 0xFF immediate MAX
1 0 0 1 PWM, phase correct 0xFF TOP BOTTOM
2 0 1 0 CTC OCR0A immediate MAX
3  0 1 1 Fast PWM 0xFF TOP MAX
4  1 0 0 reserved
5  1 0 1 PWM, phase corect OCR0A TOP BOTTOM
6  1 1 0 reserved
7  1 1 1 Fast PWM OCR0A TOP TOP

(2)についてはCS02:0で行なう。
Clock Select Bit

CS02 CS01 CS00 description
0 0 0 no clock source (Timer/Counter stopped)
0 0 1 clkIO (no prescaling)
0 1 0 clkIO/8
0 1 1 clkIO/64
1 0 0 clkIO/256
1 0 1 clkIO/1024
1 1 0 external clock source on T0. falling edge
1 1 1 external clock source on T0. rising edge

ノーマルモードでWGM02|WGM01|WGM00=000。
プリスケーラなしでCS02|CS01|CS00=001。
タイマーのオーバフロー割り込みを許可(TOIE0=1)することで、TCNT0=255の次にオーバーフローするとISR(TIM0_OVF_vect)が呼ばれる。

// for ATtiny13
#include <avr/io.h>;
#include <avr/interrupt.h>;

ISR(TIM0_OVF_vect)
{
    PORTB ^= (1<<PB0);
}

void init_timer()
{
    TCCR0A = 0; // normal mode
    TCCR0B = (1<<CS00); // prescaler = 1
    TIMSK0 |= (1<<TOIE0);
    //TCNT0 = 0;
}

int main()
{
    DDRB =(1<<PB0);
    init_timer();
    sei(); // enable global interrupts
    while(1) {
    }
}

次に肉眼でも動作がわかるようにしたい。
16bitタイマなら65535まで数えることができるが、8bitタイマでは255が限界なので分周を使う。

TCCR0B = (1<<CS00); // FCPU
TCCR0B = (1<<CS01); // FCPU/8
TCCR0B = (1<<CS01)|(1<<CS00); // FCPU/64
TCCR0B = (1<<CS02); // FCPU/256
TCCR0B = (1<<CS02)|(1<<CS00); // FCPU/1024

のように変えることで、TCNT0の進み方を遅くする。
分周比1024の場合は1tick=1024/120000=85msで256カウントで0.22s(約4.6Hz)になる。

Timer1 (16bit)

16ビットタイマーについても同様だが、tiny13にはないので、以下では定番のtiny2313を使う。
世代によってレジスタ名が微妙に違うので、ヘッダファイルなりデータシートなりで調べる。
上のコードでは
TIM0_OVF_vect → TIMER0_OVF_vect, TIMSK0→TIMSK
などとする。

// for ATtiny2313
#include <avr/io.h>;
#include <avr/interrupt.h>;
ISR(TIMER0_OVF_vect)
{
    PORTB ^= (1<<PB0);
}

void init_timer0()
{
    TCCR0A = 0; // normal mode
    TCCR0B = (1<<CS02)|(1<<CS00); // prescaler 1024
    TIMSK |= (1<<TOIE0);
    TCNT0 = 0;
}

int main()
{
    DDRB = (1<<PB0);
    init_timer0();
    sei();
    while(1) {
    }
    return 0;
}

Timer1の場合も0->1とする程度でほぼ同様に書ける。
ただし、TCNT1は16ビットで0-65535までを取るので、prescalerなしでも54.6ms=18Hzになる。

// for ATtiny2313
#include <avr/io.h>;
#include <avr/interrupt.h>;
ISR(TIMER1_OVF_vect)
{
   PORTB ^= (1<<PB0);
}

void init_timer1()
{
    TCCR1A = 0; // normal mode
    TCCR1B = (1<<CS10);    // prescaler 1
    TIMSK |= (1<<TOIE1);
    //TCNT1 = 0;
}

int main()
{
    DDRB = (1<<PB0);
    init_timer1();
    sei();
    while(1) {
    }
    return 0;
}

2つのLEDを別のタイミングで動かすような場合に_delay_ms()を使うと、かえって難しいが、
割り込みを使えば、設定しておいて、sei()で一気に動き出す。

timer0のレジスタを見ただけでもかなり微妙な名前の違いがあり、一つのコードでいろいろなCPUに使いまわそうとすると、CPUごとに場合分けして書くということになる。そういうときに

#if defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny10__)
    TIMSK0 |= (1<<TOIE0);
#else defined(__AVR_ATtiny2313__)
    TIMSK |= (1<<TOIE0);
#endif

のように書くことである程度ポータブルにできる(が読みにくくなる)。

カテゴリー: AVR

AVR入門(3) ピン入力と割り込み

ピン入力と割り込みの基礎をまとめておく。
ATtiny13を使うが、他のCPUでもほぼ同じである。(ATtiny10はピン数が少なくより制約が大きいが、tiny13のTimer0は8ビットであるのに対し、tiny10のTimer0は16ビットであるといった違いもある。次回はタイマー割り込みを考えている。)

もっとも簡単なのはスイッチ入力であるが、ガイガーカウンタのようなパルス入力も原理は同じである。
機械的なスイッチではバウンスの処理が必要であるが、ここでは省略する。(数msec程度の間にON,OFFを繰り返しが起こるので、割り込みを検出してから短い時間は無効にするなど、工夫が必要)

スイッチを押すとLOW、はなすとHIGHになるようにする回路を考える。スイッチの片側はVCCに10kΩの抵抗を介してプルアップし、スイッチの反対側はGNDに落とす。プルアップされた側をPB1と接続して、スイッチを押すとPB0のLEDが点灯するようにする。

ATtiny13

1 PB5/RESET 8 VCC
2 PB3 7 PB2
3 PB4 6 PB1/INT0
4 GND 5 PB0
#include <avr/io.h>

void led_on()
{
    PORTB |= (1 << PB0);
}
void led_off()
{
    PORTB &= ~(1 << PB0);
}

int main()
{
    DDRB |= (1 << PB0);
    led_off();
    while(1) {
        if (bit_is_set(PINB, 1)) {
            led_off();
        } else {
            led_on();
        }
    }
}

bit_is_setはavr/sfr_defs.hで定義されていて、

#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))

であり、bit_is_set(PINB, 1)は

PINB & (1<<PB1)

と同じで、PINBの1ビット目が1であれば、trueである。

これが普通のやりかたであるが、ずっと変化がないときに毎回ピンの状態をチェックしているのは無駄に思える。
マイコンにはハードウェア割り込みという機能があるので、これを使う方法で書き直してみる。

INT0による割り込み

tiny13では外部割り込みはPB1にINT0が割り当てられている。上で入力にPB1を使ったのはこのためである。
割り込みに関するレジスタは
MCUCR,GIMSK
である。INT0に割り込みがあったときに呼ばれるルーチンは

ISR(INT0_vect)
{
}

に書く。interrupt.hをインクルードする必要がある。

MCUCR: MCU Control Register

Bit 7 6 5 4 3 2 1 0
MCUCR PUID SE SM1 SM0 ISC01 ISC00
ISC01 ISC00
0 0 INT0がLOWのとき割り込みが発生
0 1 INT0に任意の変化で割り込みが発生
1 0 INT0にfalling edge(HIGH→LOW)で割り込みが発生
1 1 INT0にrising edge(LOW→HIGH)で割り込みが発生

GIMSK: General Interrupt Mask Register

Bit 7 6 5 4 3 2 1 0
GIMSK INT0 PCIE

INT0=1のとき、割り込みが有効
(PCIEはINT0以外のPCINT5..0を有効にするときに使う)

以下はINT0=PB1でfalling edge(HIGHからLOWへの変化)の割り込みがあると、
10msだけLEDをONにするだけのコード。whileループでは何もしないことに注意する。

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

ISR(INT0_vect)
{
    PORTB |= (1<<PB0);
    _delay_ms(10);
    PORTB &= ~(1<<PB0);
}

int main()
{
    DDRB |= (1<<PB0);

    MCUCR |= (1<<ISC01);  // falling edge of INT0
    GIMSK |= (1<<INT0);       // enable INT0 interrupt    
    sei(); // enable global interrupts

    while(1) {
    }

    return 0;
}

tiny13を2個用意して、1個は単なる発振(Lチカ)にしておき、その出力をもう1個のtinyのINT0に入力するという風にして、ISC01|ISC00=00,01,10,11の違いをLEDで視覚的に見ることができるので、比較してみるとわかりやすいと思う。

カテゴリー: AVR

WIZ820IO

WIZnetのイーサネットモジュール
http://strawberry-linux.com/catalog/items?code=36018
イーサネットシールドではW5100が使われているが、ブレッドボードでは使いにくい。
以前にもW5100のモジュール(WIZ812MJ)はあったが、バス接続も使えるタイプで2列のため変換基板が必要だった。
大きさとしてもモジュラジャックとほぼ変わらずコンパクトである。
MACアドレスが用意されていないので、使わなくなったLANカードなどから拝借します。(あくまでも実験用)

当初はArduino-0022でしか使えなかったが、WIZnetに連絡した方がいて、Arduino-1.0でも使えるようになった。

SPI接続であるので、基本はMOSI,MISO,SCKであるが、それ以外にSSとRESETと電源まわりの接続が必要。

http://www.wiznet.co.kr/Sub_Modules/en/library/Newsletter_View.asp?PK_NUM=96

上リンク先の図は一見親切ですが、間違っている。PIN mapに従って接続します。

nanoだと小さいブレッドボードでOK

ブレッドボードArduinoだと収まらないので長いやつでこのくらい。3.3Vレギュレータで電源5Vから変換しています。FTDIの3.3Vだと電流が足りないようだ。

WIZ820io Arduino
SS D10
MOSI D11
MISO D12
SCLK D13
RESET RESET
Vin3.3 V3.3
GND GND

ライブラリとデータシートは
http://www.wiznettechnology.com/Sub_Modules/en/product/Product_Detail.asp?cate1=&cate2=&cate3=&pid=1161#tab

のDownloadにある。
library_Arduino_v1.0.zipを展開すると
w5100.cpp, w5100.h
の2つのファイルができるので、これを標準のライブラリと入れ換える。Macの場合は
Arduino.app/Contents/Resources/Java/libraries/Ethernet/utility
にコピーする。念のため、元のファイルはバックアップを取っておく。
実質これだけで後はイーサネットシールドと同様に使える。
もし、イーサネットシールド(W5100)を使う場合は
w5100.hの

#define W5200

をコメントアウトする。
この方法だと他のCPU(tiny,mega644pなど)でもイーサネットが簡単に使えて、2000円位でwebサーバが作れたりします。

Arduino-1.0のEthernet Library

Arduino-1.0からDHCP,DNSが標準装備されている。
また、IPAddressというクラスがhardware/arduino/coresにあり、
これまでは

byte ip[] = {192,168,1,20};

と書いていたものが、

IPAddress ip(192,168,1,20);

という書式で書けるようになった。gateway,subnetも同様。

◯dhcpを使ってIPアドレスを取得する場合は

if (Ethernet.begin(mac)==0) {
    Serial.println("DHCP failed");
    while(1)
      ;
}

◯ネットワーク設定をマニュアルでする場合は
仮に
IPアドレスが192.168.1.10,
DNSサーバ 192.168.1.2,
ゲートウェイ 192.168.1.1,
サブネットマスク255.255.255.0
だとして

IPAddress ip(192,168,1,10);
IPAddress dns(192,168,1,2);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

のように宣言して使える。

◎DNSを使う場合

Ethernet.begin(mac, ip, dns, gateway, subnet);

◎DNSを使わない場合

Ethernet.begin(mac, ip, gateway, subnet);

のようにすることもできる。

DHCPでIPアドレスを取得し、DNSを使って接続する例(exampleのDhcpAddressPrinterとDnsWebClientを参考)

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0x00,0xAA,0xBB,0xCC,0xDE,0x02}; //ボードのMACアドレスを入力する。
char serverName[] = "arduino.cc";

EthernetClient client;

void setup()
{
    Serial.begin(9600);
    if (Ethernet.begin(mac) == 0) {
        Serial.println("Failed to configure Ethernet using DHCP");
        for (;;)
            ;
    }
    Serial.print("My IP address: ");
    for (byte n=0; n<4; n++) {
        Serial.print(Ethernet.localIP()[n], DEC);
        Serial.print(".");
    }
    Serial.println();
    delay(1000);
    Serial.println("connecting..."); 
    if (client.connect(serverName, 80)) {
        Serial.println("connected");
        client.println("GET / HTTP/1.0");
        client.println();
    } else {
        Serial.println("connection failed");
    }
}

void loop()
{
    if (client.available()) {
        char c = client.read();
        Serial.print(c);
    }
    if (!client.connected()) {
        Serial.println();
        Serial.println("disconnecting.");
        client.stop();
        while(1)
         ;
    }
}
カテゴリー: Arduino, AVR

atmega32u4 (3)

(追記 2012/5/20 Leonardoがやっと出ました)
結構ピンの役目が変わっています。Arduino-1.0.1 IDEで正式に対応しましたが、
Adafruitなどのボードを使っていた場合はbootloaderの入れ換えが必要です。

1  PE6          D7
2  UVcc
3  D-
4  D+
5  UGnd
6  UCap
7  VBus
8  PB0          D17 /   SS RXLED / PCINT0
9  PB1          D15 /   SCK / PCINT1
10 PB2          D16 /   MOSI / PCINT2
11 PB3          D14 /   MISO / PCINT3
12 PB7          D11# / PCINT7
13 RESET
14 VCC
15 GND
16 XTAL2
17 XTAL1
18 PD0          D3# / SCL / INT0
19 PD1          D2 / SDA / INT1
20 PD2          D0  /   RXD1 / INT2
21 PD3          D1  /   TXD1 / INT3
22 PD5          TXLED
23 GND
24 AVCC
25 PD4          D4      A6
26 PD6          D12     A11
27 PD7          D6#     A7 / INT6
28 PB4          D8      A8 / PCINT4
29 PB5          D9#     A9 / PCINT5
30 PB6          D10#    A10 / PCINT6
31 PC6          D5#
32 PC7          D13#
33 PE2          HWB
34 VCC
35 GND
36 PF7          A0      D18
37 PF6          A1      D19
38 PF5          A2      D20
39 PF4          A3      D21
40 PF1          A4      D22
41 PF0          A5      D23
42 AREF
43 GND
44 AVCC

Leonardoのアナログピン配列変更

(追記 2011/11/30 結局Arduino 1.0ではLeonardoは見送りとなってしまいました)

(追記 2011/11/09 また変わりました)
https://github.com/arduino/Arduino/commit/f0801e61e6d39aa88f1cc6f6ca89d594e268efa1

2011/11/09時点での配列は以下の通り
7~11の配列がまた入れ替わりました。

obsolete!
1 PE6 - D7
2 UVcc
3 D-
4 D+
5 UGnd
6 UCap
7 VBus
8 PB0 - D14 (SS)  - RXLED / PCINT0
9 PB1 - D15 (SCK) / PCINT1
10 PB2 - D16 (MOSI) / PCINT2
11 PB3 - D17 (MISO)  / PCINT3
12 PB7 - D11#   / PCINT7
13 RESET
14 VCC
15 GND
16 XTAL2
17 XTAL1
18 PD0 - D3# / SCL / INT0
19 PD1 - D2   / SDA / INT1
20 PD2 - D0  / RXD1 / INT2
21 PD3 - D1  / TXD1 / INT3
22 PD5 - TXLED
23 GND
24 AVCC
25 PD4 - D4 - A6
26 PD6 - D12 - A10
27 PD7 - D6# - A7
28 PB4 - D8  - A11 / PCINT4
29 PB5 - D9# - A8 / PCINT5
30 PB6 - D10 - A9 / PCINT6
31 PC6 - D5#
32 PC7 - D13#
33 PE2 - HWB
34 VCC
35 GND
36 PF7 - A0
37 PF6 - A1
38 PF5 - A2
39 PF4 - A3
40 PF1 - A4
41 PF0 - A5
42 AREF
43 GND
44 AVCC

以下の内容は最新ではありません。

2011/11/02の時点でgithubのソース(pins_arduino.h)でArduino Leonardo (ATmega32u4)のピン配列に若干の変更があった模様。(Arduino-1.0RC2には反映されていない)
変更部を赤字で示す。アナログピンにA11を追加し、A6-A11が連続するように変更したようだ。基板を作ってる方には結構な痛手ではないかと。

obsolete!
1 PE6 - D7
2 UVcc
3 D-
4 D+
5 UGnd
6 UCap
7 VBus
8 PB0 - D14 (SS)  - RXLED / PCINT0
9 PB1 - D15 (SCK) / PCINT1
10 PB2 - D16 (MOSI) / PCINT2
11 PB3 - D17 (MISO)  / PCINT3
12 PB7 - D11#   / PCINT7
13 RESET
14 VCC
15 GND
16 XTAL2
17 XTAL1
18 PD0 - D3# / SCL / INT0
19 PD1 - D2   / SDA / INT1
20 PD2 - D0  / RXD1 / INT2
21 PD3 - D1  / TXD1 / INT3
22 PD5 - TXLED
23 GND
24 AVCC
25 PD4 - D4 - A6
26 PD6 - D12 - A7
27 PD7 - D6# - A8
28 PB4 - D8  - A9 / PCINT4
29 PB5 - D9# - A10 / PCINT5
30 PB6 - D10 - A11 / PCINT6
31 PC6 - D5#
32 PC7 - D13#
33 PE2 - HWB
34 VCC
35 GND
36 PF7 - A0
37 PF6 - A1
38 PF5 - A2
39 PF4 - A3
40 PF1 - A4
41 PF0 - A5
42 AREF
43 GND
44 AVCC
カテゴリー: Arduino, AVR

ATmega644p/1284p variants for Arduino-1.0rc1

arduino variantsのつくりかた(仮)の続きです。
(Arduino-1.0RC2が出ています。もうすぐ正式リリースとなりそうです)

SanguinoのコードやkosakaさんのATmega/tiny用hardware.zipなどを参考にしてstandardのpins_arduino.hを修正したところ、ひとまず動きました。

私の動作環境は
・MacOSX(MacBookAir)
・Arduino-1.0RC1
・Sparkfun Pocket Programmer(usbtiny)
ですが、Arduino-1.0RC1が動く環境であれば、他のOS、ISPでも問題ないかと思います。

動作確認したのは
マイコン環境:
ブレッドボード上クリスタルなしのmega644p/8MHz

Arduinoスケッチ:
D0~D31でのBasic/Blinkと
PWM(D3,D4,D12,D13,D14,D15の6本)でAnalog/Fadingが動くことだけです。
(追記 10/28)
Serial(TXD0,RXD0),Serial1(TXD1,RXD1),SoftwareSerialも動きました。

アップロードはUSBtinyでISPの6本と接続し、Tools/ProgrammerでUSBTinyを選択した後、File/UploadUsingProgrammer(Shift+Command+U)を使いました。

WordPressの都合でtxtとかtgzなどをそのままダウンロードできないため、githubに公開しました。
スケッチフォルダのhardware以下に展開して、Arduinoを再起動すると使えるようになります。

まだリリースになっていないArduino-1.0 RC1上の実装ですので、試験的なものです。
上の環境以外では試していないので動作は保証しません。
ISPを使うのであればbootloaderは不要です。また、bootloaderは用意していませんので、シリアルアップロードには対応していません。

https://github.com/stastaka/arduino-1.0-atmegaxx4-variants

カテゴリー: Arduino, AVR

arduino variantsのつくりかた(仮)

(以下の情報はArduino-1.0 RC1の話なので、正式リリースまでに変更される可能性があります)

Arduino-1.0 からこれまでになかったフォルダhardware/arduino/variants/{standard,mega,leonardo}ができている。
もとはhardware/arduino/cores/arduinoにあったpins_arduino.hだけがある。
ここにはマクロや定義があって、

NUM_DIGITAL_PINS 
NUM_ANALOG_INPUTS
analogInputToDigitalPin(p)
digitalPinHasPWM(p)
SS
MOSI
MISO
SCK
SDA
SCL
LED
A0~A7
digitalPinToPCICR(p)
digitalPinToPCICRbit(p)
digitalPinToPCMSK(p)
digitalPinToPCMSKbit(p)
port_to_mode_PGM[]
port_to_output_PGM[]
port_to_input_PGM[]
digital_pin_to_port_PGM[]
digital_pin_to_bit_mask_PGM[]
digital_pin_to_timer_PGM[]

と結構数があるが、これらを定義することで俺様仕様のArduino cloneがつくれる仕組みのようである。必要なファイルは以下の2つだけのようだ。

1. variantsにhogeというディレクトリを作ったとして、使いたいCPUに応じてpins_arduino.hをカスタマイズする。
standardの場合を参考にしながら、データシートを調べる。
PWMがあるピンにはOC0A(→TIMER0A)などと書いてある。
PCICR、PCMSKはPCINTに関係がある。(LeonardoはdigitalPinToPCICRなどが未定義で未完成状態です。SoftwareSerialを使おうとするとエラーが出ました。)
物理ピン(PB0など)と論理ピン(D0など)の対応はdigital_pin_to_port_PGMで定義されている。

2. hardware/boards.txtに

hoge644p8MHz.name=ATmega644P / 8MHz
hoge644p8MHz.upload.protocol=stk500v2
...
hoge644p8MHz.build.mcu=atmega644p
hoge644p8MHz.build.f_cpu=8000000L
hoge644p8MHz.build.core=arduino
hoge644p8MHz.build.variant=hoge
...
...
hoge1284p16MHz.name=ATMega1284P / 16MHz
hoge1284p16MHz.upload.protocol=stk500v2
...
hoge1284p16MHz.build.mcu=atmega1284p
hoge1284p16MHz.build.f_cpu=16000000L
hoge1284p16MHz.build.core=arduino
hoge1284p16MHz.build.variant=hoge

のような書式でビルドに必要な情報を書く。
周波数だけ変えるとか、644p/1284pなどピン配列が共通なものを同じhogeフォルダで共有して、名前で切り替える。
コードについては実際に動かしてから公開します。

ATTinyについては、
http://hlt.media.mit.edu/?p=1229
の最後の方にArduino 1.0 supportというのがある。

ファイル2つでいいという話は既にこちら
http://suz-avr.sblo.jp/article/48387405.html
に書いてありました。

カテゴリー: Arduino, AVR

ATtiny10

米粒AVRとして秋月に登場しました。10個で450円とお安いですが、6ピンのSMDなので老眼一歩手前には目がしんどいです。

6ピンしかないせいもあって、通常のISPは使えずTPIという方法で書き込みます。AVRISPmkIIは対応していますが、usbtiny(Pocket Programmer)は対応していません。USBTiny MKiiは対応するようです。また、aitendoで買えるusbaspは新しいファームウェアにアップデートすれば対応するということですが、そのためにはもう一台ISPライターを持っている必要があります。

今回は仕方なくAVRISPmkIIを使います。
ATtiny10

1 PB0 / TPIDATA 6 PB3 / RESET
2 GND 5 VCC
3 PB1 / TPICLK 4 PB2

TPI

1 DATA 2 VCC
3 CLOCK 4 N.C
5 RESET 6 GND

AVRISPmk2 - tiny10
1 - 1 TPIDATA
2 - 5 RESET
3 - 3 TPICLK
4 -    N.C
5 - 6 RESET
6 - 2 GND

のように接続して、

avrdude -c avrisp2 -p t10 -P usb
avrdude: Device signature = 0x1e9003

と出て動作確認できた。
avrdudeはMacPortsでインストールすると5.10でtiny10にも対応しています。(最近5.11になりました)
しかし、MacPortsもCrossPackもgccは古いので、現時点ではavr-gccを自力でbuildする必要があります。
(追記 2011.12.13) Ubuntu 11.10ではavr-gccのバージョンが4.5.3となっているので、tiny10をコンパイルできる。

クロスコンパイラを作るのはconfigure; makeと単純にはいきません。
Atmelのパッチ置き場は
http://distribute.atmel.no/tools/opensource/avr-gcc/
にあり、またhttp://www.heise.de/ct/projekte/machmit/ctbot/wiki/AVRToolchainというサイトでパッチとコンパイルの手順が出ていたので、参考にしました。

これで楽勝と思いきや、意外なところでつまづき。Lチカをやってもスピードが正しく出ていない。FUSEにクロック設定がないのはなぜ?と思っていたらtwitter情報で、データシートのp.21あたりにあることがわかります。
Register DescriptionのCLKMSR,CLKPSRで設定

CLKMSRはClock Main Settings Registerで
CLKMSR=0x00(Internal 8MHz), 0x01(Internal 128kHz),0x10(External clock)

CLKPSRはClock Prescale Registerで
分周比を設定します。デフォルトは0x03で8分周。0x00で分周なしです。

これを変えるだけではだめで更にCCP=Configuration Change Protectionというレジスタも変更が必要です。(0xD8というシグナチャを書き込む)
本来FUSEで設定するような項目なのでプロテクトを掛けており、シグナチャを変えないと変更できないという仕様みたいです。
8MHzに設定する場合はMakefileで
-DF_CPU=8000000
を指定する。PB0を点滅させるコードは以下のようになり、tiny13よりちょっと面倒です。
他にも_delay_ms(n); でnの値が小さいとコンパイルエラーが出たり、-DF_CPU=1000000でもエラーが出ました。
(追記)このエラーは自分でビルドしたコンパイラに限らず、Ubuntuでインストールされるgcc-4.5.3でも同様でした。

// blink PB0
#include <avr/io.h>
#include <util/delay.h>

#define LED PB0 //or PB1,PB2

int main()
{
    CCP = 0xD8;
    CLKMSR = 0x00;  // internal 8MHz
    CCP = 0xD8;
    CLKPSR = 0x00; // prescale = 1

    DDRB = (1<<LED);
    while(1) {
        PORTB ^= (1<<LED);
        _delay_ms(100);
    }
    return 0;
}
カテゴリー: AVR

atmega32u4 (2)

atmega32u4のつづき

Adafruitからボードが来たので、Leonardo化した。
電源を与えなくてよいのでいつものusbtinyをISPに接続。
$ARDUINO_HOME/hardware/arduino/bootloaders/diskloader
にあるDiskLoader-Leonardo.hex
を書き込むだけでよい。
(avrdudeはmacportsでインストールしてバージョンは5.10、rc1に付属のものは5.11です)

avrdude -c usbtiny -p atmega32u4 -U flash:w:DiskLoader-Leonardo.hex:i

後はusbケーブルを接続して、ボードからLeonardoを選択してポートを選ぶと、
ふつうにArduinoとして使える。
ただし、アップロード前にリセットスイッチを押す必要がある。
ピンの対応関係がわかりにくいが、前に書いた通りで、ボードに合わせると以下のようになる。普通のArduinoのLチカの13番はC7である。

3V		5V
E6	D7      A
B0	D14     F0	A5
B1	D15     F1	A4
B2	D16     F4	A3
B3	D17     F5	A2
D0	D3      F6	A1
D1	D2      F7	A0
D2	D0      C7	D13
D3	D1      C6	D5
D4	D4      B7	D11
D5	TXLED   B6	D10
D6	D12     B5	D9
D7	D6      B4	D8
GND		GND
RST		VCC

起動するとPWMで点滅した後、blinkします。

カテゴリー: Arduino, AVR
カテゴリー
2020年8月
 12
3456789
10111213141516
17181920212223
24252627282930
31