mikrocontroller.net

Forum: Compiler & IDEs Normale Division funktioniert nicht


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

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich lese das Drehzahl vom Motor meines Autos über den µC ein. Das Signal 
ist pulsweitenmoduliert. Da es nicht genau sein muss lese ich es einfach 
direkt über einen Portpin ein und zähle mit, wie lange das signal high 
ist. Das funktioniert auch relativ gut (bis auf das, dass ab und zu auch 
komplett unsinnige werte eingelesen werden, aber egal). Die umgerechnete 
Drehzahl gib ich dann am LCD aus.

Das Problem ist nun, dass die division durch 10 und wieder 
anschliessende multiplikation mit 10 anscheinend nicht immer 
funktioniert. Ich will damit nur die unsinnige Einer-Stelle des 
Drehzahlsignals abschneiden. Aber trotzdem zeigt die Drehzahl am LCD ab 
und zu noch eine einerstelle an (also irgendwas anderes als 0). eine 
zeit lang ist die drehzahl am lcd immer im zehnerbereich und dann hab 
ich auf einmal wieder 2568 rpm.

Vielen Dank schonmal im Voraus

mfg Wolfgang

Autor: atze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi, sind deine daten vom typ ganzzahltyp??? gruß atze

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Laß doch die ganze komplizierte Hin- und Herrechnerei sein, rechne von 
vornerein immer mit "drehzahl_in_10rpm" und gib nachher noch eine 0 aus. 
Sollte auch schneller gehen ;-)

also
if (Drehzahl_in_teile > 0)
{
        Drehzahl_in_10rpm = 700000 / Drehzahl_in_teile;
}
(mit einer 0 weniger)

und danach natürlich
if (Drehzahl_in_10rpm > 450) Drehzahl_in_10rpm = 450;
if (Drehzahl_in_10rpm < 50) Drehzahl_in_10rpm = 0;

später hängst du einfach die 0 dran:
strcat(Drehzahl_in_rpm_Temp, "0");

Bedenken mußt du nämlich, daß eine Division, auch wenn sie korrekt 
funktioniert, ganz schön Rechenleistung frißt, vor allem bei long.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ atze: Ja das sind Ganzzahltypen.

@ der mechatroniker: Ja das stimmt. Diese paar Berechnungen fressen mir
                     sehr die Rechenleistung auf.


Und was ist jetzt der Grund dafür, dass die Ausgabe der Drehzahl am LCD 
ab und zu stimmt und dann wieder nicht?

