TimerWasseralarm mit ATtiny13          

von Gerd Sinning                       
Elektronik-Labor   Projekte   AVR 

Bei meiner Waschmaschine hatte sich fatalerweise der Abwasserschlauch gelöst. Das habe ich erst gemerkt, als schon alles unter Wasser stand. Also wird, wenn es auch etwas zu spät ist, ein Wasseralarm gebaut. Dieser funktioniert mit einem AT13. Das klingt wie ein Overkill und man könnte das auch mit ein paar 555 Timern bauen, aber so braucht man sehr wenige Bauteile: nur drei, den Controller, einen Wderstand und einen Piezo für den akustischen Alarm. Der Wassersensor ist ein Stück Streifenraster-Platine.

Nach dem Einschalten wartet der AT13 10 Sekunden (Waittime = 10) und geht dann in den sleep mode und überwacht PB3. Ein pin change interrupt an PB3 weckt ihn auf und der Alarm geht los ( Ontime = 15 ; 15 seconds alarm on), danach wartet er wieder 10 Sekunden und geht dann schlafen. Der sleep mode verbraucht wenig Strom, die Batterie (hier 3 x 1,5 Volt) hält lange. Timer0 ist für die Zeiten zuständig, ein 10 ms Interrupt steuert die Sekunden. Nun hat der AT13 keinen zweiten Timer, deshalb wird der Ton für den Piezo so erzeugt, dass PB0 und PB1 mit einem Delay ein- und ausgeschaltet werden. Der Delay wird verändert im Unterprogramm SweepUp, so jault der Piezo wie ein amerikanisches Polizeiauto. Lauter wird es, wenn man den Piezo zwischen PB0 und PB1 anschliesst, die werden gegenphasig angesteuert.

Nun kann man auch einen Ldr an PB3 anschließen, dann geht der Alarm los, wenn Licht auf den Ldr fällt, z. B. als Alarm für eine Schublade oder einen Schrank. Wenn geöffnet wird dann jault der Piezo los und erschreckt jeden. Ohne Piezo und mit einer Led an PB2 lässt sich der Schrank für die Zeit Ontime beleuchten , damit man die Socken findet. Die Einschaltzeit lässt sich dann verlängern, für 60 Sekunden mit Ontime = 60. Die Sekunden zählen bis maximal 255. Alle Zeiten sind parametrisiert und leicht zu ändern, je nach Anwendung.

Das Programm ist in Assembler wegen der sleep mode Steuerung und mit 218 bytes recht kurz, da ist noch viel Platz für Erweiterungen. Neben dem Wasseralarm gibt es viele Möglichkeiten.

Quellenhinweis: datasheet ATtiny13, Atmel.com

Downlaod: Ala13.zip
;***************************************************************************
; AT13 water alarm
;
; goes to sleep mode and waits for pin change interrupt PCINT3 on PB3
; noisy alarm with piezo
; 1.2 MHz clock
;
;
;***************************************************************************
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY;
;
;***************************************************************************
;
; Pinout ATtiny13/ATtiny13V 8-PDIP/SOIC
;
;(PCINT5/RESET/ADC0/dW) PB5 VCC
;(PCINT3/CLKI/ADC3) PB3 PB2 (SCK/ADC1/T0/PCINT2)
;(PCINT4/ADC2) PB4 PB1 (MISO/AIN1/OC0B/INT0/PCINT1)
; GND PB0 (MOSI/AIN0/OC0A/PCINT0)
;
;***************************************************************************
; PB3 input Inpin
;***************************************************************************

.DEVICE ATtiny13 ;for gavrasm V3.3


.equ reload = 256 - 187 ; 10 ms Timer0
.equ Waittime = 10 ; 10 seconds wait before on
.equ Ontime = 15 ; 15 seconds alarm on
.equ Offtime = 10 ; 10 sec wait after alarm


.equ fout1 = PB0 ; output frequ
.equ fout2 = PB1 ; output freq 180
.equ Led2 = PB2 ; output on during alarm
.equ Inpin = PB3 ; input
.equ Led4 = PB4 ; output on during Offtime

.def S = r14
.def T0reload = r15

.def temp = r16
.def countL = r17 ; main timing
.def countSec = r18
.def countdel = r19
.def cntWait = r20
.def counter = r21
.def topcount = r22 ;determines frequency
.def locount = r23
.def second = r24
.def minute = r25


.cseg
.org 0
; Reset-vector to adress 0000
rjmp reset
reti ; INT0addr= 0x0001 External Interrupt 0
rjmp PC_irq ; PCI0addr= 0x0002 Pin change Interrupt
rjmp TIM0_OVF ; OVF0addr= 0x0003 Timer/Counter0 Overflow
reti
reti
reti
reti
reti

