Drehzahl über ICP

Gast #1989108
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
Angehängte Dateien:
Gast #1989340
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 :(
Persönliche Seite #1989388
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.
Gast #1989444
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?
Persönliche Seite #1989781
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.
Gast #1990503
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
Persönliche Seite #1990642
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.
Gast #1990669
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
Gast #1999223
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?
Angehängte Dateien:
Gast #1999251
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
Gast #1999295
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.
#1999303
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.
#1999374
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.
Gast #1999487
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.
Gast #2000126
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?
Gast #2002451
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 :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren