単3電池を長期間(2~3年)もたせるため、これまではPICでSleepとWatch Dog Timer(WDT)を使うようにしていました。今回は、それをやったついでに、Arduinoで同じことができるかを試してみました。上の写真はArduino-UNOからとり出したATmega328P単体を使って実験している様子です。
WDTはマイコンの動きを監視し一定時間以上反応がなければリセットして再起動をする機能です。この記事で書くのは、何が普通でないのかといえば、WDT検出でマイコンをリセットはせず、Sleepの直後にある命令から自動的に再開したいという目的です。これがうまくできれば、別途に割り込みを作らずWDTだけですむので、しかけが単純になりとても便利です。そして、Arduinoでやってみて分かった方法を、まずはこの記事に書いておきたいというわけです。
事の発端は、2階のベランダにスズメ一家が立ち入らないようにするためのちょっとした工作です。
庭で遊んでいるときは雀の学校のようで可愛らしいのですが、どうやら早朝のトイレの教育(?)にベランダを使うというのは感心しません。最近は毎朝欠かさずですから、毎度の掃除はたいへんです。そして、「このベランダには来ないように何とかならない?」と家内に頼まれたわけです^^;
一般的にはCDを吊るすとか、鳥よけテープを使うとか、最悪ではネットを張るとか、方法は色々とあるようです。たぶんですが、いちばん簡単な方法は、眩しい超高輝度白色LEDを付近でチカチカさせることではないでしょうか。勝手な電子マンとしては、早速週末にそれを試すことに。
ベランダに設置して放置し、単3電池を数か月はもたせる必要がありそうで、どうしても省エネ処理が必要です。前に作った次のリンク先のドロボー除けと同じようなものです。
いちばん簡単なドロボー除け(かな?) - 勝手な電子工作・・
そちらは設置してから1年半近くたちますが、未だにどれも単3電池を代えずに完動中。その時はSleepに加えて外付けRCによりクロックの長周期化で、電池が数年間持つようににしたのがうまく実現できていますから。
今回は数か月もたせれば良さそうなので、内蔵クロック(16MHz)で動かすことにして回路を簡素にすることにしました。外付けは超高輝度LEDとその直列抵抗だけです。
超高輝度LEDは10mmφ砲弾型で、20mAで20カンデラも光ります(カタログ仕様)。前に千石電商で購入しました。詳しいデータシートがないので照射角を測ってみると半値角が僅か4.5°の鋭いビームです。最終的にはこれを水平に向けるように設置します。鳥の立場で考えれば、まぶしい目に合うと二度と来ないかと思うからです。
順方向3.3V以上が必要のため4.5V電源とし、10mA程度で点灯させるよう直列抵抗を100Ωにしました。これで消費電流を測るとSleep状態(全体時間の97%)は20μA、点灯状態(3%)はほぼ10mAです。よって平均400μA未満。これだと連続半年はもちそうです。
点滅は次の動画のようになります。動画の後ろのほうでWatchDogが吠えるのでビックリしないでください、冗談にいれてみたのですが^^
このPICプログラムは記事の最後、Arduinoのスケッチの後ろにご参考用につけておきます。
動作確認後、ユニバーサル基板に作り電池ボックスに貼り付けました。ごく簡単なので短時間に3つ作りました。
そして雨除けのため、それぞれ全体をビニールのチャック袋に収めました。
この3つをベランダの長手方向に向けて並べて配置。翌朝はベランダへの来訪はぴたりと止まり、フンが全くありません^^ しめしめ!
とはいえ鳥も頭がよいので、そのうちに慣れてまた来るかもしれません。このまましばらく様子を見ることにします。
さて、省エネアプリケーションに毎度PICアセンブラを持ち出すのもどうかと思うわけですから、今回は同じことをArduinoでやってみるわけです。
省エネが目的なので、Arduino UNOなどの開発ボードのまま動かす(電流ジャンジャン食う)のではなく、UNOでプログラムを書き込んだら、そこからATmega328P単体を取り出して製作に使うわけです。取り出しやすくするためには、UNOに無圧ソケットを挿しておくと楽です。
ATmega328Pを何度も取り出すための、無圧ソケット(ゼロプレッシャーソケット)の上手な取り付け方は、前に次の記事に詳しく書きましたのでご参照ください。
Zoom用かんたん操作ボタンをArduino-UNOで作る(その1) - 勝手な電子工作・・
ちょっと脱線しましたが、本論であるWatch Dog Timerによるリセットを伴わないSleepからの復帰方法についてです。
そもそもWDTは稼働していることをタイマーで見張る番犬なので、起動すればマイコンにリセットがかかる、つまり再起動させる使い方が普通なわけです。それでも省エネアプリケーションを工夫してできないことはないのですが、再起動時にはSleepの次の命令に自動的に戻って欲しいものです。
Watch Dog Timerではなく他の割り込みを使えばできるわけなのですが、毎度それを考えるのも面倒。PICのやり方と同じように、WDTにシステムリセットをしない割り込みとして使えれば、回路もプログラムも簡単になるわけです。
まずATmega328PのデータシートでWatch Dog Timerのあたりを何度も読み返してみました。一番主なところはWDTCSRというコントロールレジスターの使い方です。下の図では文言をカットしてありますが、長々と書かれています。やや複雑なのですがシツコク読みます。
そして、ついにMCUにResetをかけず割り込みだけしてSleepから目覚めそうな方法をUNOで試しました。結構複雑で何度かやりなおしましたが、しつこくやってやっと正解らしき方法にたどり着きました。そのスケッチを後ろにつけておきます。
省エネの電流を測るために、次のようにATmega328P単体用の回路を組みます。
普通に16MHzのクリスタルを使い5Vでテストしたところ、POWER-DOWNさせるSleep時でも80μAほどを消耗します。そこで、Sleepの間はADCへのPower供給を止めるようにしてみたところ、これで26.8μAしか消耗しないことがわかりました。
クロックを遅くするなど更に色々やってみることがあるかとは思いますが、とにかく今後はSleepとWatch Dog Timerの組み合わせだけで、Arduinoでも簡単に省エネ処理ができそう\(^_^)/
次が今回のArduino-UNOのテストスケッチです。その後ろにPICアセンブラーの実プログラムをつけておきます。
/*******************************************************
Watch Dog Timer test for Arduino (ATmega328P)
Initial version 7/18, 2021 by Akira Tominaga
*******************************************************/
#include "avr/sleep.h"
#include "avr/wdt.h"
#define LED 13
void setup() { // ***** Arduino setup() *****
// sleep time definitions for Watch-dog-timer
#define sT1 B00000110 // 1 second
#define sT2 B00000111 // 2 seconds
#define sT4 B00100000 // 4 seconds
#define st8 B00100001 // 8 seconds
#define sleepTime sT4 // select sleep-time from above
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
// for Sleep and Watch-dog-timer
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
setWDT(sleepTime);
}
void loop() { // ***** Arduino loop() *****
digitalWrite(LED, HIGH); // LED on
delay(20); // for 20mS
digitalWrite(LED, LOW); // and off
deepSleep(); // sleep + ADCpower-off
}
ISR(WDT_vect) { // *** Intrpt svc rtn for WDT ISR(vect) *****
} // do nothing here
/**********************************
User defined functions
**********************************/
// ***** Setting Watch dog timer *** setWDT(seconds) *****
void setWDT(byte sleepT) {
sleepT += B00010000; // sleepTime + Enalbe WD-change bit-on
MCUSR &= B11110111; // Prepare WDT-reset-flag in MCU-status-Reg
WDTCSR |= B00011000; // Enable WD-system-reset + WD-change
WDTCSR = sleepT; // Set sleepTime + Enable WD-change
WDTCSR |= B01000000; // Finally, enable WDT-interrrupt
}
// ***** Sleep + Stopp ADC power *** deepSleep() *****
void deepSleep(void) {
ADCSRA &= B01111111; // disable ADC to save power
sleep_enable();
sleep_cpu(); // sleep until WDT-interrup
sleep_disable();
ADCSRA |= B10000000; // enable ADC again
}
// *** End of program
細かい説明は省略させていただきますが、とにかく別途の割り込みのしかけもいらず、短くて簡単ですね。要は単に休ませるというDelayの代わりに所定時間のSleepを入れるだけですから。おそらく4秒のWatchDogTimerだけ用意しておけば、Loopさせることで1分とか10分とかにも対応しやすいかと思います。
このやり方は簡単だしメモリー消費なども殆どない点がよいかと勝手に思います。
もし正確に10分単位などでの計測が必要なら、9分56秒だけスリープさせてから次にRTCの分の値の変化タイミングで処理することなどで精密にできると思います。
次に今回の雀よけPICプログラムをご参考までに載せておきます。
;U210718-WDT-12F1822-V00t.asm As of 7/18, 2021
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Sleep and Restart by WDT for PIC12F1822 V00 ;
; (C)2015-2021 Akira Tominaga, All rights reserved. ;
; Function ;
; 1. Blink bright LED to drive mischievous birds away ;
; Input/output ;
; RA0 LED output ;
; Remarks ;
; 1. Clock = HFINTOSC ( 16MHz) ;
; Hence 1 step = 0.25 micro seconds ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
list p=12F1822 ; list directive to define processor
#include "p12F1822.inc" ; device specific variable definitions
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_SWDTEN & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
; page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Macro definitions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Device dependent Macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DEVset macro
BANKSEL OSCCON ; Bank=1
movlw B'01111010' ; 16MHz and internal oscillator
movwf OSCCON
;
; BANKSEL INTCON ; Interrupt Con (in all banks hence comment)
clrf INTCON ; Disable all interrupts
;
; PORTA initialization
BANKSEL PORTA ; Bank=0
clrf PORTA
; BANKSEL LATA ; Bank=2
; clrf LATA
BANKSEL ANSELA ; Bank=3
clrf ANSELA ; No use of ADC
BANKSEL ADCON0 ; Bank=1
clrf ADCON0 ; No use of ADC
;
BANKSEL TRISA ; Bank=1
movlw B'11111110' ; RA0 is output
movwf TRISA
;
BANKSEL OPTION_REG ; Bank=1
bcf OPTION_REG,7 ; Enable weak pull-up
BANKSEL WPUA ; Bank=4
movlw B'00111110' ; Weak Pull-up for RA 1 to RA5
movwf WPUA ;
;
BANKSEL WDTCON ; Bank=1
clrf WDTCON ; WDT is set by program
;
clrf BSR ; Bank=0
InitP ; Initialize ports
endm
;
InitP macro ; Initialize ports
movlw B'11111110' ; All inputs pulled-up and outputs L
movwf PORTA
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I/O macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For general purpose ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEDon macro ; LED on
goto $+1
bsf PORTdbg,LED
goto $+1
endm
;
LEDoff macro ; LED off
goto $+1
bcf PORTdbg,LED
goto $+1
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Time cosuming macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic macro ;Consume 1 μS only
goto $+1
goto $+1
endm
;
Mic2 macro mic2p ;Consume 2 μS x n
movlw mic2p
call Mic2r
endm
;
Mic2p5 macro mic25p ; Consume 2.5μS x n
movlw mic25p
call Mic25r
endm
;
Mic5 macro mic5p ; Consume 5μS x n
movlw mic5p
call Mic25r
movlw mic5p
call Mic25r
endm
;
Mic50 macro mic50p ; Consume 50μS x n
movlw mic50p
call Mic50r
endm
;
Milli macro millip ; Consume mS x n
movlw millip
call Millir
endm
;
Mil100 macro mil100p ; Consume 100 mS x n
movlw mil100p
call Mil100r
endm
;
Secs macro secsp ; Consume Second x n
movlw secsp
call Secsr
endm
;
Mins macro minsp ; Consume Minute x n
movlw minsp
call Minsr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files and Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cblock H'20'
;
; For Application support
;
; Areas for time consuming subroutines
; Do not change the sequences from Mic5c to Minsc
; if co-used with calculation parameters
Mic25c
Mic50c
Millic
Mil100c
Secsc
Minsc
;
endc
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LedOnT equ D'25' ; LED-on Time(25mS)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For PORTA ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;LED equ 0
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTdbg ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdbg equ PORTA ;
LED equ 0 ; LED for debugging
Trig equ 0 ; DSO trigger pulse port for test use
;
page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Initializing ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0
goto Startp ; Go to start entry
org 4 ; This is Interrupt entry
retfie ;
;
Startp DEVset ; Define ports
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Main program loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mainp nop
;Step1 Blink LED once and wait a second
call WDoffr ; Off watch-dog-timer
LEDon ; Blink LED once
Milli LedOnT ; for LedOnT (25mS)
LEDoff
call WD1Sr ; On watch-dog-timer 1 Sec
sleep ; This includes clrwdt
;
;Step2 Blink LED once again and wait a second
call WDoffr ; Off watch-dog-timer
LEDon ; Blink LED once
Milli LedOnT ; for LedOnT (25mS)
LEDoff
call WD1Sr ; On watch-dog-timer 1Sec
sleep ; This includes clrwdt
;
;Step3 Blink twice with 0.5 sec sleep and wait a few seconds
call WDoffr ; Off watch-dog-timer
LEDon ; Blink LED 1st time
Milli LedOnT ; for LedOnT (25mS)
LEDoff
call WDqSr ; On watch-dog-timer short
sleep ; This includes clrwdt
LEDon ; Blink LED 2ndt time
Milli LedOnT ; for LedOnT (25mS)
LEDoff
call WD1Sr ; On watch-dog-timer long
sleep ; This includes clrwdt
goto Mainp ; Contilue infinite loop
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Watch-dog-timer subrooutines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WDT bit0=0 : WDToff bit0=1 : WDTon
; WDT bit5-1: Time value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set 1-Second WDT ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WD1Sr equ $
BANKSEL WDTCON
movlw B'00010101' ; Enable 1 sec WDT
movwf WDTCON
clrf BSR ; Set Bank=0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set a quarter Second = 256mS WDT;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WDqSr equ $
BANKSEL WDTCON
movlw B'00010001' ; Enable 256mS WDT
movwf WDTCON
clrf BSR ; Set Bank=0
return
;l
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set 8-Second WDT ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WD8Sr equ $
BANKSEL WDTCON
movlw B'00011011' ; Enable 8 sec WDT
movwf WDTCON
clrf BSR ; Set Bank=0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set WDT off ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WDoffr equ $
BANKSEL WDTCON
bcf WDTCON,SWDTEN ; Disable SW Watch Dog Timer
clrf BSR ; Bank = 0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Timing subrooutines for general purposes ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.0 micro S x n (Mic2) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic2r movwf Mic25c ; + Wset + call = 1 micro sec
;
Mic2l decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic2li ; else go out (2nd time 1.75 mic sec)
return
;
Mic2li goto $+1 ; (2nd time 2.25 mic sec)
nop ; (2nd time 2.5 mic sec)
goto Mic2l ; go back (2nd time 3 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.5 micro S x n (Mic2p5) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic25r movwf Mic25c ; + Wset + call = 1 micro sec
nop ; 1.25 micro sec
;
Mic25l nop ; 1.5 micro sec (2nd time 4 mic sec)
decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic25li ; else go out (2nd time 2.25 mic sec)
return
;
Mic25li Mic ; (2nd time 3.25 mic sec)
goto Mic25l ; go back (2nd time 3.75 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 50 Microseconds x n Mic50 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Mic50r movwf Mic50c ; set how many 50 microsec (1 micro sec to here)
nop ; 1.25 micro sec up to here
;
Mic50l Mic2p5 D'19' ; + 47.5 = 48.75 mic sec (2nd time 98.75 mic sec)
nop ; + 0.25 = 49 micro sec (2nd time 99 mic sec)
;
decfsz Mic50c,F ; If exhausted then 1 mic S hereafter
goto Mic50li ; else go out (2nd time 49.75 mic sec)
return
;
;
Mic50li Mic ; (2nd time 50.75 mic sec)
goto Mic50l ; go back (2nd time 51.25 mic sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Milliseconds x n (Milli) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Millir movwf Millic ; set how many 1 mil sec (1 mic S up to here)
nop ; 1.25 micro sec
;
Millil Mic50 D'19' ; + 50 mic x 19 = 951.25 mic S (2nd, 1951.25)
Mic2p5 D'19' ; + 47.5 mic = 998.75 micro S (2nd, 1998.75)
nop ; +0.25 mic = 999 micro sec (2nd, 1999)
;
decfsz Millic,F ; If exhausted then 1 micro sec hereafter
goto Millili ; else go out (2nd, 999.75 mic S)
return
;
Millili Mic ; (2nd time 1000.75 mic S)
goto Millil ; go back (2nd time 1001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 100 Milliseconds x n (Mil100);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mil100r movwf Mil100c ;set how many 100 ms(1 micr sec up to here)
nop ; 1.25 micro sec
;
Milhl Milli D'99' ;+1ms x 99 = 99001.25 micS (2nd,199001.25mic)
Mic50 D'19' ; + 950 mic = 99951.25 micS(2nd.199951.25mic)
Mic2p5 D'19' ; + 47.5 mic = 99998.75micS(2nd,199998.75mic)
nop ; + 0.25 mic = 99999 mic S (2nd,199999 micS)
;
decfsz Mil100c,F ; If exhausted then 1 micro sec hereafter
goto Milhli ; else go out (2nd time, 99999.75 mic S)
return
;
Milhli Mic ; (2nd time, 100000.75 mic S)
goto Milhl ; (2nd time, 100001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Seconds x n (Secs) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Secsr movwf Secsc ; set how many sec ( 1 mic sec up to here)
nop ; 1.25 micro sec
;
Secsl Mil100 D'9' ;
Milli D'99' ; + 999 milli sec = 999001.25 micro sec
;
Mic50 D'19' ; + 950 mic = 999951.25 micro sec
Mic2p5 D'19' ; + 47.5 mic = 999998.75 micro sec
nop ; + 0.25 mic = 999999 micro sec
;
decfsz Secsc,F ; If exhausted then 1 micro sec hereafter
goto Secsli ; else, go out
return
;
Secsli Mic
goto Secsl ; (Second time, Sec + 1.25 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Minutes x n (Mins) ;
; Overhead ignored, that is only ;
; 751.25 Mic S even when 100 Min ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Minsr movwf Minsc ;set how many minutes from parameter
;
Minsl Secs D'60' ; 1 Seconds x 60
decfsz Minsc,F
goto Minsl
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end
出かける寸前に慌てて書いた記事でしたため、行き届かない点があればすみません。省エネが必要な測定などにもしお役に立てば幸いです。
©2021 Akira Tominaga, All rights reserved.