PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit Tasten auf RN Mega8



pacer_one
05.03.2008, 19:55
Hallo,

ich habe das RN-Mega8 und wollte mal fragen wie ihr eure Tasten programmiert habt. Mein spezielles Problem ist, dass wenn ich keine Taste drücke der Messwert zappelt. Für einen Test habe ich mal einen 4,7K Widerstand als Pulldown auf Masse gelegt . Das Zappeln ohne Drücken einer Taste war dann weg. Leider aber zappelt dann der Messwert bei Taste 5.

Ich habe absolut keinen Plan, wie ich das jetzt in Griff bekommen soll. ](*,)

Gruß, JK

linux_80
05.03.2008, 20:48
Bist du immer die gleiche Person, oder wird der Account von mehreren Personen verwendet ?
Hab da fast sowas wie ein DejaVu oder wie das heisst !

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=38510

pacer_one
06.03.2008, 08:52
natürlich hab ich das nochmal gepostet. Normalerweise mache ich das nicht.
Aber ich kann es mir nicht vorstellen, dass keiner ne Anwort auf meine Frage hat. Ich bin unmöglich der einzige der das RN8 in Assembler programmiert.
Im Moment hab ich noch ein elektronisches Problem, aber ein bisschen Unterstützung in der Programmierung brauche ich dann doch.

Ich habe jetzt mal den internen Pullup aktiviert (die Atmeldoku ist die beste Lektüre), leider habe ich Probleme mit der Taste 5, der Messwert schwankt stark. Taste 4 ist auch nicht besser. Ohne Pullup funktionieren die Tasten wunderbar.

Gerko
14.03.2008, 14:33
Hallo!

Ich verstehe dein Problme noch nicht so ganz, wenn ich Taster anbringe dann verwende ich einen Widerstand. der die Spannung auf 0 zieht (oder auf high, je nachdem). Das mache ich allerdings extern, also nicht mit dem Programm, wüsste auch nicht wie das geht. Was du als zappeln bezeichnest, ist wahrscheinlich das Schalterprellen, den ausdruck hab ich hald so gelernt. Das kann man schlecht unterdrücken, aber man kann im Programm eine kurze warteschleife einbauen und den interrupt erst später wieder aktivieren, so vermeidet man sowas. mit der zeit muss man sich spielen, je nach Taster kann das zwischen 1-100ms sein.

Programmcode will ich jetzt eigentich keinen reinstellen, aber du könntest ja mal herzeigen was du so geschrieben hast, und dann können wir beraten was jetzt verbessert werden sollte.

pacer_one
15.03.2008, 10:24
Hallo Gerko,

wollte jetzt mal fragen ob du auch das RN-Mega8 hast? Ich habe mich vielleicht etwas unklar ausgedrückt, aber auf dem RN-Mega8 gibt es 5 Tasten die über ein Widerstandsnetzwerk an den ADC angeklemmt sind.

Also ich habe zwei Programme. Das erste Programm gibt den Wert der jeweiligen Taste auf dem UART aus. Es basiert auf dem ersten Programm:


.NOLIST ; List-Output unterdrücken
.INCLUDE <m8def.inc> ; das gibt es für jeden Controllertyp

;.include "C:\PROGRA~1\VMLAB\include\m8def.inc

.def temp = r16 ; allgemeines temp Register, zur krufristigen Verwendung
.def temp2 = r17 ; Register für 24 Bit Addition, Lowest Byte
.def temp3 = r18 ; Register für 24 Bit Addition, Middle Byte
.def temp4 = r19 ; Register für 24 Bit Addition, Highest Byte
.def adlow = r20 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def adhigh = r21 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def messungen = r22 ; Schleifenzähler für die Messungen
.def ztausend = r23 ; Zehntausenderstelle des ADC Wertes
.def tausend = r24 ; Tausenderstelle des ADC Wertes
.def hundert = r25 ; Hunderterstelle des ADC Wertes
.def zehner = r26 ; Zehnerstelle des ADC Wertes
.def zeichen = r27 ; Zeichen zur Ausgabe auf den UART


;------------------------------------------------------
; Peripherie initialisieren
;------------------------------------------------------
.equ F_CPU = 7273800 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate

; Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate



.LIST ; List-Output wieder aufdrehen
.CSEG ; was nun folgt, gehört in den FLASH-Speicher

;------------------------------------------------------
; Start Adresse 0000 /Interruptvektoren
;------------------------------------------------------
.org 0x000
rjmp Init ; Interruptvektoren überspringen

;------------------------------------------------------
; INITIALIZE
;------------------------------------------------------
INIT:
;Stack Pointer setzen
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp

; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp

; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren

; ADC initialisieren: Single Conversion, Vorteiler 128
ldi temp, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
out ADMUX, temp
ldi temp, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
out ADCSRA, temp

; Pullup aktivieren
ldi temp,0x00
out DDRC,temp
ldi temp,0x01
out PORTC,temp

;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:

clr temp
clr temp2
clr temp3
clr temp4

ldi messungen, 0 ; 256 Schleifendurchläufe

; neuen ADC-Wert lesen (Schleife - 256 mal)

sample_adc:
sbi ADCSRA, ADSC ; den ADC starten

wait_adc:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
rjmp wait_adc

; ADC mit 10 Bit einlesen:

in adlow, ADCL ; immer zuerst LOW Byte lesen
in adhigh, ADCH ; danach das mittlerweile gesperrte High Byte

; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden

add temp2, adlow ; addieren
adc temp3, adhigh ; addieren über Carry
adc temp4, temp ; addieren über Carry, temp enthält 0
dec messungen ; Schleifenzähler MINUS 1
brne sample_adc ; wenn noch keine 256 ADC Werte -> nächsten Wert einlesen

; Aus den 256 Werten den Mittelwert berechnen
; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte
; (im Register temp2) fällt einfach weg
;
; allerdings wird der Wert noch gerundet

cpi temp2,128 ; "Kommastelle" kleiner als 128 ?
brlo no_round ; ist kleiner ==> Sprung

; Aufrunden
subi temp3, low(-1) ; addieren von 1
sbci temp4, high(-1) ; addieren des Carry

no_round:

; Ergebnis nach adlow und adhigh kopieren
; damit die temp Register frei werden

mov adlow, temp3
mov adhigh, temp4

;in ASCII umwandeln

ldi ztausend, -1 + '0' ; um binär-Wert in ASCII zu wandeln, auf den binär-Wert den
_a6ser: ; ASCII-Wert der Null addieren
inc ztausend
subi adlow, low(10000) ; -10,000
sbci adhigh, high(10000)
brcc _a6ser

ldi tausend, 10 + '0'
_a7ser:
dec tausend
subi adlow, low(-1000) ; +1000
sbci adhigh, high(-1000)
brcs _a7ser

ldi hundert, -1 + '0'
_a8ser:
inc hundert
subi adlow, low(100) ; -100
sbci adhigh, high(100)
brcc _a8ser

ldi zehner, 10 + '0'
_a9ser:
dec zehner
subi adlow, -10 ; +10
brcs _a9ser
subi adlow,-'0'

;an UART Senden

mov zeichen, ztausend ; Zehntausender Stelle
rcall transmit
mov zeichen, tausend ; Tausender Stelle ausgeben
rcall transmit
mov zeichen, hundert ; Hunderter Stelle ausgeben
rcall transmit
mov zeichen, zehner ; Zehner Stelle ausgeben
rcall transmit
mov zeichen, adlow ; Einer Stelle ausgeben
rcall transmit
ldi zeichen, 13 ; CR
rcall transmit
ldi zeichen, 10 ; LF
rcall transmit


rjmp Hauptschleife


;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------
transmit:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp transmit
out UDR, zeichen
ret

;------------------------------------------------------
; ENDE
;------------------------------------------------------
Ende:
rjmp Ende


Das zweite Programm gibt die jeweilige Nummer gedrückten Taste auf dem UART zurück. Das Programm ist natürlich nich nicht fertig, funktioniert aber schon.

; Programm zur Abfrage der Tsten auf dem RNMega8
; Schaltung überprüfen (am ADC mit Multimeter messen) hängt ADC in der Luft?

