mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Drehzahl über ICP


Autor: Lalo123 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Lalo123 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Sry jetzt hab ich den Schaltplan ganz vergessen.

Autor: Lalo123 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...
volatile int Erg = 0;  
int drehzahl =0;
volatile int ziffer = 0;
...
Warum ist "drehzahl" nicht volatile?

  zahl = Erg * 60;            // Drehzahl berechnen aus der Frequenz f*60sec= U/min

  drehzahl=1234;  
"drehzahl" wird nur an dieser einen Stelle gesetzt (was ja nur zu 
Testzwecken drin sein soll), sonst aber auf "0" gelassen.

  ziffer = zahl2/1;   // 1er Stelle für Segmentanzeige
Interessante Berechnung.

Autor: Lalo123 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wenn ich im Kopf drehzahl keinen Wert zuweise und auf static setze:
volatile int Erg = 0;  
static unsigned int drehzahl;  
volatile int ziffer = 0;
volatile int zahl = 0;
volatile int stelle= 0;
volatile int schleife= 0;
volatile int drehzahl2 = 0;
volatile int zahl2 = 0;

Dann müsste doch der Wert "drehzahl" nach dem Aufruf der Funktion 
erhalten bleiben?

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lalo123 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deine Erklärung, ich häng gerade trotzdem noch etwas auf der 
Leitung.


int Messwerte_auslesen()      //Unterprogramm zur Messwertausgabe 
{  
  schleife++;
  
  // liegt eine vollst?ndige Messung vor?

  Erg = (NrOverflows * 65536) + (EndTime - StartTime);

  // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
  Erg = F_CPU / Erg;       // f = 1 / t   

  //aus der Frequenz berechnet sich die Drehzahl
  zahl = Erg * 60;            // Drehzahl berechnen aus der Frequenz f*60sec= U/min

  Mittelwert+=zahl;        // Drehzahl 28x messen
  
  if (schleife<29)
  {
  Messwerte_ausgeben();
  }
  
  else
  {
  schleife=0;
  drehzahl=Mittelwert/28;            // Drehzahl wieder durch 28 dividieren
  Mittelwert=0;
  
  }
  
}  


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

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerade aufgefallen:
void Messwerte_ausgeben(void)  
{
  ...

  return;
}
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.

Autor: Lalo123 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian H. schrieb:
> Wie wird diese Funktion aufgerufen?

Über die main:
  while(1)              
  {
    Messwerte_ausgeben();
       
     if (Ausgabe==TRUE)  
       {
       
       Messwerte_auslesen();
       
          
  }  


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
  while(1)              
  {
    Messwerte_ausgeben();
                Messwerte_auslesen();
       
          
  }  


Wird die Auslesefunktion über die ISR aufgerufen dann flimmert die 
Anzeige höchstens kurz und bleibt bei 0000

Autor: Soisdas (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Autor: berliner (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Soisdas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: berliner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also erzeugt das Auslösen der Gabellichtschranke mit Sicherheit einen 
Pegelwechsel?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: berliner (Gast)
Datum:

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

Autor: Soisdas (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Soisdas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok ich hab das mal so ungestöpselt jetzt bekomm ich den Pullup am PB0 
nicht aktiviert oO
  DDRD |= 0xFF;
  PORTD = 0;
  
  DDRC |= 0xFF;
  PORTC = 0;
  
  
  DDRB &= ~(1 << DDB0);
  DDRB |= (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4); 
  PORTB |= (1 << PB0); //Pullup


  TCCR1B |= (1<<CS10);  // kein PreScale
  TCCR1B &= ~(1<<ICES1); // Fallende Flanke
  TIMSK = (1<<TICIE1) | (1<<TOIE1);   // Interrupts akivieren, Capture + Overflow
  sei();  


Das sollte doch so funktionieren. Ich messe keine 5V an PB0 auch wenn 
ich nix dranhängen hab.

Autor: Sascha Weber (sascha_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void ausgabe(int iziffer, int istelle)
{
  seg_port1=0;
  seg_port2=0;
  seg_masse_port=0;  <<hier wieder NULL !!!
  

siehe Code

Sascha

Autor: Soisdas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahh ich Heini..... danke ;)

Autor: Soisdas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sascha Weber (sascha_w)
Datum:

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

Sascha

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Soisdas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das versuche ich gerade mit:
  
//LED einschalten
  
  PORTC |= (1<<PC0);
  PORTB |= (1<<PB4);
  
  _delay_ms(2000);  
    
  
  PORTB &= ~(1<<PB4);
  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?

Autor: Soisdas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: berliner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cool....

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.