• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

Reaktives Licht mit Atmel AVR

Windi

Geoguru
Bei McDoof gibt es derzeit eine Art Reaktvilicht bzw. -sound.
Beim Happymeal für Kinder gibt es einen Bewegungsmelder. Dieser reagiert auf Lichtänderungen. Aus den Kinderzimmern piepst es seit heute Mittag permanent. Könnte man vielleicht sogar für einen Cache verwursteln.
 

gomerffm

Geocacher
Bei McDoof gibt es derzeit eine Art Reaktvilicht bzw. -sound.
Beim Happymeal für Kinder gibt es einen Bewegungsmelder. Dieser reagiert auf Lichtänderungen. Aus den Kinderzimmern piepst es seit heute Mittag permanent

hab mit meinen kids auch so zwei Teile erworben...
funktionieren aber nur wenns hell ist...
könnte sowas ja ggf. mit dem AD-Wandler des Tiny´s und ner Fotodiode (vielleicht tuts ja auch ne normale LED -die geben ja auch etwas Spannung ab wenns hell ist-) nachbilden....
mal schauen
 

eigengott

Geowizard
Wer es lieber Hardcore mag: Windis Reaktivlicht in Assembler.

Code:
;
; Reaktive light with Atmel AT Tiny 13
; Inspired by Windi
;
.nolist
.include "tn13def.inc"
.list

.def	mp = R16
.def	ldr_l = R17
.def	ldr_h = R18
.def	old_ldr_l = R19
.def	old_ldr_h = R20
.def	daycount = R21
.def	dayblink = R22
.def	param = R23
.def	temp_l = R24
.def	temp_h = R25

.equ	THRESHOLD = 50
.equ	DAYTIME_THRESHOLD = 800
.equ	DAYTIME_CHECKS = 200
.equ	DAYBLINK_PAUSES = 8

.equ	LED_OUT = PORTB3
.equ	LDR_IN = PORTB4

.equ	DELAY_16ms	= 0
.equ	DELAY_32ms	= 1
.equ	DELAY_64ms	= 2
.equ	DELAY_125ms	= 3
.equ	DELAY_250ms	= 4
.equ	DELAY_500ms	= 5
.equ	DELAY_1s	= 6
.equ	DELAY_2s	= 7
.equ	DELAY_4s	= 32
.equ	DELAY_8s	= 33

;
; Interrupt vectors
;
.cseg
	rjmp main		; Reset handler
.org WDTaddr
	reti			; Watchdog handler
.org ADCCaddr
	reti			; ADC handler

;
; Main program
;
main:
;
; Setup stack pointer
;
	ldi mp, low(RAMEND)
	out SPL, mp

;
; Set clock prescaler to /16
;
	ldi mp, 0b10000000
	out CLKPR, mp
	ldi mp, 0b00000100
	out CLKPR, mp

;
; Disable Analog Comparator and reference voltage
;
	sbi ACSR, ACD
	cbi ACSR, AINBG

;
; Setup sleep mode to power-down mode
;
	ldi mp, (1<<SE) | (1<<SM1) | (0<<SM0) | (0<<PUD)
	out MCUCR, mp
	
;
; Set LED as output, all other pins to input
;
	ldi	mp, (1<<LED_OUT)
	out	DDRB, mp
	out PORTB, mp

;
; Configure ADC
;
	ldi mp, (0<<REFS0) | (1<<MUX1) | (0<<MUX0) | (0<<ADLAR)
	out ADMUX, mp
	ldi mp, (1<<ADTS2)
	out ADCSRB, mp
	ldi mp, (1<<ADC2D)
	out DIDR0, mp

; Initalize daytime and old LDR values
	ldi dayblink, DAYBLINK_PAUSES
	ldi daycount, DAYTIME_CHECKS
	ldi old_ldr_l, low(1023)
	ldi old_ldr_h, high(1023)
;
; Main loop
;
main_loop:
; Short delay between measurements (disable for long distance?)
	ldi param, DELAY_125ms
	rcall delay

; Read LDR value
	rcall read_ldr

; Check if difference to old LDR value is above threshold
	mov temp_l, ldr_l
	mov temp_h, ldr_h
	sub temp_l, old_ldr_l
	sbc temp_h, old_ldr_h
	mov old_ldr_l, ldr_l
	mov old_ldr_h, ldr_h
	cpi temp_l, low(THRESHOLD)
	ldi mp, high(THRESHOLD)
	cpc temp_h, mp
	brlt no_blink