.NOLIST ; List-Output unterdrücken
; .INCLUDE <m8def.inc> ; das gibt es für jeden Controllertyp

.include "C:\PROGRA~1\VMLAB\include\m8def.inc"

.def temp = r16 ; allgemeines temp Register, zur krufristigen Verwendung
.def temp2 = r17 ; Register für 24 Bit Addition, Lowest Byte
.def temp3 = r18 ; Register für 24 Bit Addition, Middle Byte
.def temp4 = r19 ; Register für 24 Bit Addition, Highest Byte
.def adlow = r20 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def adhigh = r21 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def messungen = r22 ; Schleifenzähler für die Messungen
.def ztausend = r23 ; Zehntausenderstelle des ADC Wertes
;.def Taste1 = r24 ; Tausenderstelle des ADC Wertes
;.def Taste2 = r25 ; Hunderterstelle des ADC Wertes
;.def Taste3 = r26 ; Zehnerstelle des ADC Wertes
.def zeichen = r27 ; Zeichen zur Ausgabe auf den UART


;------------------------------------------------------
; Peripherie initialisieren
;------------------------------------------------------
.equ F_CPU = 7273800 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate

; Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate



.LIST ; List-Output wieder aufdrehen
.CSEG ; was nun folgt, gehört in den FLASH-Speicher

;------------------------------------------------------
; Start Adresse 0000 /Interruptvektoren
;------------------------------------------------------
.org 0x000
rjmp Init ; Interruptvektoren überspringen

;------------------------------------------------------
; INITIALIZE
;------------------------------------------------------
INIT:
;Stack Pointer setzen
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp

; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp

; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren

; ADC initialisieren: Single Conversion, Vorteiler 128
ldi temp, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
out ADMUX, temp
ldi temp, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
out ADCSRA, temp

;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:

clr temp
clr temp2
clr temp3
clr temp4

ldi messungen, 0 ; 256 Schleifendurchläufe

; neuen ADC-Wert lesen (Schleife - 256 mal)

sample_adc:
sbi ADCSRA, ADSC ; den ADC starten

wait_adc:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
rjmp wait_adc

; ADC mit 10 Bit einlesen:

in adlow, ADCL ; immer zuerst LOW Byte lesen
in adhigh, ADCH ; danach das mittlerweile gesperrte High Byte

; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden

add temp2, adlow ; addieren
adc temp3, adhigh ; addieren über Carry
adc temp4, temp ; addieren über Carry, temp enthält 0
dec messungen ; Schleifenzähler MINUS 1
brne sample_adc ; wenn noch keine 256 ADC Werte -> nächsten Wert einlesen

mov adlow, temp3
mov adhigh, temp4


Taste1:
subi adlow, low(70) ; -70
sbci adhigh, high(70)
brcc Taste2

ldi zeichen, '1' ; Taste1
rcall transmit
rjmp taste_gefunden


Taste2:
subi adlow, low(65) ; -65
sbci adhigh, high(65)
brcc Taste3

ldi zeichen, '2' ; Taste2
rcall transmit
rjmp taste_gefunden

Taste3:
subi adlow, low(65) ; -65
sbci adhigh, high(65)
brcc Taste4

ldi zeichen, '3' ; Taste3
rcall transmit
rjmp taste_gefunden

Taste4:
subi adlow, low(65) ; -65
sbci adhigh, high(65)
brcc Taste5

ldi zeichen, '4' ; Taste4
rcall transmit
rjmp taste_gefunden

Taste5:
ldi zeichen, '5' ; Taste5
rcall transmit
rjmp taste_gefunden

taste_gefunden:
rjmp Hauptschleife


;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------
transmit:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp transmit
out UDR, zeichen
ret

;------------------------------------------------------
; ENDE
;------------------------------------------------------
Ende:
rjmp Ende


Einfach mal anschauen...

linux_80
15.03.2008, 13:42
Ich hab zwar ein RN-Mega8, mach aber meist nix per ASM damit.

Hast Du wirklich einen solchen Quarz im Einsatz:
7273800
Ich finde hier nur solche:
7372800

Beim ADC könnte man den Prescaler noch mit /64 laufen lassen, dann gehts doppelt so schnell, und ist noch im Limit.