Autor: GastABC (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entweder optimiert der Compiler /10 *10 weg (kann ich mir eigentlich 
nicht vorstellen), oder der Fehler liegt wo anders:

Wie gibst du denn die Drehzahl aus? Interrupt-gesteuert? Wenn ja, dann 
könnte der Interrupt ja auch genau beim Abarbeiten des Drehzahl-lesens 
eintreffen und Dir damit deine Werte versauen. Nu so eine Idee.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Ausgabe erfolgt ganz normal am Schluss der Hauptschleife. Nach den 
ganzen Berechnungen und Einlesen der Ports, usw. Das kanns nicht sein.

Dass der Compiler es weg optimiert glaub ich auch nicht, da beim Wert am 
Display die meiste Zeit die Einerstelle dann 0 ist. Ab und zu dann für 
ein paar Sekunden dann aber wieder nicht. Es ist auch kein Muster zu 
erkennen, dass es regelmäßig dann die Einerstelle wieder ausgibt.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void Drehzahl_einlesen (void)
{
...

if (bit_is_clear(PIND, 3) && freigabe_drehzahl == 2)
{
freigabe_drehzahl = 0;
}

...
}

Ist es gewollt, daß freigabe_drehzahl == 2 bleibt, wenn nach dem 
Verlassen der while-Schleife bit_is_clear(PIND, 3) false zurückgibt?

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja das ist gewollt da die if in der while nur zum begrenzen der variable 
und somit der unteren drehzahlgrenze dient. Aber durch das hast du mich 
auf etwas anderes aufmerksam gemacht. Muss ich gleich mal nachschauen. 
Ich meld mich später wieder...

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hab eine neue Methode ausprobiert, die das Signal genauer einliest 
ohne Schwankungen, aber dafür blockiere ich den µC damit. Dachte am 
Anfang das wär nicht so arg, aber anscheinend doch. Die 
Aktualisierungszeit des Drehzahlsignals ist dadurch auf ein paar 
Sekunden gestiegen!

Hier der Code:

if (bit_is_clear(PIND, 3))
{
  Drehzahl_in_teile = 0;

  while (bit_is_clear(PIND, 3)) {};
  while ((bit_is_set(PIND, 3)) && (Drehzahl_in_teile < 65000)) 
Drehzahl_in_teile++;
}

Der Code an sich stimmt ja oder? Aber kann es wirklich sein, dass dieser 
code den µC so ausbremst?

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie würde bei euch der Code für das Einlesen eines PWM-Signals von einem 
Datenpin aussehen? (ohne Timer und Interrupt, die sind schon für eine 
pwm-ausgabe in verwendung) Ich brauche keinen kompletten Source-Code, 
sondern eh nur die Stelle mit der Abfrage.

Das Signal hat eine Periodendauer von ein paar ms, der Takt des µC ist 
16MHz und die Abfrage sollte den µC nicht zu lange auslasten, da ich 
auch noch Spannungen mittels ADC einlese und die dann immer schnell am 
LCD angezeigt werden sollen, ohne "Ruckler". es wäre gut wenn das Signal 
um die 10 mal/s eingelesen wird, nicht langsamer.

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

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang wrote:

> Aber kann es wirklich sein, dass dieser
> code den µC so ausbremst?

Dein Code pollt das Signal. Er wartet also solange in der
Schleife, bis er einen kompletten High-Puls des Signals gesehen
hat.
Das 'Ausbremsen' ist also per Design: In der Zeit, in der der
Eingangspegel des Signals auf High ist, passiert nichts weiter
(ausser einem möglichen Interrupt) und kann auch nichts weiter
passieren.

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

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang wrote:
> Wie würde bei euch der Code für das Einlesen eines PWM-Signals von einem
> Datenpin aussehen? (ohne Timer und Interrupt, die sind schon für eine
> pwm-ausgabe in verwendung)

Es gibt nur die beiden Möglichkeiten
* entweder du pollst das Signal
* oder du lässt dir einen Interrupt vom Signal erzeugen, wenn
  es den Pegel wechselst. Allerdings brauchst du dazu einen Timer,
  denn irgendwie musst du ja auch die Zeit messen.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass der µC durch das Pollen ausgebremst wird ist mir klar, mir ist nur 
nicht klar, warum die Aktualisierungsrate des LCD auf einmal alle 3 
sekunden ansteigt mit diesem code hier:

if (bit_is_clear(PIND, 3))
{
  Drehzahl_in_teile = 0;

  while (bit_is_clear(PIND, 3)) {};
  while ((bit_is_set(PIND, 3)) && (Drehzahl_in_teile < 65000))
Drehzahl_in_teile++;
}

Mit dem alten Code hier hingegen funktioniert es einwandfrei, dass die 
Werte am LCD mehrere Male pro Sekunde aktualisiert werden, ohne dass 
irgend ein anderer Programmteil geändert wurde.

if (bit_is_clear(PIND, 3) && freigabe_drehzahl == 0)
  {
    freigabe_drehzahl = 1;
    Drehzahl_in_teile = 0;
  }

  while ((bit_is_set(PIND, 3) && freigabe_drehzahl == 1))
  {
    Drehzahl_in_teile++;

    if (Drehzahl_in_teile > 65000)
    {
      freigabe_drehzahl = 2;
    }
  }

  if (bit_is_clear(PIND, 3) && freigabe_drehzahl == 2)
  {
    freigabe_drehzahl = 0;
  }

Will den ganz obigen neuen Code aber lieber verwenden, da er genauer ist 
als der untere, bezüglich wann der Beginn des High ist. Der µC läuft ja 
mit 16MHz und das Signal hat eine Periodendauer von maximal 50ms. Warum 
schaut es dann so aus, als ob der µC für mehrere Sekunden blockiert ist 
mit dieser Polling-Methode? Denkfehler im Code?

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.