
UKW-Schatzkisterl
von Alexander "Electronicfox" Fuchs
Mein Aufbau besteht aus folgenden Bauteilen:
UKW-Radiomodul vom Conrad-Adventskalender 2012 mit TDA7088
Audioendstufe LM386N
Mikrocontroller AVR ATMEGA328P
8-Bit-Schieberegister mit Latch 4094
Zweifach 2-zu4-Decoder 74LS139
Dreifach LED-7-Segmentdisplay
Kleines Schatztruhengehäuse
Diverse Taster, Potis und Kappen
Die
Bedienung ist sehr einfach gestaltet mit programmierbaren
Senderprogrammplätzen, welche einfach mit 4 kleinen Tasten umgeschaltet
werden können. Intern sind 3 UKW-Radiosender fest mit Potis vorjustiert
und Programmplatz 1 kann von vorne aus auf jeden beliebigen Sender
jeder Zeit und an jeden Standort des Radios justiert werden. Aus
schaltungstechnischen Gründen ist nur ein Mono-Betrieb möglich. Für
Stereo wäre ein
aufwendiger Umbau des Moduls nötig gewesen.
So schaut es im Betrieb aus:
Ich
habe zwei Aufbauten für den Batteriedeckel. Einmal das Rote-Samt-Design
und einmal das Münzendesign. Beides schaut bei diesem
UKW-Radioschatzkisterl ziemlich gut aus. Die Schaltung erklärt sich von
selbst, da der Aufbau ziemlich gut konstruiert wurde. Bei jedem
Senderwechsel wird die RESET-Schaltung am Modul aktiviert, so dass ein
Abstimmen völlig unproblematisch wird. Denn das Radio war eigentlich
nur für SCAN-/RESET-Betrieb gedacht und daher musste
Schaltungstechnisch getrickst werden. Der Mikrocontroller übernimmt
dabei alle Aufgaben selbstständig, sogar die Programmanzeige des
Displays und die Tastenabfrage. Das Assemblerprogramm ist weiter unten
zu finden und gut erklärt.
Das
Radio hat einen guten Klang und die Abstimmung ist sauber. Für den
Betrieb reicht eine kleine 9V-Blockbatterie vollkommen aus und benötigt
bei mittlerer Lautstärke ca. 40mA.
Begonnen hat alles mit einem
Urlaub, einem Erlebnis, einer Idee, einen Aufbau und den Fund des
Gehäuses bei Nanu-Nana im EKZ Fischapark in Wr. Neustadt Österreich.
Im
August 2014 war ich mit meiner Lebensgefährtin in Salzburg und machten
einen netten Urlaub. Zum Abschluss des Urlaubs besuchten wir zusammen
das Radiomuseum in Grödig, welches etwas auswärts vom Zentrum zu finden
ist. Dort sahen wir dieses russische Radio. Früher gab es viele
Designer mit schönen Ideen. Als ich im Dezember 2014 gelesen habe, dass
ein neuer Bastelwettbewerb stattfindet und mit dem Thema UKW-Radio zu
tun hat, habe ich mich zurückerinnert und konstruierte zunächst ein
Radiomodul mit Ablaufsteuerung sowie Displayanzeige.
Dieser Beitrag als PDF:
Schalzkistzerl.pdfZum Abschluss noch das Assemblerprogramm:
Download:
Schaltztruhe.zip.NOLIST
.INCLUDE "m328Pdef.inc" ; Befehlsliste des ATMega328P
.LIST
.def temp1 = r16
.def temp2 = r19
.def segm0 = r20
.def segm1 = r21
.def segm2 = r22
.def tempadc = r23
.equ SCHIEBE_DDR = DDRD
.equ SCHIEBE_PORT = PORTD
.equ SCK = 0
.equ SIN = 1
.equ RCK = 2
.equ ZIFB = 3
.equ ZIFA = 4
.equ TUNEA = 5
.equ TUNEB = 6
.equ TUENA = 7
.DSEG
.ORG 0X0100
.CSEG
.ORG $0000
jmp Main ; Reset vector
reti ; Int vector 1
nop
reti ; Int vector 2
nop
reti ; Int vector 3
nop
reti ; Int vector 4
nop
reti ; Int vector 5
nop
reti ; Int vector 6
nop
reti ; Int vector 7
nop
reti ; Int vector 8
nop
reti ; Int vector 9
nop
reti ; Int vector 10
nop
reti ; Int vector 11
nop
reti ; Int vector 12
nop
reti ; Int vector 13
nop
reti ; Int vector 14
nop
reti ; Int vector 15
nop
reti ; Int vector 16
nop
reti ; Int vector 17
nop
reti ; Int vector 18
nop
reti ; Int vector 19
nop
reti ; Int vector 20
nop
reti ; Int vector 21
nop
reti ; Int vector 22
nop
reti ; Int vector 23
nop
reti ; Int vector 24
nop
reti ; Int vector 25
nop
main:
; Init stack
ldi r16, HIGH(RAMEND) ; Init MSB stack
out SPH,r16
ldi r16, LOW(RAMEND) ; Init LSB stack
out SPL,r16
ldi r16,0x00 ; AUSGANG Port B
out DDRD,r16
ldi r16,0x00 ; AUSGANG Port C
out DDRD,r16
ldi r16,0xff ; AUSGANG Port D
out DDRD,r16
rjmp UKW1
main1:
rcall ad0 ; ADC-Kanal0 aufrufen und initialisieren
loop:
rcall adcRead
cbi SCHIEBE_PORT, TUENA
sbis PINB, 0
rjmp UKW1
sbis PINB, 1
rjmp UKW2
sbis PINB, 2
rjmp UKW3
sbis PINB, 3
rjmp UKW4
rcall DISPLAY
rjmp main1
UKW1:
sbi SCHIEBE_PORT, TUENA
ldi segm0, 140
ldi segm1, 175
ldi segm2, 249
cbi SCHIEBE_PORT, TUNEA
cbi SCHIEBE_PORT, TUNEB
rcall WarteDIS
rjmp loop
UKW2:
sbi SCHIEBE_PORT, TUENA
ldi segm0, 140
ldi segm1, 175
ldi segm2, 164
sbi SCHIEBE_PORT, TUNEA
cbi SCHIEBE_PORT, TUNEB
rcall WarteDIS
rjmp loop
UKW3:
sbi SCHIEBE_PORT, TUENA
ldi segm0, 140
ldi segm1, 175
ldi segm2, 176
cbi SCHIEBE_PORT, TUNEA
sbi SCHIEBE_PORT, TUNEB
rcall WarteDIS
rjmp loop
UKW4:
sbi SCHIEBE_PORT, TUENA
ldi segm0, 140
ldi segm1, 175
ldi segm2, 153
sbi SCHIEBE_PORT, TUNEA
sbi SCHIEBE_PORT, TUNEB
rcall WarteDIS
rjmp loop
ad0: ;ADC 0
ldi r16, (1<<REFS1) | (1<<REFS0)
sts ADMUX, r16
ldi r16, (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
sts ADCSRA, r16
ret
ad1: ;ADC 1
ldi r16, (1<<REFS1) | (1<<REFS0) | (1<<MUX0)
sts ADMUX, r16
ldi r16, (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
sts ADCSRA, r16
ret
adcRead:
lds r16, ADCSRA // Lesen
ori r16, (1<<ADSC) // Modifizieren
sts ADCSRA, r16 // Schreiben
loopx:
lds r16, ADCSRA
sbrc r16,ADSC
rjmp loopx
lds r17,ADCL
lds r18,ADCH
ret
lights:
;lsr r17 ; nur bei +5V
;out PORTD, r17
ret
DISPLAY:
sbi SCHIEBE_PORT, ZIFA
cbi SCHIEBE_PORT, ZIFB
mov temp1, segm0
rcall Schiebe
rcall SchiebeOut
rcall WarteDIS
ldi temp1, 255
rcall Schiebe
rcall SchiebeOut
rcall WarteDIS
cbi SCHIEBE_PORT, ZIFA
sbi SCHIEBE_PORT, ZIFB
mov temp1, segm1
rcall Schiebe
rcall SchiebeOut
rcall WarteDIS
ldi temp1, 255
rcall Schiebe
rcall SchiebeOut
rcall WarteDIS
cbi SCHIEBE_PORT, ZIFA
cbi SCHIEBE_PORT, ZIFB
mov temp1, segm2
rcall Schiebe
rcall SchiebeOut
rcall WarteDIS
ldi temp1, 255
rcall Schiebe
rcall SchiebeOut
rcall WarteDIS
ret
;-----------------------------------------------------------------------------
;
; Die Ausgabe im Schieberegister in das Ausgaberegister übernehmen
;
; Dazu am RCK Eingang am Schieberegister einen 0-1-0 Puls erzeugen
;
SchiebeOut:
sbi SCHIEBE_PORT, RCK
cbi SCHIEBE_PORT, RCK
ret
;-----------------------------------------------------------------------------
;
; 8 Bits aus temp1 an das Schieberegister ausgeben
Schiebe:
push temp2
ldi temp2, 8 ; 8 Bits müssen ausgegeben werden
Schiebe_1:
;
; jeweils das höchstwertige Bit aus temp1 ins Carry-Flag schieben
; Je nach Zustand des Carry-Flags wird die Datenleitung entsprechend
; gesetzt oder gelöscht
;
rol temp1 ; MSB -> Carry
brcs Schiebe_One ; Carry gesetzt? -> weiter bei Schiebe_One
cbi SCHIEBE_PORT, SIN ; Eine 0 ausgeben
rjmp Schiebe_Clock ; und Sprung zur Clock Puls Generierung
Schiebe_One:
sbi SCHIEBE_PORT, SIN ; Eine 1 ausgeben
;
; einen Impuls an SCK zur Übernahme des Bits nachschieben
;
Schiebe_Clock:
sbi SCHIEBE_PORT, SCK ; Clock-Ausgang auf 1 ...
cbi SCHIEBE_PORT, SCK ; und wieder zurück auf 0
dec temp2 ; Anzahl der ausgegebenen Bits runterzählen
brne Schiebe_1 ; Wenn noch keine 8 Bits ausgegeben -> Schleife bilden
pop temp2
ret
WarteDIS:
ldi R16, $1F
WGLOOP0: ldi R17, $AB
WGLOOP1: dec R17
brne WGLOOP1
dec R16
brne WGLOOP0
ldi R16, $01
WGLOOP2: dec R16
brne WGLOOP2
ret
STBY:
ldi R16, $24
WGLOOPA: ldi R17, $BC
WGLOOPB: ldi R18, $C4
WGLOOPC: dec R18
brne WGLOOPC
dec R17
brne WGLOOPB
dec R16
brne WGLOOPA
ldi R16, $01
WGLOOPD: dec R16
brne WGLOOPD
ret