; Above threshold, let LED blink ten times and reset old LDR value
	ldi param, 10
	rcall blink_led
	ldi old_ldr_l, low(1023)
	ldi old_ldr_h, high(1023)

; Check if LDR value is above daytime threshold
no_blink:
	cpi ldr_l, low(DAYTIME_THRESHOLD)
	ldi mp, high(DAYTIME_THRESHOLD)
	cpc ldr_h, mp
	brlt nighttime

; Above daytime threshold, decrease daycount if it isn't already zero
	tst daycount
	breq daytime_check
	dec daycount
	rjmp daytime_check
nighttime:
	ldi daycount, DAYTIME_CHECKS
daytime_check:
; If LD has been over daytime threshold for along time,
; pause a bit and blink once in a while
	tst daycount
	brne main_loop
	ldi param, DELAY_8s
	rcall delay
	dec dayblink
	brne main_loop
	ldi param, 1
	rcall blink_led
	ldi dayblink, DAYBLINK_PAUSES
	rjmp main_loop

;
; Read LDR value via ADC
;
read_ldr:
	push mp
	ldi mp, (1<<ADEN) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
	out ADCSRA, mp
	ldi mp, (1<<SE) | (0<<SM1) | (1<<SM0) | (0<<PUD)
	out MCUCR, mp
	sleep
	cli
	in ldr_l, ADCL
	in ldr_h, ADCH
	ldi mp, (0<<ADEN)
	out ADCSRA, mp
	ldi mp, (1<<SE) | (1<<SM1) | (0<<SM0) | (0<<PUD)
	out MCUCR, mp
	sei
	pop mp
	ret

;
; Let LED blink "blinks" times
;
blink_led:
	push mp
	push param
	mov mp, param
blink_loop:
	cbi PORTB, LED_OUT
	ldi param, DELAY_32ms
	rcall delay
	sbi PORTB, LED_OUT
	ldi param, DELAY_125ms
	rcall delay
	dec mp
	brne blink_loop
	pop param
	pop mp
	ret

;
; Delay subroutine
;
delay:
	push mp

; Setup watchdog timer
	cli
	wdr
	ldi mp, (1<<WDCE) | (1<<WDE)
	out WDTCR, mp
	mov mp, param
	ori mp, (0<<WDCE) | (0<<WDE) | (1<<WDTIE)
	out WDTCR, mp
	sei

; Delay
	sleep

; Stop watchdog timer
	cli
    wdr
	ldi mp, (1<<WDCE) | (1<<WDE)
	out WDTCR, mp
	ldi mp, (0<<WDE)
	out WDTCR, mp
	sei
	pop mp
	ret
 

huirad

Geocacher
Da in einem anderen Thread gerade wieder über Atmel AVR Programmieradapter diskutiert wird:

Ich habe mir für meine Experimente mit dem ATTiny13 einen einfachen Programmieradapter für die serielle Schnittstelle selber gebaut. Der Materialeinsatz ist recht gering (5 Winderstände, 2-3 Dioden, 1 Transistor).

Bauanleitungen dafür gibt es im Internet, z.B. hier oder hier. Ich habe für meinen Aufbau die Schaltung aus dem Pollin Bausatz übernommmen, die auf dem gleichen Prinzip basiert.

Als Programmiersoftware habe ich ausprobiert:
1.) Mit grafischer Bedienoberfläche für Windows: PonyProg. Die offizielle Ponyprog Version unterstützt den ATTiny13 leider noch nicht, eine speziell angepasste Version gibt es hier
2.) Kommandozeilentool, für verschiedene Betriebssysteme verfügbar: AVRDUDE. Für Windows, z.B. in der
WinAVR Distribution enthalten. Achtung: Die AVRDUDE Version (5.1) aus der derzeit aktuellen PortableWinAVR Distribution hat noch einen Bug im Konfigurationsfile für den ATTiny13. Mit AVRDUDE 5.3 aus dem aktuellen WinAVR vom 22.01.07 gibt es aber kein Problem mehr.
Beispiel für den Aufruf von AVRDUDE per Kommandozeile:
Code:
 avrdude -p attiny13 -c ponyser -P com1 -U flash:w:rl_4.2.hex:i
Dabei spezifiziert "-p attiny13" den Microcontrollertyp, "-c ponyser -P com1" den oben beschriebenen Programmieradapter und "-U flash:w:rl_4.2.hex:i" die .hex Datei, die geladen wird.
 

huirad

Geocacher
Und gleich noch ein kurzer Erfahrungsbericht zur C-Programmierung.

Als ich das Beispielprogramm aus Kapitel 4.2 des Kochbuchs (bzw. aus dem Posting von Dani_B vom 04.12.2005 ausprobiert habe, da war ich erstmal geschockt: 3894 Bytes Codegröße - das passt ja nie in den ATTiny13 rein. Als Ursache für den großen Code stelle sich heraus, daß der Aufruf von _delay_ms() mit einer Variablen als Parameter die Gleitkommabibliothek erfordert, siehe die Note in der Dokumentation.
Also: Tip: Als Parameter für _delay_ms() nur Konstanten verwenden!

Hier noch meine Variante des Programms:
Code:
//rl_4.2.c
//Reaktives Licht mit ATTiny13
//Modifiziertes Grundprogramm aus Kapitel 4.2 des Kochbuchs http://reaktivlicht.de/kochbuch.pdf vom 16.12.2006
//Änderungen gegebüber Grundprogramm: 
//-Taktfrequenz 128kHz
//- Entladezeit als Konstante (ansonsten werden Floating Point Libraries mitgeladen und der Code passt nicht mehr in den ATTiny13)
//- Entladezeit verkürzt auf 1000µs ( angepasst an Pollin LED's Best. Nr, 120437), ggf. noch weitere Anpassungen nötig
// - Nur noch lokale Variablen: Geringere Codegröße, da diese Variablen in den Registern gehalten werden statt im RAM

#include <avr/io.h>
//#define F_CPU 128000 //Taktfrequenz ist bereits im makefile definiert
#include <util/delay.h> //maximale delays bei 128 kHz: _delay_us(6000),  _delay_ms(2047)


unsigned char led_abfrage(void) 
{
    unsigned char led_status;
    PORTB &= ~(1<<PB3); // Portb.3 auf Masse schalten
    PORTB |= (1<<PB4); // Portb.4 auf +Ub schalten, um die LED zu 'laden'
    _delay_us(1); // Ladezeit 1 µs, kann ggf. noch verkleinert werden
    DDRB &= ~(1<<PB4); // Portb.4 nun zwecks Abfrage der LED-Ladung auf 'Eingang' schalten
    PORTB &= ~(1<<PB4); // Pullup abschalten, sonst geht's nicht!
    _delay_us(1000); // Entladezeit zeit_ms (1500 µs) - je kleiner, je unempfindlicher
    led_status = (PINB & (1<<PINB4)); // Ladezustand einlesen
    DDRB |= (1<<PB4); // Portb.4 wieder auf Ausgang schalten
    PORTB &= ~(1<<PB4); // Portb.4 auf Masse schalten
    return led_status;
}


int main(void) 
{
    unsigned char i;
    DDRB = 0b00011000; // Pinb.3 und .4 auf 'Ausgang', Rest auf 'Eingang' schalten
    PORTB = 0b11100111; // Pullups zuschalten, außer für Pinb.3 und .4
    ADCSRA &= ~(1<<ADEN); // A/D-Wandler abschalten, eigentlich unnötig da Voreinstellung
    ACSR |= (1<<ACD); // AnalogKomparator abschalten
    
    while (1) {
        if ( led_abfrage() == 0) 
        { // LED durch Licht entladen?
            for (i = 0; i < 10 ; i++) 
            { // 10x blinken
                PORTB |= (1<<PB3); // PB3 auf Vcc schalten
                _delay_ms(50); // 50 ms Blitz
                PORTB &= ~(1<<PB3); // PB3 auf GND schalten
                _delay_ms(500); // ca. 500ms Pause
            }
        }
    }    
    return 0;
}

Und mein makefile:
Code:
#Minimal Makefile für ein einfaches avr-gcc Projekt
#Getestet mit der WinAVR (http://winavr.sourceforge.net/) Distribution vom 22.01.07 

#Die folgenden 3 Make Targets sind definiert
# - make all: compiliert den Sourcecode, erzeugt das .hex file
# - make clean: löscht alle Files, die beim compilieren generiert wurden
# - make program: überträgt das generierte .hex file in den Mircocontroller über den einfachen seriellen Programmieradapter

#Achtung: Eigene Anpassungen  sollten normalerweise nur in 1.) und 2.) nötig sein 

# 1.) Microcontrollerspezifisches
MCU            = attiny13
F_CPU          = 128000

# 2.) Target und Source Files
TARGET         = rl_4.2
SRC            = $(TARGET).c

# 3.)  Compilerflags
# implizite Regel: n.o is made automatically from n.c with a command of the form '$(CC) -c $(CPPFLAGS) $(CFLAGS)'.  
OPT    = -Os
CDEFS  = -DF_CPU=$(F_CPU)UL
CFLAGS = -Wall $(OPT) -mmcu=$(MCU) $(CDEFS)

# 4.)  Linkerflags
LDFLAGS = -Wl,-Map,$(TARGET).map
LIBS    = 

# 5.) Define programs and commands.
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump

# 6.) Regeln
OBJ = $(SRC:%.c=%.o)

%.elf: $(OBJ)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)

