そのオリンパスのデジカメで撮ったアサガオ開花動画
いろんな連続写真で遊んでいこうとおもう。
wdtサンプル
_delay_msは電力の無駄なのでwdtでLEDをチカチカさせるサンプル。
// tiny2313V @ 1MHz #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <avr/wdt.h> #include <util/delay.h> /* volatile long timer = 0; ISR(WDT_OVERFLOW_vect) { } */ EMPTY_INTERRUPT(WDT_OVERFLOW_vect); int main(void) { int i; // start WDT cli(); wdt_reset(); MCUSR &= ~(1<<WDRF); // 「WDTリセットされた」フラグクリア WDTCSR |= (1<<WDCE)|(1<<WDE); // wdt変更前処理 #define _WDT_15MS ((0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_30MS ((0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0)) #define _WDT_60MS ((0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(0<<WDP0)) #define _WDT_120MS ((0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(1<<WDP0)) #define _WDT_250MS ((0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_500MS ((0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(1<<WDP0)) #define _WDT_1S ((0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(0<<WDP0)) #define _WDT_2S ((0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0)) #define _WDT_4S ((1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_8S ((1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0)) WDTCSR = (1<<WDIE)|(0<<WDE)|_WDT_1S; // wdt設定 reset=0, interrupt=1, 1sec. sei(); DDRB = 0b00001111; for(i=0;i<5;i++){ PORTB = 0b00001111; _delay_ms(100); PORTB = 0b00000000; _delay_ms(100); } set_sleep_mode(SLEEP_MODE_PWR_DOWN); for(;;){ for(i=0; i<8; i++){ // 0.02mA PORTB = i % 16; sleep_mode(); } for(i=8; i<16; i++){ // 5.5mA-6.0mA PORTB = i % 16; _delay_ms(1000); } } }
参考: http://avrwiki.jpn.ph/wiki.cgi?page=Getting+Started+Notes+%2D+SLEEP
オリンパスのデジカメのリモコンをAVRで作った
オリンパスのリモコンRM-1
のコードを5分おきに送信してシャッターを切ります。
材料
- Atmel AVR Tiny2313V
- 赤外線LEDが1個
- (パスコン)
- 単三電池2本&電池ボックス
// Olympus Remocon #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <avr/wdt.h> #include <util/delay.h> #define nop() __asm__ __volatile__ ("nop") void send_ir(int us, char on) { // 38KHz 1sec=1000ms=1000000us => 38000 // 1000000/38000 = 26.3157895us on/off 13.1578947us // 1MHz => 1sec => 1000000 => 1op=1us for(; 0<=us; us-=26){ PORTB = on ? 0b00000011 : 0b00000000; nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); // ON 12 / OFF 1.. 6 // ON 10 / 3.. 8 // ON 5 / 8..13 PORTB = 0b00000000; nop(); nop(); nop(); nop(); nop(); } } void send_data(char* data, int bits) { int i; int lead_high_len = 9000; int lead_low_len = 4500; int data_high_len = 560; int data_low0_len = 560; int data_low1_len = 1690; int stop_high_len = 560; DDRB = 0b00000011; send_ir(lead_high_len, 1); send_ir(lead_low_len, 0); for(i=0; i<bits; i++){ int on = data[i/8] & (1<<(7-i%8)); send_ir(data_high_len, 1); send_ir(on ? data_low1_len : data_low0_len, 0); } send_ir(stop_high_len, 1); _delay_ms(1000); } EMPTY_INTERRUPT(WDT_OVERFLOW_vect); void init_wdt_interrupt(int interval) { cli(); wdt_reset(); MCUSR &= ~(1<<WDRF); // 「WDTリセットされた」フラグクリア WDTCSR |= (1<<WDCE)|(1<<WDE); // wdt変更前処理 #define _WDT_15MS ((0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_30MS ((0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0)) #define _WDT_60MS ((0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(0<<WDP0)) #define _WDT_120MS ((0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(1<<WDP0)) #define _WDT_250MS ((0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_500MS ((0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(1<<WDP0)) #define _WDT_1S ((0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(0<<WDP0)) #define _WDT_2S ((0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0)) #define _WDT_4S ((1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_8S ((1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0)) WDTCSR = (1<<WDIE)|(0<<WDE)|interval; // wdt設定 reset=0, interrupt=1 sei(); } void main_olympus(void) { char shutter[] = {0b01100001, 0b11011100, 0b10000000, 0b01111111}; char wide[] = {0b01100001, 0b11011100, 0b01000000, 0b10111111}; char tele[] = {0b01100001, 0b11011100, 0b11000000, 0b00111111}; char minus[] = {0b01100001, 0b11011100, 0b00100000, 0b11011111}; char plus[] = {0b01100001, 0b11011100, 0b10100000, 0b01011111}; int i, t; init_wdt_interrupt(_WDT_1S); set_sleep_mode(SLEEP_MODE_PWR_DOWN); for(;;){ send_data(shutter, 32); send_data(shutter, 32); send_data(shutter, 32); for(i=0; i<57; i++){ sleep_mode(); } // 57sec.. for(t=0; t<4; t++){ // 1min x 4. send_data(wide, 32); for(i=0; i<59; i++){ sleep_mode(); } } } } int main(void) { main_olympus(); }
秋月通販で買えるAVRの比較
| tiny2313V | mega88 | mega164P | mega644P | ||
|---|---|---|---|---|---|
| 秋月価格 | 100 | 250 | 400 | 550 | |
| ピン数 | 20 | 28 | 40 | 40 | |
| フラッシュメモリ | 2k | 8k | 16k | 64k | |
| EEPROM | 128 | 512 | 512 | 2048(2k) | |
| SRAM | 128 | 1024(1k) | 1024(1k) | 4096(4k) | |
| タイマー | 8*1,16*1 | 8*2,16*1 | 8*2,16*1 | ← | |
| RTC | - | ○ | ○ | ← | |
| PWM | 4 | 6 | 6 | ← | |
| ADC | - | 6 | 8 | ← | |
| AC | 1 | 8 | 8 | ← | |
| 2線シリアル | USI | TWI | TWI | ← | |
| USART | 1 | 1 | 2 | ← | |
| SPI | USI | SPI | SPI | ← |
AVRホタル
暗いところに持っていくと点滅します。
部品はtiny2313とLEDを1個ずつ。
LEDを光センサーとして使っています。
// AVR Hotaru
#include <avr/io.h>
//#include <avr/interrupt.h>
#include <util/delay.h>
#define nop() __asm__ __volatile__ ("nop")
#define SERIAL_DEBUG 0
#if SERIAL_DEBUG
#define BAUD 2400
//#define SET_PORT(PORT, MASK, VALUE) PORT = (VALUE & MASK)|((~MASK) & PORT)
void usart_init(void)
{
#define _UBRR (F_CPU/16/BAUD-1)
UBRRH = _UBRR>>8;
UBRRL = _UBRR;
UCSRB = 0b00011000;
UCSRC = 0b00000110;
}
#endif
#define LED_DEBUG 1
int main(void)
{
char ac0;
int count = 0;
int on_count = 0;
int on_rate = 0;
int i,j,k;
int bright = 0;
int led_on = 1;
#if SERIAL_DEBUG
usart_init();
#endif
#if LED_DEBUG
DDRD = 0b01111100;
PORTD = 0b00000000;
#endif
for(;;){
// 参考) http://elm-chan.org/junk/leddet/report.html
// LEDポートに短時間"L"レベルを出力して接合容量Cjや浮遊容量Csを放電する。
DDRB = 0b00000001;
PORTB = 0b00000000;
_delay_ms(1);
// LEDポートを入力に設定する→光電流により容量が充電され、入力電圧が直線的に上昇してくる。
DDRB = 0b00000000;
PORTB = 0b00000000;
// 4ms待ってから入射有りか判断
_delay_ms(4);
ac0 = ACSR & 0b00100000;
if(ac0){
on_count++;
}
count++;
if(50<=count){
on_rate = 100*on_count/count; // 50サンプル取って平均
count = 0;
on_count = 0;
}
#if SERIAL_DEBUG
while(!(UCSRA & 0b00100000));
UDR = ac0 ? '*' : '.';
#endif
#if LED_DEBUG
{
unsigned char d = 0;
if(on_rate<45){ d |= (1<<2); }
if(on_rate<40){ d |= (1<<3); }
if(on_rate<35){ d |= (1<<4); }
if(on_rate<30){ d |= (1<<5); }
if(on_rate<25){ d |= (1<<6); }
PORTD = d;
}
#endif
DDRB = 0b00000001;
if(0){
// 閾値でON/OFF
if(on_rate<20){
PORTB = 0b00000001;
}else{
PORTB = 0b00000000;
}
_delay_ms(30);
}else{
// 明るさ 0-100,100-0 のこぎり型に明滅
int b;
bright++;
b = bright;
if(100<bright){
b = 200-bright;
if(200<bright){
bright = 0;
led_on = (on_rate<20);
}
}
//b = 100-on_rate;
for(j=0; j<10; j++){
if(led_on){
PORTB = 0b00000001;
}
for(i=0; i<b; i++){
_delay_ms(0.01);
}
PORTB = 0b00000000;
for(i=0; i<100-b; i++){
_delay_ms(0.01);
}
}
}
}
}
MacにAVR開発環境をつくった
http://www.obdev.at/products/avrmacpack/index.html
No.19 入門用AVR-ISPライター
http://homepage2.nifty.com/denshiken/AVW019.html
用の設定。
# Name: Makefile
# Author: <insert your name here>
# Copyright: <insert your copyright message here>
# License: <insert your license reference here>
# This is a prototype Makefile. Modify it according to your needs.
# You should at least check the settings for
# DEVICE ....... The AVR device you compile for
# CLOCK ........ Target AVR clock rate in Hertz
# OBJECTS ...... The object files created from your source files. This list is
# usually the same as the list of source files with suffix ".o".
# PROGRAMMER ... Options to avrdude which define the hardware you use for
# uploading to the AVR and the interface where this hardware
# is connected.
# FUSES ........ Parameters for avrdude to flash the fuses appropriately.
DEVICE = attiny2313
CLOCK = 1000000
PROGRAMMER = -c avrispv2 -P /dev/tty.usbserial
OBJECTS = main.o
FUSES = -U hfuse:w:0xDF:m -U lfuse:w:0x64:m
# ATTiny2313 fuse bits (fuse bits for other devices are different!):
# WinAVR Extend:0xFF HIGH:0xDF LOW:0x64
# Example for 8 MHz internal oscillator
# Fuse high byte:
# 0xDF = 1 1 0 1 1 1 1 1 <-- 0RSTDISBL (default:1) if set to 0, RESET pin is disabled
# ^ ^ ^ ^ ^ ^ ^------ 1BODLEVEL0 (default:1) --
# | | | | | +-------- 2BODLEVEL1 (default:1) --
# | | | | +---------- 3BODLEVEL2 (default:1) BODLEVEL2-0 : 111 : disable low bat.
# | | | +-------------- 4WDTON (default:1) if set to 0, watchdog is always on
# | | +---------------- 5SPIEN (default:0) if set to 1, serial programming is disabled
# | +------------------ 6EESAVE (default:1) set to 0 to preserve EEPROM over chip erase
# +-------------------- 7DWEN (default:1) debug wire
#
# Fuse low byte:
# 0x64 = 0 1 1 0 0 1 0 0 <-- CKSEL0 (default:0) --
# ^ ^ ^ ^ ^ ^ ^------ CKSEL1 (default:0) --
# | | | | | +-------- CKSEL2 (default:1) --
# | | | | +---------- CKSEL3 (default:0) CKSEL3-0 : 0100 : 8MHz RC
# | | | +-------------- SUT0 (default:0) --
# | | +---------------- SUT1 (default:1) SUT1-2 : 10 : 6*CK 14*CK+64ms
# | +------------------ CKOUT (default:1)
# +-------------------- CKDIV8 (default:0)
# Tune the lines below only if you know what you are doing:
AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)
# symbolic targets:
all: main.hex
.c.o:
$(COMPILE) -c $< -o $@
.S.o:
$(COMPILE) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
.c.s:
$(COMPILE) -S $< -o $@
flash: all
$(AVRDUDE) -U flash:w:main.hex:i
fuse:
$(AVRDUDE) $(FUSES)
# Xcode uses the Makefile targets "", "clean" and "install"
install: flash fuse
# if you use a bootloader, change the command below appropriately:
load: all
bootloadHID main.hex
clean:
rm -f main.hex main.elf $(OBJECTS)
# file targets:
main.elf: $(OBJECTS)
$(COMPILE) -o main.elf $(OBJECTS)
main.hex: main.elf
rm -f main.hex
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
# If you have an EEPROM section, you must also create a hex file for the
# EEPROM and add it to the "flash" target.
# Targets for code debugging and analysis:
disasm: main.elf
avr-objdump -d main.elf
cpp:
$(COMPILE) -E main.c
直接使うときは↓
avrdude -v -c avrispv2 -P /dev/tty.usbserial -p attiny2313 -U flash:w:ISP2313T.hex:i avrdude -vv -c avrispv2 -p t2313 -P /dev/tty.usbserial



