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 :(
"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
intMesswerte_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
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.
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.
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
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.
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.
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.
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 :)