%.lss: %.elf
	$(OBJDUMP) -h -S $< > $@

%.hex: %.elf
	$(OBJCOPY) -j .text -j .data -O ihex $< $@


# 7.) Make Targets
.PHONY : all clean program

all: $(TARGET).elf $(TARGET).lss $(TARGET).hex

clean:
	rm -rf *.o *.elf *.hex *.map *.lss *.lst

program: $(TARGET).hex
	avrdude -q -q -p $(MCU) -c ponyser -P com1 -U flash:w:$(TARGET).hex:i
 
A

Anonymous

Guest
hi

hab nun endlich meinen programmer ans laufen bekommen das programm ist auch schon im tiny13v aber mit den fusebits komm ich nicht ganz klar

hier mal 4 bilder was ich alles einstellen kann

http://german-lose.serv12.ackermedia.de/fuse/1.jpg
http://german-lose.serv12.ackermedia.de/fuse/2.jpg
http://german-lose.serv12.ackermedia.de/fuse/3.jpg
http://german-lose.serv12.ackermedia.de/fuse/4.jpg

alle Einstellungen sind so wie sie am Anfang waren 1 uC hab ich schon geschrottet hab nur den takt mal geändert (auf bild 1 zu sehen) und schon kam ich nicht mehr auf den uC

Bevor ich nun den nächsten schrotte frag ich mal lieber nach

vielen dank schonmal im vorraus

mfg

chris
 

eigengott

Geowizard
chrisi01 schrieb:
alle Einstellungen sind so wie sie am Anfang waren 1 uC hab ich schon geschrottet hab nur den takt mal geändert (auf bild 1 zu sehen) und schon kam ich nicht mehr auf den uC

Kannst du die Datenrate des Programmers ändern? Wenn man den internen Oszillator weit genug 'runterdreht - so wie bei dir - klappt die serielle Kommunikation nur noch mit entsprechend geringer Datenrate. Ich stelle in solchen Fällen bei meinem Programmer die niedrigste Datenrate ein um die Lock-Bits neu zu setzen (höherer Takt, keine Teilung). Danach lässt sich der Chip wieder normal ansprechen.
 

Windi

Geoguru
eigengott schrieb:
Kannst du die Datenrate des Programmers ändern? Wenn man den internen Oszillator weit genug 'runterdreht - so wie bei dir - klappt die serielle Kommunikation nur noch mit entsprechend geringer Datenrate. Ich stelle in solchen Fällen bei meinem Programmer die niedrigste Datenrate ein um die Lock-Bits neu zu setzen (höherer Takt, keine Teilung). Danach lässt sich der Chip wieder normal ansprechen.
Das Problem habe ich bei mir nur wenn ich auf 128kHz und Teilung durch 8 einstelle.
Bei allen höheren Frequenzen klappt es bei mir einwandfrei.
 
A

Anonymous

Guest
hi

nein kann da nix einstellen da sitzt ein fester quarz drauf und nix zum einstellen vorhanden.

Um den einen Tiny gehts mir auch nicht der hat 79ct gekostet sch*** drauf :lol:

aber wie setzt ich den nun die Fusebits richtig damit er auch funkt? hab ihn programmiert und in die Schaltung eingebaut (es ist nur eine LED an Port B0 die ich anschalte per programm) und die leuchtet leider net wenn ich den uC in die Schaltung steck. Wenn ich den uC ausm Sockel raus nehm und die Vcc vom uC mit dem Pin wo der Port B0 liegt mit nem draht verbinde (also am sockel des uC ohne uC) leuchtet die LED es ist also alles richtig gebaut nur der uC steuert irgendwie nicht richtig den Ausgang hoffe auf hilfe vermute eben das was an den Fuse Bits nicht stimmt.

Als Spannungsquelle hab ich 2 1,5V Batterien in Reihe. Sprich 3V.

mfg

chris
 

Starglider

