Hallo, ich möchte mit meinem Atmega8 über eine Gabellichtschranke die Drehzahl an meiner Bohrmaschine auslesen. Das Ganze wird über eine 7-Segmentanzeige angezeigt. Spasseshalber habe ich in der "Messwerte_auslesen" Funktion der Drehzahl irgendeinen Wert gegeben um zu schauen ob nach der Messung auch in diese Funktion gesprungen wird. Leider tut sich da nichts und die Anzeige zeigt nur 0000 an. Schreibe ich den Wert "1234" für Drehzahl direkt in die Ausgabefunktion wird der Wert auch angezeigt leider leuchten die anderen Segmente schwach mit. Hat da jemand ne Lösung für meine 2 Problemchen? Gruss Lalo
Ich hab das mal genauer beobachtet, wenn ich die Gabellichtschranke unterbreche dann flimmert die Anzeige kurz. Vermutlich zeigt sie den Wert "1234" nur kurz an. Fragt sich warum an der Variablen "drehzahl" ändert sich doch nichts mehr :(
1 | ...
|
2 | volatile int Erg = 0; |
3 | int drehzahl =0; |
4 | volatile int ziffer = 0; |
5 | ...
|
Warum ist "drehzahl" nicht volatile?
1 | zahl = Erg * 60; // Drehzahl berechnen aus der Frequenz f*60sec= U/min |
2 | |
3 | drehzahl=1234; |
"drehzahl" wird nur an dieser einen Stelle gesetzt (was ja nur zu Testzwecken drin sein soll), sonst aber auf "0" gelassen.
1 | ziffer = zahl2/1; // 1er Stelle für Segmentanzeige |
Interessante Berechnung.
Und wenn ich im Kopf drehzahl keinen Wert zuweise und auf static setze:
1 | volatile int Erg = 0; |
2 | static unsigned int drehzahl; |
3 | volatile int ziffer = 0; |
4 | volatile int zahl = 0; |
5 | volatile int stelle= 0; |
6 | volatile int schleife= 0; |
7 | volatile int drehzahl2 = 0; |
8 | volatile int zahl2 = 0; |
Dann müsste doch der Wert "drehzahl" nach dem Aufruf der Funktion erhalten bleiben?
"drehzahl" bleibt immer erhalten, weil es eine globale Variable ist. Jedoch merkt Deine Hauptschleife nicht, dass sich der Wert "drehzahl" in einer ISR gendert hat. Für den Compiler reicht es aus, einmal nachzusehen und dann immer den selben Wert zu verwenden. Daher "volatile". Denn dann schaut die Hauptschleife jedesmal genau hin, ob sich die Variable "drehzahl" geändert hat. volatile brauchtst Du für jede Variable, die sich innerhalb einer ISR ändert. "static" bringt dir nur etwas innerhalb einer Funktion. Diese Variable wird dann nicht auf den Stack, sondern irgendwo statisch im Speicher abgelegt. Der Inhalt ist dann der selbe, wie er beim letzen Funktionsaufruf war.
Danke für deine Erklärung, ich häng gerade trotzdem noch etwas auf der Leitung.
1 | int Messwerte_auslesen() //Unterprogramm zur Messwertausgabe |
2 | {
|
3 | schleife++; |
4 | |
5 | // liegt eine vollst?ndige Messung vor?
|
6 | |
7 | Erg = (NrOverflows * 65536) + (EndTime - StartTime); |
8 | |
9 | // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
|
10 | Erg = F_CPU / Erg; // f = 1 / t |
11 | |
12 | //aus der Frequenz berechnet sich die Drehzahl
|
13 | zahl = Erg * 60; // Drehzahl berechnen aus der Frequenz f*60sec= U/min |
14 | |
15 | Mittelwert+=zahl; // Drehzahl 28x messen |
16 | |
17 | if (schleife<29) |
18 | {
|
19 | Messwerte_ausgeben(); |
20 | }
|
21 | |
22 | else
|
23 | {
|
24 | schleife=0; |
25 | drehzahl=Mittelwert/28; // Drehzahl wieder durch 28 dividieren |
26 | Mittelwert=0; |
27 | |
28 | }
|
29 | |
30 | }
|
In diese Funktion wird ja nur nach einer abgeschlossenen Messung gesprungen. Der gemessene Wert soll 28x gemessen und ein Mittelwert gebildet werden damit die 7-Segmentanzeige nicht rumzuckt. Die bekomme ich den Wert der Variablen "Drehzahl" in eine andere Funktion? Ich kann sie ja nicht einfach an eine andere Variable übergeben denn sobald die Funktion verlassen wird steht für drehzahl wieder 0
Gerade aufgefallen:
1 | void Messwerte_ausgeben(void) |
2 | {
|
3 | ...
|
4 | |
5 | return; |
6 | }
|
Wozu das "return"? Die Funktion ist sowieso zuende und geht auch ohne "return" zum Aufrufer zurück. Lalo123 schrieb: > In diese Funktion wird ja nur nach einer abgeschlossenen Messung > gesprungen. Wie wird diese Funktion aufgerufen? Lalo123 schrieb: > Ich kann sie ja nicht einfach an eine andere Variable übergeben denn > sobald die Funktion verlassen wird steht für drehzahl wieder 0 Nein, denn die Variable "drehzahl" ist doch global. Sie wird nur einmal bei Programmstart mit 0 gefüllt. Danach jedoch nicht mehr. Wie kommst Du darauf, dass sie nach Verlassen der Funktion wieder auf 0 steht? Lalo123 schrieb: > _W_ie bekomme ich den Wert der Variablen "Drehzahl" in eine andere > Funktion? Da sie global ist, ganz einfach, benutzen.
Christian H. schrieb: > Wie wird diese Funktion aufgerufen? Über die main:
1 | while(1) |
2 | {
|
3 | Messwerte_ausgeben(); |
4 | |
5 | if (Ausgabe==TRUE) |
6 | {
|
7 | |
8 | Messwerte_auslesen(); |
9 | |
10 | |
11 | }
|
Die Ausgabe True Bedingung geschieht in der ISR. Christian H. schrieb: Wie kommst Du > darauf, dass sie nach Verlassen der Funktion wieder auf 0 steht? Naja wenn ich für drehzahl=1234 nehme und in die main beide Funktionen ständig aufrufe dann zeigt es mir den Wert einwandfei an
1 | while(1) |
2 | {
|
3 | Messwerte_ausgeben(); |
4 | Messwerte_auslesen(); |
5 | |
6 | |
7 | }
|
Wird die Auslesefunktion über die ISR aufgerufen dann flimmert die Anzeige höchstens kurz und bleibt bei 0000
Meine 7-Segmentanzeige will immer noch nicht so recht. Ich hab mein Programm jetzt mal vereinfacht in dem ich die Messgeschichte rausgehauen habe. Jetzt soll einfach sobald ein Interrupt ausgelöst wird die Variable auf Drehzahl=1234; gesetzt werden und permanent ausgegeben werden. Die Anzeige zeigt aber weiterhin 0000 an und flimmert nach einem Interrupt kurz. Die Variable Drehzahl ist doch global und müsste doch remanent gesetzt werden oder etwa nicht?
Du hast am SIGNAL INPUT einen Pulldown von 100 Ohm. Was ist wenn dein Pulsgeber garnicht nach VCC schaltet, sondern nur nach GND? Was für Pegel hat die Lichtschranke? Ist der Ausgangsstrom stark genug um an dem Widerstand einen High-Pegel zu erzeugen? mfg berliner
Entschuldigung das habe ich vergessen zu ändern. Den 100 Ohm Widerstand habe ich durch einen 10k Ohm Widerstand ersetzt weil es mir, wie du richtig erkannt hast, die 5V vom Output der Gabellichtschranke runtergezogen hat.
Soisdas schrieb: > Entschuldigung das habe ich vergessen zu ändern. Den 100 Ohm Widerstand > habe ich durch einen 10k Ohm Widerstand ersetzt weil es mir, wie du > richtig erkannt hast, die 5V vom Output der Gabellichtschranke > runtergezogen hat. Die Frage ist: Wozu da überhaupt einen Widerstand nach Masse? Bzw. die Lichtschranke so verschalten? Dein Anzeigenmultiplex ist zwar ..... umständlich, allerdings finde ich keinen Fehler. Sofern der Capture Interrupt ausgelöst wird, sollte das eigentlich alles klappen. Vorschlag: Bau den ganzen Klimbim vom Pin PB0 ab und löte statt dessen einen Draht an. Schalte den internen Pullup für PB0 ein. Damit ist der Default Zustand: Pin ist high Capture auf fallende Flanke stellen und dann mit dem Draht mal kurz Masse antippen.
also erzeugt das Auslösen der Gabellichtschranke mit Sicherheit einen Pegelwechsel?
berliner schrieb: > also erzeugt das Auslösen der Gabellichtschranke mit Sicherheit einen > Pegelwechsel? Ich hab eher den Verdacht, dass seine momentane Verschaltung der Lichtschranke einen kurzen Kurzschluss erzeugt. Daher das Flimmern und daher das Rücksetzen auf 0
habs auch mal so gemacht, wie Karl heinz Buchegger sagte: sollte keine Probleme machen.
Hier mal die Peripherieschaltung der Gabellichtschranke. RL ist der 10 kOhm Widerstand und der andere soll der 50 Ohm Schutzwiderstand für die LED darstellen (in Wirklichkeit sind 175Ohm) Aber ich vermute auch dass das Problem hier zu suchen ist.
Soisdas schrieb: > Hier mal die Peripherieschaltung der Gabellichtschranke. RL ist der 10 > kOhm Widerstand und der andere soll der 50 Ohm Schutzwiderstand für die > LED darstellen (in Wirklichkeit sind 175Ohm) Verkabel das mal anders. Im Bild ist ein NPN Transistor eingezeichnet. Den baut man immer so ein, dass er direkt nach Masse durchschaltet: Schmeiss alle Widerstände (bis auf den Led-Vorwiderstand) raus. Dann hängst du die Lichtschranke direkt mit dem Collector an den ICP Pin. Der Emitter des Transistors geht nach Masse. Zusätzlich aktivierst du noch den internen Pullup Widerstand am ICP Pin und konfigurierst den ICP auf fallende Flanke. So eine Lichtschranke wird wie ein nach Masse durchschaltender Taster benutzt.
Ok ich hab das mal so ungestöpselt jetzt bekomm ich den Pullup am PB0 nicht aktiviert oO
1 | DDRD |= 0xFF; |
2 | PORTD = 0; |
3 | |
4 | DDRC |= 0xFF; |
5 | PORTC = 0; |
6 | |
7 | |
8 | DDRB &= ~(1 << DDB0); |
9 | DDRB |= (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4); |
10 | PORTB |= (1 << PB0); //Pullup |
11 | |
12 | |
13 | TCCR1B |= (1<<CS10); // kein PreScale |
14 | TCCR1B &= ~(1<<ICES1); // Fallende Flanke |
15 | TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture + Overflow |
16 | sei(); |
Das sollte doch so funktionieren. Ich messe keine 5V an PB0 auch wenn ich nix dranhängen hab.
1 | void ausgabe(int iziffer, int istelle) |
2 | {
|
3 | seg_port1=0; |
4 | seg_port2=0; |
5 | seg_masse_port=0; <<hier wieder NULL !!! |
siehe Code Sascha
So jetzt hab ich einen Pullupwiderstand dran und die Sache wird nun auf Masse gezogen. Ergebnis bleibt das Gleiche ---> Anzeige flackert nur kurz bei der fallenden Flanke.
hmm ..., jetzt mal ne blöde Frage - hast du im Makefile den richtigen Controllertyp eingestellt? Sascha
Ich werde das Gefühl nicht los, dass dein µC bei einem Interrupt einen Reset macht. Weiß nicht warum. Kannst du mal im main() als erstes eine LED einschalten, halbe Sekunde warten, LED ausschalten. Dann würde man das sehen, wenn ein Reset auftritt und dein Programm neu startet.
Das versuche ich gerade mit:
1 | |
2 | //LED einschalten
|
3 | |
4 | PORTC |= (1<<PC0); |
5 | PORTB |= (1<<PB4); |
6 | |
7 | _delay_ms(2000); |
8 | |
9 | |
10 | PORTB &= ~(1<<PB4); |
11 | PORTC &= ~(1<<PC0); |
Die LED geht zwar an aber nichtmehr aus. Btw ich benutze myAVR Workpad Plus. Ist es möglich mit AVR Studio ein myAVR Multiprog USB Programmer zu programmieren?
Wollte nur mal eben bescheid geben das KarlHeinz recht hatte. Der µC hat sich ständig resetet weil der Watchdogtimer ständig aktiv war. Über die Sofware die Fuses umgestellt und siehe da es geht :)
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.