Hallo,
ich habe mir eine Schaltung zusammen gebaut und diese mit dem folgenden
Code geflasht.
http://nopaste.info/d182180668.html
Der Käfer ist ein ATMega8. So weit läuft auch alles, der Fototransistor
etc. alles klappt, allerdings habe ich ein problem ab Zeile 101.
Das ganze sollte folgendermassen laufen:
Wenn auf BLI (PC3) GND anliegt schalte den Transistor an BLO (PC1).
Liegt nach einer Sekunde immernoch GND an BLI dann schalte nicht mehr.
Liegt nach einer Sekunde kein GND mehr an Schalte BLO noch für 2 sek und
schalte dann ab.
Das klappt auch soweit mit dem Code, allerdings brauche ich eine Lösung
er kennt ob GND gehalten wird, und wenn ja, dann warte solange bis kein
GND mehr anliegt, allerdings tue auch solange nicht.
Also, wird BLI kurz auf Masse gezogen schalte transistor für 3 sek. Wird
BLI auf Masse gehalten tue nichts, auch wenn masse wieder abfällt nicht.
Sondern erst wenn wieder auf Masse gezogen wird.
Ich hoffe das ist verständlich und jemand kann mit dabei weiter helfen.
Wenn man sich maximal unbeliebt machen will, dann verstreut man die
Bestandteile seines Projekts auf möglichst vielen Web-Seiten, damit es
für die Forenteilnehmer möglichst kompliziert wird, sich die Einzelteile
anzusehen, zu studieren und mit deiner Beschreibung in Einklang zu
bringen. Das gilt für Photos. Und in noch größerem Masse gilt es für
Code
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
#define LICHT PC0 // Licht port
5
#define BLO PC1 // Blinker links ausgangsport
6
#define BRO PC2 // Bliner rechts ausgangsport
7
#define BLI PC3 // Blinker links eingangsport
8
#define BRI PC4 // Blinker rechts eingangsport
9
#define FOTOTR PC5 // Fototransistor
10
#define STRPORT PORTC
11
#define STRDDR DDRC
12
13
// Variablen
14
inttimerstat=0;
15
intlichtsek=3;
16
intlichtstat=0;
17
intblinkerlinkson=0;
18
intblt=10;// Blinkerlinkstimerzeit
19
intbrt=10;// Blinkerrechtstimerzeit
20
//Variable für die Zeit des Timers
21
volatileunsignedintsekunde;
22
23
// Timer ISR
24
ISR(TIMER1_OVF_vect){
25
TCNT1=49911;// Zaehlregister mit Vorladewert vorladen
26
sekunde++;// Variable hochzählen
27
blt++;
28
brt++;
29
}
30
31
32
/* ADC initialisieren */
33
voidADC_Init(void){
34
35
uint16_tresult;
36
37
// interne Referenzspannung als Refernz für den ADC wählen:
38
ADMUX=(1<<REFS1)|(1<<REFS0);
39
40
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
41
// schon auf 0, also single conversion
42
ADCSRA=(1<<ADPS1)|(1<<ADPS0);// Frequenzvorteiler
43
ADCSRA|=(1<<ADEN);// ADC aktivieren
44
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
45
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
46
47
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung
48
while(ADCSRA&(1<<ADSC)){// auf Abschluss der Konvertierung warten
49
}
50
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
51
Wandlung nicht übernommen. */
52
result=ADCW;
53
}
54
55
/* ADC Einzelmessung */
56
uint16_tADC_Read(uint8_tchannel)
57
{
58
// Kanal waehlen, ohne andere Bits zu beeinflußen
59
ADMUX=(ADMUX&~(0x1F))|(channel&0x1F);
60
ADCSRA|=(1<<ADSC);// eine Wandlung "single conversion"
61
while(ADCSRA&(1<<ADSC)){// auf Abschluss der Konvertierung warten
62
}
63
returnADCW;// ADC auslesen und zurückgeben
64
}
65
66
intmain(void){
67
68
// Setze Portausgänge
69
STRDDR|=(1<<LICHT);// Licht
70
STRDDR|=(1<<BLO);// Blinker Links
71
STRDDR|=(1<<BRO);// Blinker Rechts
72
73
// Setze Porteingänge
74
STRDDR&=~(1<<BLI);// Blinker Links
75
STRDDR&=~(1<<BRI);// Blinker Rechts
76
STRDDR&=~(1<<FOTOTR);// Fototransistor
77
// Timer
78
// Global Interrupts aktivieren
79
sei();
80
81
TIMSK|=(1<<TOIE1);
82
TCCR1B|=(1<<CS11)|(1<<CS10);//Prescaler = 64
83
TCNT1=0xFFFF;//Zaehlregister vorladen mit FFFF zum Sofortstart
sorry, ich bin es grundsätzlich gewöhnt ein pastebin zu nutzen. z.b. in
einem chat (irc) kommt es nicht so gut wenn man einen ganzen code
postet. zumal in einem pastebin der code auch editierbar dargestellt
wird. aber ok, ich werde es mir merken den code direkt zu posten.
Tobias N. schrieb:> Also, wird BLI kurz auf Masse gezogen schalte transistor für 3 sek. Wird> BLI auf Masse gehalten tue nichts, auch wenn masse wieder abfällt nicht.> Sondern erst wenn wieder auf Masse gezogen wird.>> Ich hoffe das ist verständlich und jemand kann mit dabei weiter helfen.
die Lösung deines Problems liegt darin, dass du weg musst von 'Ist eine
Taste gedrückt' und hin musst zu 'Hat sich der Zustand des Eingangs
verändert (im Vergleich zum letzten mal als nachgesehen wurde) und wenn
ja, wie hat er sich verändert'. Du brauchst eine Flankenerkennung.
Im Prinzip kann das zb so aussehen
1
...
2
3
oldLinks=jetzigerPinStatus;
4
5
while(1)// Hauptschleife
6
{
7
newLinks=jetzigerPinStatus;
8
9
if(oldLinks!=newLinks)// Hoppla, am Pin hat sich was getan!
10
{
11
if(newLinks==ZustandLow)// der Pin ist von 1 auf 0 gewechsel
12
{
13
machwasfürdenFalleinerfallendenFlanke
14
}
15
16
else// der Pin ist von 0 auf 1 gewechselt
17
{
18
machwasfürdenFalleinersteigendenFlanke
19
}
20
}
21
}
Und in diese Flankenerkennung bettest du jetzt deine Zeitsteuerung ein.
Die im Prinzip so aussieht, dass du dir bei der fallenden Flanke den
Wert einer vom Timer hochzählenden Variablen merkst und bei der
steigenden Flanke mit dem dann aktuellen Wert vergleichst. Wenn die
Differenz klein genug ist, dann war auch der Puls kurz genug und du
machst dein Ding und startest die LED. Ist er aber größer als dein
Grenzwert, dann machst du gar nichts.
Wobei ich das 'Nachleuchten' der LED so realisieren würde, dass in der
Timer ISR (die auch auf weniger als 1 Sekunde einstelle), ein Zähler
heruntergezählt wird, der im Prinzip eine Eieruhr realisiert und der bei
erreichen von 0 dann die LED abschaltet.
1
volatileuint8LEDLinks;
2
3
ISR(...)
4
{
5
if(LEDLinks>0)
6
{
7
LEDLinks--;
8
if(LEDLinks==0)
9
schalteLinkeLEDab
10
}
11
12
....
13
}
Im Hauptprogramm muss man dann nur noch die LED einschalten, den Zähler
LEDLinks auf einen vernünftigen Wert setzen (hängt davon ab, wie oft die
ISR aufgerufen wird), und nach Ablauf der mit diesem Wert verknüpften
Zeit, schaltet die ISR die LED wieder ab.
Das sind so die Einzelteile, von denen ich denke, dass sie dir
weiterhelfen. Vorausgesetzt ich hab deine Problembeschreibung richtig
verstanden.
also das ganze soll halt erkennen ob eine taste gedrückt oder gehalten
wird. also wird die taste nur einmal gedrückt schalte den transistor 3
sek, danach schalte ab. wird die taste gehalten dann tue nichts, selbst
wenn die taste wieder losgelassen wird. also reagiere auf tippen und
nicht auf halten, wird gehalten dann tue solange nichts bis die taste
wieder getippt wird.
also, wird der blinker links nur angetippt, blinke 3mal (etwa 3sek) wird
der blinker aber komplett geschaltet (an einer ampel z.b. beim abbiegen)
dann tue, selbst wenn der blinker nach der kurve von alleine ausgeht
nichts, also tue nur was wenn der hebel angetippt wird.
das soll halt werden: 1x tippen, 3 x blinken
derzeigt erkennt man code zwar 1x tippen, 3 x blinken aber wenn man den
hält und dann z.b. 10sek später den blinker ausmacht, dann schaltet der
code 1sek später den blinker nochmal für 3 sek. und das muss ich
irgendwie erkennen und "abschalten".
Tobias N. schrieb:> also das ganze soll halt erkennen ob eine taste gedrückt oder gehalten> wird. also wird die taste nur einmal gedrückt schalte den transistor 3> sek, danach schalte ab. wird die taste gehalten dann tue nichts, selbst> wenn die taste wieder losgelassen wird. also reagiere auf tippen und> nicht auf halten, wird gehalten dann tue solange nichts bis die taste> wieder getippt wird.
Ja.
Und da dein µC genausowenig wie du ein Hellseher ist, läuft es darauf
hinaus, auszumessen wie lange die Taste gedrückt wurde. Wird die Taste
niedergedrückt, dann startet eine Stoppuhr, wird sie losgelassen, dann
stoppt die Stoppuhr. Und erst dann kannst du entscheiden ob das ein
kurzes Antippen oder langes Halten war.
Und genau so läuft das dann auch im Code
Beim Niederdrücken die aktuelle 'Uhrzeit' merken. Beim Loslassen die
dann aktuelle "Uhrzeit" holen, beide vergleichen und aus der Differenz
der beiden die weiteren Schlüsse ziehen. 'Uhrzeit' ist nichts anderes
als ein Zähler, der zb Timergesteuert alle 0.01 Sekunden um 1 hochzählt.
Aber der springende Punkt ist, dass du erst beim Loslassen der Taste
diese Unterscheidung treffen kannst, wobei du zu kurze Tastendrücke als
Tastenprellen gleich mit verwirfst.
Ich weiß schon, dass du von deinem Code retten willst, was zu retten
ist.
Aber erstens ist das nicht viel Code und zweitens denke ich, dass du mit
diesem Code nicht vernünftig weiter kommst. Du stehst fast am Ende in
einer Sackgasse und die einzige Chance ist es umzudrehen und an den
Anfang zurückzufahren.
So aufwändig ist das ganze ja nicht. Die paar Codezeilen hast du gleich.
ja, wie du schon sagst, viel is es nicht. und naja das bisschen kann ich
wirklich neu machen. mir hing es da nur ein wenig an der umsetzung, nach
deiner erklärung nun ist es für mich auch jetzt klarer geworden.
wurde taste gedrücke zähle solange taste gedrückt wird.
danach werte aus, wurde taste länger als 1sek (ist ja dann veränderbar)
gedrückt tue garnichts, ansonsten schalte den transistor 3 sek.