0

3軸加速度センサ ACA302を使って傾斜を測定

加速度センサーで、重力加速度つまり地球が引っ張るアレをセンシングできます。これで傾斜とか、向きがわかります。

これで俺もMacSaberできる!(やりません)

論文2つsubmitして6時間寝たら明け方目が覚めて、朝9時から授業のグルワでその後研究室で昼寝。

その後ふらふらになりながら、なんとなく1年以上前に買った加速度センサーに挑戦してみた。

マイコンさわるの1ヶ月半ぶりだけど1時間ぐらいであっさり動いた。慣れたもんだ…

SourceCode(avr-gcc)&Video

使ったのは、秋葉原のツクモロボット館などで売ってるスター精密のACA302。価格は2000円ぐらい。

普通加速度センサーは1万円とかのが色々あるんだけど、手が届かないのでコレで。アンプ内蔵型なのでコレ単体でAVR atmega8のADコンバータにぶち込めば動くお手軽感がいい。実にPhysical Computing向け。

とりあえず、傾斜を検出する分には問題ない。

加速度センサ ACA302の実装

Read more

0

AVR – mega8でロータリーエンコーダを回す

2週間ぐらい前の事なので曖昧だが、ATmega8のタイマ/カウンタ1で秋月で100円のインクリメンタル型ロータリーエンコーダーを使ってみた。

DSC00968.jpg

写真下のマイコンは関係無い。

既にTiny26Lでやっている人がいたので参考にしながらさくっと書いた。

ソースコード(AVR-GCC)

んで数日後に書き直した。

ソースコード(AVR-GCC)動画

なんで書き直したかは記憶が定かではないのだが、とりあえず大した違いは無いしどちらも動く。昨日も古い方でデモしてきたばかりだし。

動作設定としてはこんな感じで

/** 動作設定 **/
#define FOSC 8000000 // 8MHz
#define BAUD 9600 // 9600bps
#define MYUBRR FOSC/16/BAUD-1 // UART分周率
volatile char uart_recv_data; // UART受信データ
/** ロータリーエンコーダ設定 **/
volatile char rot_state;
#define ROT_TCNT1 65536-32+1 // 8MHz 1024分周で1ms(1000Hz)

タイマ/カウンタ1を初期化する。main()から1回だけ呼び出す必要がある。

/* タイマ/カウンタ1オーバーフロー割り込み設定 */
void overflow1_init(void){
TCCR1B = (1<<CS12)|(0<<CS11)|(0<<CS10); // 256分周
sbi(TIMSK,TOIE1); // タイマ/カウンタ1オーバーフロー割り込み許可
TCNT1 = ROT_TCNT1; // 1ms毎に割り込み設定(ロータリーエンコーダー用)
}

ロータリーエンコーダー監視スレッド。割り込みなので書いておけば一定時間毎に実行される。

/* タイマ/カウンタ1オーバーフロー割り込み
ロータリーエンコーダー監視用 */
SIGNAL(SIG_OVERFLOW1){
TCNT1 = ROT_TCNT1; // タイマ/カウンタ初期化 1ms毎に割り込み設定
char past_state; // 1回前の状態
past_state = rot_state;
if(bit_is_set(PIND,PD3)){
if(bit_is_set(PIND,PD4)) // HH
rot_state = 1;
else // HL
rot_state = 0;
}
else{
if(bit_is_set(PIND,PD4)) // LH
rot_state = 2;
else // LL
rot_state = 3;
}
if((rot_state+3+1)%3 == past_state){ // 右回り
uart_send_str(&qute;R&qute;);
}
else if((rot_state+3-1)%3 == past_state){ // 左回り
uart_send_str(&qute;L&qute;);
}
}

書いてて10ms毎じゃない気がしてきたが、速い分には問題ないし、他にもタイマを回しているのだったら色々タイミングもずれてくると思うので適宜対処して下さい。