;***************************************************************************
;* "TIM0_OVF" - Timer/counter0 overflow interrupt handler
;*
;* The overflow interrupt fires every 10 ms, more or less
;*
;***************************************************************************

TIM0_OVF: in S,sreg ; Updated every 10 ms, calibrate

out TCNT0,T0reload ; for 9.973 ms Interrupt
;sbis PINB, toggle ; skip if set
;sbi PORTB, toggle ; set output
;sbic PINB, toggle ; skip if set
;cbi PORTB, toggle

TIM0_1:
inc countL ; main timing
cpi CountL, 100 ; 100 x 10 ms
brne TIM0_ex
clr countL ; every second
inc countSec ; seconds 0 to 255


TIM0_ex: out sreg,S
reti

;***************************************************************************
;* pin change interrupt
;***************************************************************************

PC_irq: in S,sreg

ldi temp, (0<<SE)
out MCUCR, temp
ldi temp, (0<<PCIE) ; disable pin change interrupts
out GIMSK, temp

ldi temp,0b00010111 ; output, 1 = output , 0 = input
out DDRB,temp ; to data direction register
ldi temp,0b00000011 ; Timer/Counter 0 clocked at CK/64 = 40 us
out TCNT0,T0reload ; for 9.984 ms Interrupt
out TCCR0B,temp ; 1,2 Mhz, turn on
out sreg,S
reti

;***************************************************************************
;* Reset
;***************************************************************************

reset:
; writing the calibration byte to the OSCCAL Register.
; ldi temp,0x70 ; test , config val
; out OSCCAL,temp ; for the clock
nop
nop

ldi temp,0b00000000 ; set PORTB
out PORTB, temp ; 1 = pull-up , 0 = float
ldi temp,0b00010111 ; output, 1 = output , 0 = input
out DDRB,temp ; to data direction register

;***************************************************************************

; timer0 setup:
ldi temp,0b0000010 ; Bit 1 – TOIE0: Timer/Counter0 Overflow Interrupt Enable
out TIFR0,temp ; clear pending Interrupt
out TIMSK0,temp ; in the Timer Interupt Mask Register

ldi temp,0b00000011 ; Timer/Counter 0 clocked at CK/64
out TCCR0B,temp ; 1,2 Mhz
ldi temp, reload ; Timer/Counter 0 reload
out TCNT0,temp ; for 10 ms Interrupt

mov T0reload, temp

sbi AcsR, Acd ; Disable Comparator
sbi ADCSRA, ADEN ; Disable AD

sei ; Enable gobal interrupt


;***************************************************************************
; intro

ldi temp,0b00010100 ; test leds
out PORTB, temp ;
ldi topcount, 255
ldi locount, 200
clr countL
I1:
rcall SweepUp ; 1 beep
cpi countL, 2
brlo I1
ldi temp,0b00000000 ;
out PORTB, temp ; turn off

clr countL
clr countSec
waituntilon:
cpi countSec, Waittime ; wait delay
brlo waituntilon

; main loop

loop:
; turn off:
ldi temp, 0
out PORTB, temp ; all off
out DDRB,temp ; make input, data direction register
out TCCR0B,temp ; stop timer

ldi temp, (1<<PCINT3) ; mask pin change interrupts
out PCMSK, temp ; on PB3
ldi temp, (1<<PCIE) ; Enable pin change interrupts
out GIFR, temp ; clear flag
out GIMSK, temp
; Disable pullups, Enable sleep mode, Sleep => Power Down
ldi temp, (1<<PUD |1<<SE | 1<<SM1 | 0<<SM0)
out MCUCR, temp
sleep

; continue program
clr countL
clr countSec
ldi topcount, 255
ldi locount, 100
sbi portb, Led2 ; led on during alarm
waiton:
rcall SweepUp ; 1 loop
cpi countSec, Ontime ; wait Ontime seconds
brlo waiton
cbi portb, Led2

clr countL
clr countSec
sbi portb, Led4
waitoff:
cpi countSec, Offtime ; wait Offtime seconds
brlo waitoff
cbi portb, Led4

rjmp loop ; loop, sleep again


;***************************************************************************

Delay:
dec countdel ; 1 6*countdel 0,005 ms
nop ; 1
nop ; 1
nop ; 1
brne Delay ; 2
ret

SweepUp:

sbi PORTB, fout1
cbi PORTB, fout2
mov countdel, topcount
rcall Delay
cbi PORTB, fout1
sbi PORTB, fout2
mov countdel, topcount
rcall Delay
dec topcount ; increase frequency
cp topcount, locount ; kHz
brsh SweepUp
cbi PORTB, fout1
cbi PORTB, fout2
ret



 Elektronik-Labor   Projekte   AVR