Geoguru
chrisi01 schrieb:
aber wie setzt ich den nun die Fusebits richtig damit er auch funkt? hab ihn programmiert und in die Schaltung eingebaut (es ist nur eine LED an Port B0 die ich anschalte per programm) und die leuchtet leider net wenn ich den uC in die Schaltung steck.
Das könnte auch ein Softwareproblem sein.:wink:
Poste doch mal dein Programm.
 
A

Anonymous

Guest
#define F_CPU 128000
#include <avr\io.h>
#include <util\delay.h> //ok die bräuchte ichjetzt nicht aba egal ne pause soll später eh mal rein ;)
void initPorts(void)
{
DDRB=0x01;
}
main (void)
{
{
PORTB = 1;

}
while (true);
}

mfg

chris
 
A

Anonymous

Guest
hi

habs hinbekommen hab das konfigurieren aus der funktion rausgenommen und ins hauptprogramm gepackt ;)

wollt jetzt ne _delay_ms(500); verwenden da wird die hex file aber gleich ganze 9kbyte groß :shock: :shock: das bringt der ja logischerweise nie ind en 1kb speicher des uCs wo isn etz der tricky dabei?

mfg

chris
 

Starglider

Geoguru
chrisi01 schrieb:
habs hinbekommen hab das konfigurieren aus der funktion rausgenommen und ins hauptprogramm gepackt ;)
Es hätte wohl auch in der initPorts()-Funktion funktioniert, wenn du die nur mal irgendwo aufgerufen hättest :D

Ich habe noch nichts mit C auf dem Atmel gemacht, daher kann ich zu der Sache mit der Programmgröße nichts sagen.

Nachtrag:
Ich würde mal schauen welche Optionen der Linker zum Optimieren der Programmgröße bietet.
 

Windi

Geoguru
Kenn mich mit C leider auch nicht aus aber dass das Programm so groß wird liegt vermutlich daran dass Teile der Bibliothek mit kompiliert werden die man für das Programm eigentlich gar nicht benötigt.
 
A

Anonymous

Guest
hi

hab jetzt nen anderen kompiler genommen und das blinklicht blinkt grad so schön vor sich hin :) vielen dank für die hilfe :) klappt nun alles :)

nur noch eine frage hab hier 2 Monozellen genommen (glaub ich sind die ganz großen batterien) steht aber nix drauf wieviel mah die normalerweise haben weiss das wer was da in etwa normal ist?

mfg

chris
 

radioscout

Geoking
chrisi01 schrieb:
nur noch eine frage hab hier 2 Monozellen genommen (glaub ich sind die ganz großen batterien) steht aber nix drauf wieviel mah die normalerweise haben weiss das wer was da in etwa normal ist?
Aus einem älteren Katalog eines Batterieherstellers aus .de:
Alkalimangan: 13 Ah
Zink-Kohle: 8,2 Ah
 

Windi

Geoguru
Gerade mal bei Reichelt ein Datenblatt angeschaut.
Die Energizer D-Cell ist bei einer konstanten Entladung mit 25mA bis runter auf 0,8 Volt mit 18.000 mAh angegeben.
 

huirad

Geocacher
wollt jetzt ne _delay_ms(500); verwenden da wird die hex file aber gleich ganze 9kbyte groß Shocked Shocked das bringt der ja logischerweise nie ind en 1kb speicher des uCs wo isn etz der tricky dabei?
hab jetzt nen anderen kompiler genommen und das blinklicht blinkt grad so schön vor sich hin Smile vielen dank für die hilfe Smile klappt nun alles Smile
Das interessiert mich jetzt. Welcher Compiler, welche Compilerversionen vorher/nachher?
Beim avr-gcc sollte die Compileroption -Os für kompakten Code sorgen.
 
A

Anonymous

Guest
hi

vorher: myAvrWorkpadPLUS_Demo von http://www.myavr.de

danach codevision 1.24.7d evolution. wobei da auch mein programm sehr sehr knapp reingeht hab ziemlich genau die hälfte mal reingeschrieben und 488byte gebraucht drückt mir die daumen das es reicht ;)

und 18.000mAh :shock: :shock: ich mein die zelle is ja relativ klein im gegensatz zu ner Autobatterie die ja auch "nur" ca. 50-80Ah haben bin ich schon überrascht. Da brauch ich ja kaum den tiny13V auf Energiesparen setzten ;) das hält ja auch so ewig wenn ich da ne 2ma LED nehm und die nur etwa 1/10 der Zeit leuchtet macht pi mal daumen bei ca. 10.000mAh ja dann 5,7 (grob -0,7jahre für den uC ;)) Jahre :shock:

mfg

chris
 
Oben