ロータリーエンコーダーの真ん中の足をGNDに接続し、左右の足をそれぞれマイコンのピンに接続。また、左右の足とマイコンのピンの間で、10kΩの抵抗を使ってプルアップする(VCCに接続する)

まあ写真の通り。

インクリメンタル型ロータリーエンコーダーは2本の線で4種類の回転状態を出力する。1クリック回す(カチッと言う)と、4種類の状態が一回りする。

とりあえず状態に0,1,2,3と名前をつけて、10ms毎ぐらいに状態を見に行くと、状態が1増えていたら右に回転、減っていたら左に回転みたいな感じでわかる。

■参考サイト

113.ロータリーエンコーダを使う

2343e-conv

AVR試用記-ロータリーエンコーダ

ELM – 接点入力と処理のコツ – ロータリーエンコーダの使い方

ところでタイマ/カウンタ、以前書いた時はイマイチわかってなかったのだが、タイマ割り込みが発生するのはTCCNxが8bitなら256、16bitなら65536になった時起こるとの事。つまりタイマ/カウンタオーバーフロー割り込みとはそういう事。

TCCNxが増えるタイミングは分周率(TCCRx)で決まる。64分周だったら、64クロック毎に1増える。分周なし、8、64、256、1024分周まで5段階あるのでそれでタイミングを調節できる。

また、TCCNxに直接書き込み、カウンタの初期値を設定する事もできる。これは割り込みが起こった瞬間に次の割り込みに備えて代入しなおす必要がある。

この2種類の方法で割り込みタイミングを操作する。

1

AVR – MEGA8のタイマ/カウンタ0割り込み

今日もatmega8。SIG_OVERFLOW0でのタイマ/カウンタ割込みをやってみたよDSC00830.jpg

PB0のLED点滅はタイマー割り込みで行う。同時にmain()の中のループで、UARTで文字列を送信する。→ソースコード(AVR-GCC)動画(2.1MB)

タイマ/カウンタ0は8bit。mega8には他に16bitのタイマ/カウンタ1(PWM付き)と8bitのタイマ/カウンタ2(PWM付き)があり、3つとも別のタイミングで割り込みを発生させる事ができる。

でもまだ1と2は使ってない。

タイマ0の精度として、TCCR0レジスタで分周率を設定する。

HERO’s Downloadさんより

■やり方

タイマ/カウンタ0の設定関数

/* タイマ/カウンタ0オーバーフロー割り込み設定  */
void overflow0_init(){
TCNT0 = 0; // タイマ0初期値
TCCR0 = (0<<CS02)|(0<<CS01)|(1<<CS00); // 分周率設定 前置分周無し
sbi(TIMSK,TOIE0); // タイマ/カウンタ0オーバーフロー割り込み許可
}

これをmain()から呼び出す。

int main(void){
port_init(); // PORT設定
usart_init(MYUBRR); // USART設定
overflow0_init(); // タイマ/カウンタ0設定
sei(); // 割り込み許可
for(;;){
uart_send_str(&qute;hoge\0&qute;);
}
}

sei(); を忘れずに。

んで割り込み部分

volatile unsigned int led0;
/* タイマ/カウンタ0オーバーフロー割り込み */
SIGNAL(SIG_OVERFLOW0){
led0++;
if(led0 > 1500) LED_SET(); // LED点灯
else LED_CLR(); // LED消灯
if(led0 == 3000){
led0 = 0; // カウント初期化
}
nop(1); // これ入れないと固まる
}

よくわからないけど、nop(int count); という自分で用意した関数を呼び出さないと、main()の中の処理を巻き込んで止まる。

多重割り込みとか?

一応nopの中身

/* No Operation */
void nop(int count){
int i;
for(i = 0; i < count*100; i++){
}
}

そういえばDigi-Key、mega8値上がりしてますか?mega48のが安くなってますね。mega88と同じぐらいの値段。次実装するとしたらmega88かな

PWM6個あるし