Forum: Mikrocontroller und Digitale Elektronik Drehzahl über ICP


von Lalo123 (Gast)


Angehängte Dateien:

Lesenswert?

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

von Lalo123 (Gast)


Angehängte Dateien:

Lesenswert?

Sry jetzt hab ich den Schaltplan ganz vergessen.

von Lalo123 (Gast)


Lesenswert?

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 :(

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von Lalo123 (Gast)


Lesenswert?

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?

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

"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.

von Lalo123 (Gast)


Lesenswert?

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

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von Lalo123 (Gast)


Lesenswert?

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

von Soisdas (Gast)


Angehängte Dateien:

Lesenswert?

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?

von berliner (Gast)


Lesenswert?

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

von Soisdas (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von berliner (Gast)


Lesenswert?

also erzeugt das Auslösen der Gabellichtschranke mit Sicherheit einen 
Pegelwechsel?

von Karl H. (kbuchegg)


Lesenswert?

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

von berliner (Gast)


Lesenswert?

habs auch mal so gemacht, wie Karl heinz Buchegger sagte: sollte keine 
Probleme machen.

von Soisdas (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Soisdas (Gast)


Lesenswert?

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.

von Sascha W. (sascha_w)


Lesenswert?

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

von Soisdas (Gast)


Lesenswert?

Ahh ich Heini..... danke ;)

von Soisdas (Gast)


Lesenswert?

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.

von Sascha W. (sascha_w)


Lesenswert?

hmm ..., jetzt mal ne blöde Frage - hast du im Makefile den richtigen 
Controllertyp eingestellt?

Sascha

von Karl H. (kbuchegg)


Lesenswert?

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.

von Soisdas (Gast)


Lesenswert?

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?

von Soisdas (Gast)


Lesenswert?

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 :)

von berliner (Gast)


Lesenswert?

cool....

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
Noch kein Account? Hier anmelden.