Beim 2. Beispiel wird der Pullup nicht gesetzt.

Du benutzt AVCC als Referenz, das funktionert aber beim RN-Mega8 nicht so recht, weil aussen an AREF der Spannungsteiler durch den Trimmer anliegt ! Man kann hier fast nur die externe Referenz wählen, oder man lötet die Bauteile aussen weg, bis auf den Kondensator natürlich.
Wenn Du den Jumper JPREF steckst, hast Du auch 5V.

Solltest du ein RN-Mega8-Plus haben, kann man den Jumper EXREF entfernen, dann kann die interne Referenz oder auch AVCC verwendet werden.

pacer_one
16.03.2008, 00:15
Stimmt, die Frequenz ist noch verdreht. Ich glaube ich muss mal alle Programme nachschauen. Aber sollte eigentlich keine Auswirkungen auf das Messergebnis haben, die UART-Schnittstelle funktioniert trotzdem. Ich habs natürlich geändert.

Mit dem ersten Programm teste ich ich die Qualität der Messwerte, deshalb ist das zweite Programm nicht unbedingt relevant. Das mit dem Prescaler klingt gut.

Bei mir ist der Jumper Jref gesteckt und die Spindeltrimmer nicht bestückt. Sollte also auch kein Problem sein.

Bei dir funktioniert es, schreibst du in C?

linux_80
16.03.2008, 02:09
Du solltest trotzdem mal die richtige Referenz angeben, damit die nicht gegeneinander arbeiten ! Das kann evtl. auch eine Schwankung verursachen.

Wenn ich den internen Pullup aktiviere ist der Wert ziemlich stabil, aber ganz fest bekommt man den nicht, ist halt Analog.
In welchem Bereich schwankt das bei Dir ?

Ich mach trotz allem meist in Bascom, kann aber alles andere auch.

pacer_one
16.03.2008, 12:30
im Moment wird ja die interne Referenz von 5V genutzt. Den Jumper Jref hab ich auch schon gezogen, leider ohne Erfolg.

Das merkwürdige ist aber, dass ohne Pullup die Spannung beim Drücken der Taster stabil bleibt. Somit hängt bei nicht gedrückter Taste der ADC in Luft, so dass es zu vermeintlichen Tastendrücken kommt. Aktiviere ich den Pullup, sollte bei nicht gedrückter Taste 5V angezeigt werden, tut es auch, nur leider schwanken jetzt die Spannungswerte beim Drücken der Taste 4 und 5.

Im Moment kann ich leider keine Messungen am Board durchführen, aber es handelt sich hierbei um Schwankungen im 100mV-Bereich. Das ist eindeutig zu viel. Ich wollte mal fragen welche Spannungsstufen bei deinen Tastern gemessen hast.

linux_80
16.03.2008, 13:16
Das ist nicht merkwürdig, sondern logisch !
Die Widerstände bei den Tasten sind viel kleiner als der interne Pullup.
Und wenn der ADC in der Luft hängt muss er fast schwanken, ist so seine Art (gehört zum Thema Antenne).
Ganz ohne Schwankung wird man es nicht schaffen.

Heut Nachmittag bau ich mal mein Zeug zusammen und probier es noch mal aus.

pacer_one
21.03.2008, 12:06
mit nicht logisch meinte ich, dass die Spannung beim Drücken schwankt, wenn der Pullup aktiviert ist, bei nicht aktivierten Pullup die Spannung bei Taatendruck stabil bleibt.

Also mit dem einen Propgramm hab ich mal die Spannungen auf dem UART ausgeben lassen und in Calc dargestellt. Vielleicht kann das ja mal jemand für mich verifizieren?

linux_80
21.03.2008, 15:38
Hi,

ich hab das bei mir einige Minuten laufen lassen, hab eine Wäscheklammer auf die Tasten gezwickt, und mitgeloggt, bei mir schwankt das i.d.R. +/- 1 max., nur selten mehr. Als Referenz ext. 5V, da ich sonst den Trimmer auslöten müsste.
Nur im Moment des drückens/loslassens gibts auch mal andere Werte, aber auch nur selten.