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 | int timerstat = 0; |
15 | int lichtsek = 3; |
16 | int lichtstat = 0; |
17 | int blinkerlinkson = 0; |
18 | int blt = 10; // Blinkerlinkstimerzeit |
19 | int brt = 10; // Blinkerrechtstimerzeit |
20 | //Variable für die Zeit des Timers
|
21 | volatile unsigned int sekunde; |
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 | void ADC_Init(void) { |
34 | |
35 | uint16_t result; |
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_t ADC_Read( uint8_t channel ) |
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 | return ADCW; // ADC auslesen und zurückgeben |
64 | }
|
65 | |
66 | int main (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 |
84 | uint16_t adcval; |
85 | ADC_Init(); |
86 | |
87 | // Hauptcode
|
88 | while(1) |
89 | {
|
90 | |
91 | // Lichtsensor
|
92 | adcval = ADC_Read(5); // Kanal 5 |
93 | if (adcval > 400) { STRPORT &= ~(1 << LICHT); } else { STRPORT |= (1 << LICHT); } |
94 | |
95 | // Blinker Links
|
96 | |
97 | if (blt == 1) |
98 | {
|
99 | if (!(PINC & 1<< BLI)) // Taster pressed |
100 | {
|
101 | blt = 10; |
102 | blinkerlinkson = 0; |
103 | }
|
104 | }
|
105 | else
|
106 | {
|
107 | if (!(PINC & 1<< BLI)) // Taster pressed |
108 | {
|
109 | blt = 0; |
110 | blinkerlinkson = 1; |
111 | }
|
112 | }
|
113 | if (blt == 3) |
114 | {
|
115 | blinkerlinkson = 0; |
116 | }
|
117 | |
118 | if (blinkerlinkson == 1) |
119 | {
|
120 | STRPORT |= (1 << BLO); |
121 | }
|
122 | |
123 | if (blinkerlinkson == 0) |
124 | {
|
125 | STRPORT &= ~(1 << BLO); |
126 | }
|
127 | }
|
128 | }
|
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 = jetziger Pin Status; |
4 | |
5 | while( 1 ) // Hauptschleife |
6 | {
|
7 | newLinks = jetziger Pin Status; |
8 | |
9 | if( oldLinks != newLinks ) // Hoppla, am Pin hat sich was getan! |
10 | {
|
11 | if( newLinks == Zustand Low ) // der Pin ist von 1 auf 0 gewechsel |
12 | {
|
13 | mach was für den Fall einer fallenden Flanke |
14 | }
|
15 | |
16 | else // der Pin ist von 0 auf 1 gewechselt |
17 | {
|
18 | mach was für den Fall einer steigenden Flanke |
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 | volatile uint8 LEDLinks; |
2 | |
3 | ISR( ... ) |
4 | {
|
5 | if( LEDLinks > 0 ) |
6 | {
|
7 | LEDLinks--; |
8 | if( LEDLinks == 0 ) |
9 | schalte Linke LED ab |
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.