鳥除け器(ひょっとすると画期的!?)
毎朝欠かさずベランダに来てたくさんのフンをしていくスズメ達。前回の記事で書いた鳥除け用ブリンカーを3つ設置後は、なんと全く来なくなりました!ピタッとやんで1週間・・・これが続けばビックリだし拍子抜けですね。
な~んだ、こんなので良かったのか!
世に出回る鳥除けテープや、様々な道具もそのうち併設が必要になるかな?と考えてはいたのですが、今のところはたったのこれだけで済んでいます。
ちなみに、これにまつわる前回の記事は次です。
省エネ用のSleep + Watch Dog Timer(Arduinoでもできる!) - 勝手な電子工作・・
ただ、前の装置は夜中にもピカリと強烈な光を出すため、近所に迷惑そう。暗い時は、鳥が来ないわけなので光らないようにしたい。この際きちんと作り直すことにしました。
明るさ検知用にI2C照度センサーをと考えましたが、何よりもしかけが単純ですむCdSセルを使うことにします。CdSは最近は敬遠され気味ですが、明るさで抵抗値が大きく変わる硫化カドミウム半導体です。 しかも暗い環境でも変化をよく検出します。
CdSの精度は大抵の人が考えるよりも高く、照度と抵抗変化の直線性、ヒステリシスの少なさ、温度補正が通常ほぼ不要な点、などの利点があります。価格は今Aliでみる限りは、1例として次のように20個で72円。送料をいれても1個10円しません。
こういうCdSセンサーの典型的な仕様の例を示します。 本来ずいぶん暗い状態までを測れるのが分かります。
通常の使用範囲(0~30℃)だと、あまり変化せず次のとおり、温度係数は僅か±0.002/℃です。
ただし測定回路には少し工夫を要します。
単に固定Rと直列にして間の分圧をADCに入力する形では、暗い領域内での変化の検知はできません。なぜなら、暗いと1MΩオーダーにも変化するわけなのに、入力抵抗が低い10~20kΩのADCで分圧測定をすることはできないからです(ADCがCdSと並列にはいってしまうためです)。
そこで、測定回路をチョットだけ工夫すれば、暗闇の中でも変化を正確に測定できます。次は筆者のやり方ですが、エミッタフォロワー回路をつなぐもの。これによって測定の入力インピーダンスを100倍以上高めることができます。そして、測定値は正確な分圧-0.65V(Vbe)となり、温度の影響も受けないごく単純な回路でできます。
R1には高抵抗(例:51kΩとか100kΩとか)を安心して使うことができます。R2を3kΩ程度にすればADC入力インピーダンスの影響が防げます。トランジスタはNPN型ならこの型に限りませんが、要するにインピーダンス変換をするわけです。
そして次の回路にしてArduinoで実験しました。
D2ピンから先ほどの回路へ電力供給をオンオフしますが、2mA未満なので問題ないです。そしてエミッタフォロワーの出力(上図でDarkness)をA3ピンで読みます。値が高いほど暗いわけです。
Arduinoのテストプログラムは次のものです。
/*******************************************************
Bird-Guard-Blinker for Arduino-Uno (ATmega328P)
Initial version V00 7/24, 2021 (c) Akira Tominaga
Function:
Blink bright LED to expel birds away
-Stop blinks if in enough dark environment.
-Save battery energy by deep-sleep
*******************************************************/
#include "avr/sleep.h"
#include "avr/wdt.h"
#define LED 9 // super bright LED
#define CdSval A3 // darkness val. w/ CdS circuit
#define CdSpwr 2 // Power supply for CdS circuit
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 sTQ B00000100 // 1/4 second
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(CdSpwr, OUTPUT);
digitalWrite(CdSpwr, LOW);
Serial.begin(9600);
// for Sleep and Watch-dog-timer
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
void loop() { // ***** Arduino loop() *****
#define cdsPon 40 // CdS power-on time before ADC
#define LEDoT 25 // LED-on time = 25mS
digitalWrite(CdSpwr, HIGH);
delay(cdsPon); // wait for stability
uint16_t Darkness = analogRead(CdSval);
digitalWrite(CdSpwr, LOW);
//Serial.print("Darkness=");
//Serial.println(Darkness);
if (Darkness <= 767) { // if not dark (<= 75% Vref)
// *** Step1: LED-on once and wait 1 sec
digitalWrite(LED, HIGH);// LED on
delay(LEDoT); //
digitalWrite(LED, LOW); // and off
deepSleep(sT1); // sleep + ADCpower-off
// ** Step2: LED-on once again and wait 1 sec
digitalWrite(LED, HIGH);// LED on
delay(LEDoT); //
digitalWrite(LED, LOW); // and off
deepSleep(sT1); // sleep + ADCpower-off
// ** Step: LED-on twice with short sleep, & 2 sec
digitalWrite(LED, HIGH);// LED on
delay(LEDoT); //
digitalWrite(LED, LOW); // and off
deepSleep(sTQ); // sleep + ADCpower-off
digitalWrite(LED, HIGH);// LED on
delay(LEDoT); //
digitalWrite(LED, LOW); // and off
deepSleep(sT2); // sleep + ADCpower-off
} else { // if dark enough, sleep for a minute
for (uint8_t n=0;n<15;n++){
deepSleep(sT4);
}
}
}
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 + Stop ADC pwr *** deepSleep(WDtime) *****
void deepSleep(byte WDtime) {
setWDT(WDtime);
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
色々実験してOK!
月夜など明るい夜もあるため、回路を消灯する暗さは真っ暗闇よりは少し明るく設定しています。使う場所にもよるでしょう。場合によってはR1を200kΩの可変抵抗にするなどして、いちいちプログラムで調整しない手もあるでしょうね。
よし、これならPICで作ればさらに小さくてすむなと、8ピンPICで次のようにしてみます。
だいぶ小さくできそうですね。もっとも8pinのAVRでもなんでも良いわけですが手持ちがないだけなのです^^;
ブレッドボードでの比較は次です。下がPICの配線ですが右上RA5からの小LEDはデバッグ用で、完成したら外します。そうすると消灯用以外の回路はほぼ何もないのは同様です。
PICのプログラム(アセンブラー)は次のとおり。デバッグ用のルーチンは使ってないですがつけたままです。外してかまいませんが。
;U210724-Bird-Guard-Blinker-CdS-WDT-12F1822-V00.asm As of 7/24, 2021
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Bird-Guard Blinker for PIC12F1822 V00 ;
; (C)2021 Akira Tominaga, All rights reserved. ;
; Initial Version 00 on July 24, 2021 ;
; Function ;
; 1. Blink bright LED to expel birds away ;
; stop blinking in very dark environment ;
; Save battery energy using sleep+Watch-dog-Timer ;
; Input/output ;
; RA0 LED output to super bright LED ;
; AN2(Ra2) AD input from CdS-circuit (Dark >= half Vdd) ;
; RA4 Power supply to CdS-circuit ;
; 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 TRISA ; Bank=1
movlw B'11001110' ; RA0, RA4-5 are output
movwf TRISA
;
BANKSEL ANSELA ; Bank=3
movlw B'00000100' ; AN2(RA2) is analog input
movwf ANSELA ; set it to ANSELA
BANKSEL FVRCON ; Bank=2
clrf FVRCON ; Not use Fixed Voltage Reference
;
BANKSEL ADCON0 ; Bank=1
movlw B'00001000' ; Analog channel AN2 and ADON 0(disabled)
movwf ADCON0 ;
; BANKSEL ADCON1 ; ADCONs in Bank1, hence comment
movlw B'00100000' ; Leftjustified, Fosc/32, Reference Vdd
movwf ADCON1 ;
; BANKSEL ADRESH ; ADC Registeres in Bank1, hence comment
clrf ADRESH ;
; BANKSEL ADRESL ; ADC Registeres are in Bank1, hence commen
clrf ADRESL ;
BANKSEL OPTION_REG ; Bank=1
bcf OPTION_REG,7 ; Enable weak pull-up
BANKSEL WPUA ; Bank=4
movlw B'00001010' ; Weak Pull-up RA1and RA3
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'11001010' ; All inputs pulled-up and outputs & ADC L
movwf PORTA
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; General purpose macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEDon macro ; LED on
goto $+1
bsf PORTA,LED
goto $+1
endm
;
LEDoff macro ; LED off
goto $+1
bcf PORTA,LED
goto $+1
endm
;
WDTt macro tLen ; Set WDT 1, 2, 4 or 0(1/4) Sec
if tLen==1
movlw B'00010101' ; Set 1-sec WDT
endif
if tLen==2
movlw B'00010111' ; Set 2-sec WDT
endif
if tLen==4
movlw B'00011001' ; Set 4-sec WDT
endif
if tLen==0
movlw B'00010001' ; Set a-quarter-sec WDT
endif
call WDTtr
endm
;
WDToff macro ; Off the WDT
call WDoffr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Comparison macro ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare A w/ literal and branch to Large, or Others
CalLO macro Aadr,Blit,Ladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto $+3 ; If A<B goto Others
btfss STATUS,Z ; A=B? Yes skip next
goto Ladr ; If A>B goto Laddr
; ; If A≦B then next (here)
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
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Debug and Abend macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dLEDon macro ; dLED on
goto $+1
bsf PORTdbg,dLED
goto $+1
endm
;
dLEDoff macro ; dLED off
goto $+1
bcf PORTdbg,dLED
goto $+1
endm
;
Udebug macro Area
movf Area,W
call Udbgr
endm
;
Ustop macro ; Stop until Sw2 on (=L)
call Udstopr ;
endm
;
Trigger macro ; DSO external trigger
goto $+1
bsf PORTtrg,Trig
Mic2
bcf PORTtrg,Trig
goto $+1
endm
;
Uabend macro abn ; User Abnormal-end number
movlw abn
goto Uabendr
endm
;
Ublink macro bno ; Blink LED for specified times
movlw bno
call Ublinkr
endm
;
Ucp macro CPNo ; Check point literal chr to display to LCD
movlw CPNo
movwf Ucpc
Udebug Ucpc
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files and Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cblock H'20'
;
; For Application support
MeasH ; Measured high byte
MeasL ; Measured low byte
SkipC ; Counter for bypassing blinks
;
; Areas for time consuming subroutines
Mic25c
Mic50c
Millic
Mil100c
Secsc
Minsc
;
; Areas for debugging routine
DmpA ; Display byte area
Dmp8C ; Bit counter for loop (Initial Dmp8V =8)
BlinkC ; Counter for blinking (set for Debugb or Abendb)
Abendn ; Abend number
Ucpc ; User Check point chr to trace
;
endc
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LedOnT equ D'25' ; LED-on Time(25mS)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For PORTA ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LED equ 0 ; LED @ PORTdbg
Dkns equ 2 ; Darkness value
CdSpwr equ 4 ; Power for CdS circuit
;dLED equ 5 ; for debug
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTdbg ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdbg equ PORTA ;
dLED equ 5 ; LED for debugging
Trig equ 5 ; DSO trigger pulse port for test use
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Values ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Dark equ D'191' ; Min. threshold of darkness (>=2.5V)
SkipS equ D'15' ; Skipping 15x4 seconds when dark enough
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For Debug ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Dmp8V equ D'8' ; Debug display bit counter initial value
Debugb equ D'8' ; number of blinkings to show Debugging
Abendb equ D'30' ; number of blinkings to notify Abend
;
page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Initializing ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0
goto Startp ; Go to start entry
org 4 ; This is Interrupt entry
retfie ;
;
Startp DEVset ; Define ports
call CdSpOn ; Prepare CdS circuit power
dLEDon
Mil100 5 ;
dLEDoff
Mil100 5
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Main program loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mainp nop
;Step0 Measure darkness and skip if dark enough
call CdSpOn ; Power on the CdS circuit
call Measr ; Measure the darkness level
call CdSpOff ; Power off the CdS circuit
CalLO MeasH,Dark,Skipr ; If not dark go on, else stop blinks
;
;Step1 Blink LED once and wait a second
WDToff ; Off watch-dog-timer
LEDon ; Blink LED once
Milli LedOnT ; for LedOnT (25mS)
LEDoff
WDTt 1 ; On watch-dog-timer 1 Sec
sleep ; This includes clrwdt
WDToff ; Restart without WDT
;
;Step2 Blink LED once again and wait a second
LEDon ; Blink LED once
Milli LedOnT ; for LedOnT (25mS)
LEDoff
WDTt 1 ; On watch-dog-timer 1Sec
sleep ; This includes clrwdt
WDToff ; Restart without WDT
;
;Step3 Blink twice with 0.25 sec sleep and wait a few seconds
LEDon ; Blink LED 1st time
Milli LedOnT ; for LedOnT (25mS)
LEDoff
WDTt 0 ; On watch-dog-timer 1/4 Sec
sleep ; This includes clrwdt
WDToff ; Restart without WDT
LEDon ; Blink LED 2ndt time
Milli LedOnT ; for LedOnT (25mS)
LEDoff
WDTt 2 ; On watch-dog-timer 2 Sec long
sleep ; This includes clrwdt
WDToff ; Restart without WDT
goto Mainp ; Contilue infinite loop
;
Skipr movlw SkipS ; Get skip-time (# of 4 seconds)
movwf SkipC ; Set it to counter
Skiprl WDTt 4 ; Set 4 sec WDT
sleep ; Sleep for 4 sec
WDToff ; Restart without WDT
decfsz SkipC,F ; Done ?
goto Skiprl ; No, loop WD4 x n (SkipS number)
goto Mainp ; Yes, return to main loop
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Measuring with CdS + Tr (emitter follower) circuit ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Power on/off routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CdSpOn bsf PORTA,CdSpwr ; Cds circuit power on
Milli D'40' ; Stabilize power
return
;
CdSpOff bcf PORTA,CdSpwr ; CdS circuit power off
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Measuring routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Measr equ $
BANKSEL ADCON0 ; Bank=ADCON0(Bank1)
bsf ADCON0,ADON ; ADON (bit0)
clrf BSR ; Bank=0
Mic5 D'4' ; Wait for more than 15 micro secs
;
BANKSEL ADCON0
bsf ADCON0,ADGO ; Start AD conversion
btfsc ADCON0,ADGO ; Check if ADGO on
goto $-1 ; If still on, then continue to inquire it
;
BANKSEL ADRESH
movf ADRESH,W ; Get ADRESH content
clrf BSR ; Point Bank 0
movwf MeasH ; Move it to MeasH
;
BANKSEL ADRESL
movf ADRESL,W ; Get ADRESL content
clrf BSR ; Point Bank 0
movwf MeasL ; Move it to MeasL
;
BANKSEL ADCON0
bcf ADCON0,ADON ; Cut analog connection
clrf BSR ; Bank=0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Watch-dog-timer subrooutines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WDT bit0=0 : WDToff bit0=1 : WDTon
; WDT bit5-1: Time value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set specified length of WDT ;
; Called by WDTt macro ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WDTtr equ $
BANKSEL WDTCON
movwf WDTCON
clrf BSR ; Set Bank=0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set WDT off ;
; Called by WDToff macro ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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
;
space
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Followings are for debugging purpose only ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; User debug to show a specified byte ;
; on dLED for debuggng purpose ;
; shown from bit 7 to 0 ;
; called by Udebug macro ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Udbgr clrf BSR ; Set Bank=0
movwf DmpA ; move data to Dmpa
movlw Dmp8V ; set counter 8
movwf Dmp8C ; to Dmp8C
;
Udblp Ublink Debugb ; Blink for Debugging = 8 times
btfsc DmpA,7 ; check top bit 7
goto UdbOn ; if on then to UdbOn
dLEDoff ; Show 0
Mil100 D'10' ;
goto Udbeck
;
UdbOn dLEDon
Mil100 D'10' ;
dLEDoff
Udbeck decfsz Dmp8C,F
goto Udbnext ;if not end, next
Ublink 4 ;if end, blink 4 times and
Mil100 D'30' ; blank for 3 seconds to take memo
return
;
Udbnext rlf DmpA,F ; shift for next bit
goto Udblp ; loop for next bit
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Blinking to indicate debugging mode ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Ublinkr movwf BlinkC
Ublinkl dLEDon ; dLED on
Milli D'15' ; for 15ms
dLEDoff ; dLED off
Milli D'60' ; for 60ms
decfsz BlinkC,F ; check blinking counter
goto Ublinkl ; if not exhausted, loop
return ; exhausted, return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Abend (abnormal end) routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Uabendr clrf BSR
movwf Abendn ; Set Uabend number
Ublink Abendb ; Blinking 30 times
Udebug Abendn ; Show Abend number
goto $
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end
テストの結果は特に問題なく完成。これで基板を4つ作ることにしました。といってもそれぞれ25mm x 16mmのごく小さな基板です。
例によって卓上CNCルーターで生基板から削り出します。
そして20分もかからずに削り終えたのが次。
カットして急いではんだ付けし4つを完成。
電池ボックス(単3 x 3 = 4.5V)に貼り付けたものを、防水用にチャック袋に入れてできあがり。徹底的に省エネなので電池は半年以上は持つ計算です。
今回は試しにチャック袋を二重にかぶせてみました。前の場所(2Fベランダ)の両端から長手方向に中を向けて2つずつで照らすようにしました。
本日まで+2日もスズメは全く来ませんでした^^
余談ですが、調べてみると暗いと見えないトリメとは、本当は鶏目の意味のようで、ニワトリなどキジ科の鳥だけのことなのだそうです。そしてスズメやムクドリなどは人間と同じくらいに見えているそうな。
よって、明け方や夕方のうす暗い時でも来ないようにするには、各プログラム中に定義したDarknessの値をもう少し大きくするほうが良いのかもしれません。
それにしても、こんなので鳥除けができるとは・・・。
カカシみたいに慣れると来るようなことがないか、しばらくさらに様子をみるとします。今回はスズメを寄せ付けていないのに気をよくしています。もちろん、他の鳥でどうなのかは不明ですよ^^;
皆様、必要に応じてお試しあれ。非常に明るいLEDが要りますが、最近はLEDテープも結構明るいですよね。もし試されたら結果などをコメントで教えてもらえると嬉しいです。
では今回はこのへんで。皆様のなんらかのお役に立てば幸い。
以下 2021.7.30追記:
その後も鳥を全く寄せ付けず、これだけで問題なさそうです\(^_^)/。
よって、きちんと防水ケースにセットしました。回路基板の貼り付け位置は都合の良い位置にずらしました。
ついでにDarkの限界値もVref(=Vcc)の75%ほどに上げて設定しました。これでうす暗い状態まではちゃんと働き、さらに暗いとSleepします。上に掲げたプログラム両方の該当箇所の値を更新しておきます。
防水ケースは百均タッパウェアの一番小さなもの(数年前、たしかセリアで4つで百円^^; これだと大きさがぴったり、しかも側面が透明なので目的に合うしなかなか良いですね)。
これを2Fバルコニーの両端に設置。
上の写真ではわかりにくいですが、次の写真のようにエアコン室外機の下に2つずつです。晴れた日は日照が強いため、 少しでも陰になるように。前と横のパンチホールを通る日差しも結構きついので。
そしてバルコニーの反対方向にも同じように設置。
これだけで、約 6m x 1m のバルコニーのスズメ除けになるとは思いもよりませんでした!
そして照度計測時と超高輝度LED照射時以外はSleepしているし、夜もSleepしているので、単3アルカリ電池は1年以上もつ計算になると思います。
とりあえずメデタシ メデタシ!
今後もし鳥がきたりしたらここに書き足そうと思います^^。
©2021 Akira Tominaga, All rights reserved.