mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wie rechnet der uc?


Autor: Der Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich sitze momentan vor einem kleinen Problem.

Ich möchte zwei LEDs über einen bestimmten Zeitraum automatisch faden 
und dabei manuell dimmen können. Dabei können beide LEDs einen 
unterschiedlichen Wert haben; z.B. LED1 = 52 und LED2 = 220.

Wenn ich jetzt BEIDE heller oder dunkler machen möchte, kommt 
automatisch eine vor der anderen an die Grenze. Den Helligkeitswert 
(0...255) muß ich über eine Geradengleichung ausrechnen, da ein 
Lookuptable bei meiner Aufgabe zu umfangreich wäre.

Die Gleichung sieht aus wie folgt:

Ergebnis = ( ( m * x ) / 100 ) + n + Verschiebung

Dabei sind m (-200...+200) und n (0...255) fix ;x ist die Zeit.
Die Verschiebung stellt nun meine Helligkeit höher oder tiefer WÄHREND 
des fadens. Das Problem ist, dass ich jedes mal über die Grenze 
hinausschiesse und der uc alles macht; nur nie das Richtige ;-).

Für meine Grenzen habe ich

if ( Ergebnis > 255 ) OCR1A = pgm_read_word( &pwmtable_16 [255] );
if ( Ergebnis < 0 ) OCR1A = pgm_read_word( &pwmtable_16 [0] );

if ( Ergebnis > 255 ) OCR1B = pgm_read_word( &pwmtable_16 [255] );
if ( Ergebnis < 0 ) OCR1B = pgm_read_word( &pwmtable_16 [0] );

Kann mir einer erklären, warum die Grenzen NICHT beachtet werden und der 
uc jedes mal son Mist macht?

Wäre schön, wenn einer ne Idee hat.

LG

Jens

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

Bewertung
0 lesenswert
nicht lesenswert
Der Jens schrieb:

> Kann mir einer erklären, warum die Grenzen NICHT beachtet werden und der
> uc jedes mal son Mist macht?

Ohne komplettes Program: Nein

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Je nach Datentyp kann dein Ergebnis nie größer als 255 und nie 
kleiner als 0 werden, was deine Abfragen natürlich ad absurdum führt.

Autor: Der Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK. Hier mal die wesentlichen Teile . Zur Zeit sei noch dazu gesagt. Sie 
wird in einer ISR von 0...100 gezählt
int main (void) {

int16_t Verschiebung = 0;
uint8_t Ergebnis;

if (!(PINB & (1 << PB0))) {  // dunkler    
Verschiebung--;
long_delay(20);  // 20 * 1ms
}

if (!(PINB & (1 << PB1))) {  // heller
Verschiebung++;
long_delay(20);  // 20 * 1ms
}

Ergebnis = ( ( 100 * Zeit) / 100 ) + (50 + Verschiebung);
if ( Ergebnis > 255 ) OCR1A = pgm_read_word( &pwmtable_16 [255] );
if ( Ergebnis < 0 ) OCR1A = pgm_read_word( &pwmtable_16 [0] );
OCR1A = pgm_read_word( &pwmtable_16 [Ergebnis] );

Ergebnis = ( ( -100 * Zeit) / 100 ) + (50 + Verschiebung);
if ( Ergebnis > 255 ) OCR1B = pgm_read_word( &pwmtable_16 [255] );
if ( Ergebnis < 0 ) OCR1B = pgm_read_word( &pwmtable_16 [0] );
OCR1B = pgm_read_word( &pwmtable_16 [Ergebnis] );

}

Autor: Sven T. (svent)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
was passiert denn wenn eine 8 bit Variable (uint8_t) den Wert 255 hat 
und ich 1 addiere ?
Sie wird 0 ;-)

Umgekehrt passiert ägnliches.

IMO kann ein uint8 NIE größer 255 oder kleiner 0 werden.
Und das ist das Problem bei den Abgragen.

S.

Autor: weene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

OCR1B wird überschrieben:

if ( Ergebnis > 255 ) OCR1B = pgm_read_word( &pwmtable_16 [255] );
if ( Ergebnis < 0 ) OCR1B = pgm_read_word( &pwmtable_16 [0] );
OCR1B = pgm_read_word( &pwmtable_16 [Ergebnis] );

besser:
if ( Ergebnis > 255 ) Ergebnis = 255;
if ( Ergebnis < 0 ) Ergebnis = 0;
OCR1B = pgm_read_word( &pwmtable_16 [Ergebnis] );

aber warum nimmst du nicht gleich eine 8 bit Variable für das Ergebnis?
Dann kannst du die Prüfung weglassen.

(Achtung: bei den Berechnung in größeren Variablen bzw. float rechnen)


MFG
weene

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Jens schrieb:

> uint8_t Ergebnis;
Das heißt "unsigned int mit 8 bit". Der Wertebereich ist 0 bis 255.

Das kann also nie zutreffen:
> if ( Ergebnis > 255 ) OCR1A = pgm_read_word( &pwmtable_16 [255] );
> if ( Ergebnis < 0 ) OCR1A = pgm_read_word( &pwmtable_16 [0] );
> if ( Ergebnis > 255 ) OCR1B = pgm_read_word( &pwmtable_16 [255] );
> if ( Ergebnis < 0 ) OCR1B = pgm_read_word( &pwmtable_16 [0] );
> OCR1B = pgm_read_word( &pwmtable_16 [Ergebnis] );

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
weene schrieb:
> aber warum nimmst du nicht gleich eine 8 bit Variable für das Ergebnis?
> Dann kannst du die Prüfung weglassen.

Das ist eine 8 bit Variable.

Autor: weene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok mein Fehler...

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian H. schrieb:
> Das kann also nie zutreffen:

Ich meinte nur die If-Anweisungen, nicht die OCR1B-Zuweisung.

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

Bewertung
0 lesenswert
nicht lesenswert
Der Jens schrieb:
> OK. Hier mal die wesentlichen Teile . Zur Zeit sei noch dazu gesagt. Sie
> wird in einer ISR von 0...100 gezählt
>

> Ergebnis = ( ( 100 * Zeit) / 100 ) + (50 + Verschiebung);
> if ( Ergebnis > 255 ) OCR1A = pgm_read_word( &pwmtable_16 [255] );
> if ( Ergebnis < 0 ) OCR1A = pgm_read_word( &pwmtable_16 [0] );
> OCR1A = pgm_read_word( &pwmtable_16 [Ergebnis] );

> 

Selbst wenn Ergebnis ein int16_t wäre (was es sein müssen wird):

Gehs durch.
Du rechnest dir ein Ergebnis aus.
Ist das Ergebnis zu groß setzt du einen Wert
Wenn das Ergebnis zu klein ist setzt du einen anderen Wert
Und dann: Dann setzt du auf jeden Fall noch den Wert, den du durch die 
Rechnerei erhalten hast.

D.h. Deine if sind völlig für die Katz, weil du danach immer auf jeden 
Fall noch dein Rechenergebnis benutzt.

Wenn schon, dann so
  Ergebnis = ( ( 100 * Zeit) / 100 ) + (50 + Verschiebung);
  if ( Ergebnis > 255 )
    Ergebnis = 255;
  else if ( Ergebnis < 0 )
    Ergebis = 0;

  OCR1A = pgm_read_word( &pwmtable_16 [Ergebnis] );

Dazu muss aber Ergebnis überhaupt in der Lage sein, Werte größer 255 
bzw. kleiner 0 annehmen zu können. Ein uint8_t kann das per Definiton 
schon mal nicht.

Autor: Udo. R. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>uint8_t Ergebnis;
>if (Ergebnis > 255)
>if ( Ergebnis < 0 )

beide Bedingungen können nie vorkommen, da der Wertebereich der uint8 
von 0 - 255 geht.

Auch die Berechnung
>( 100 * Zeit) / 100 )
ist ziemlich sinnfrei, da sich das zu Zeit kürzt.

Wenn ich Dich richtig verstehe willst Du daß beim Fading deiner LEDs es 
bei einer LED die auf dem Helligkeitswert 200 steht genau so lange 
dauert wie wenn die Diode den Helligkeitswert 50 hat.

Dann ist die Steigung deiner Geraden eben nicht konstant, sondern die 
ist abhängig von dem Startwert.

Bei der Diode mit dem Startwert 200 muss die Änderung der Helligkeit pro 
Zeit viermal höher ausfallen als bei der mit dem Wert 50.

Autor: Der Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> D.h. Deine if sind völlig für die Katz, weil du danach immer auf jeden
>
> Fall noch dein Rechenergebnis benutzt.

genau DAS war mein Problem!! Das mit uint8_t <-> int16_t ist mir vorhin 
dann doch noch selber aufgefallen.

Krass; wie seht ihr sowas nur immer?! wunderbar! :-)

Danke nochmal.

Eine kleine Formfrage hätte ich aber noch. Du schreibst die Abfrage so:

> if ( Ergebnis > 255 )
>
>     Ergebnis = 255;
>
>   else if ( Ergebnis < 0 )
>
>     Ergebis = 0;


ich würde sie so schreiben:

if ( Ergebnis > 255 )
  Ergebnis = 255;
if ( Ergebnis < 0 )
  Ergebnis = 0;

Also warum benutzt du ein else if? Gibt es 
Geschwindwigkeits-/Codegrößenvorteile oder ist es so nur besser zu 
sehen, dass beide if's zusammen gehören?

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Jens schrieb:
> Krass; wie seht ihr sowas nur immer?! wunderbar! :-)
z.B. in dem wir nicht versuchen maximal viel Befehle in eine Zeile zu 
quetschen... Ich weiß gar nicht wo so was herkommt wird das als 
besonders 'cool' angesehen?

Und ich persönlich gehe sogar soweit das ich immer Klammern setze auch 
wenn die Bedingung/Schleife nur eine Anweisung umfasst...

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

Bewertung
0 lesenswert
nicht lesenswert
Der Jens schrieb:

> ich würde sie so schreiben:
>
> if ( Ergebnis > 255 )
>   Ergebnis = 255;
> if ( Ergebnis < 0 )
>   Ergebnis = 0;
>
> Also warum benutzt du ein else if?

Weil, wenn schon feststeht das Ergebnis größer als 255 ist, es nicht 
mehr sein kann, das Ergebnis kleiner als 0 ist.
Wozu etwas abtesten, von dem ich den Ausgang sowieso schon kenne?

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Zeile finde ich auch noch fragwürdig:
Ergebnis = ( ( -100 * Zeit) / 100 ) + (50 + Verschiebung);

Wenn Zeit von 0 - 100 geht, dann kann Ergebnis je nach Verschiebung auch 
negativ werden. Durch die 8 bit Variable liegt ne negative Variable dann 
im Bereich 128-255. Beim Übergang von einem positiven Ergebnis zum 
negativen Ergebnis springt also der PWM-Wert von z.B. &pwmtable_16[0] um 
auf @pwmtable_16[255]. Ob das so gewollt ist?

Autor: Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und um die Frage zu beantworten: Eigentlich kann er nur addieren... 
(duck, und wech)

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MagIO schrieb:
> Beim Übergang von einem positiven Ergebnis zum
> negativen Ergebnis springt also der PWM-Wert von z.B. &pwmtable_16[0] um
> auf @pwmtable_16[255]. Ob das so gewollt ist?

Was meinst du wohl, was diese Zeile hier bewirken soll?  ;-)

Der Jens schrieb:
> if ( Ergebnis < 0 )
>   Ergebnis = 0;

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

Bewertung
0 lesenswert
nicht lesenswert
MagIO schrieb:
> Die Zeile finde ich auch noch fragwürdig:
> Ergebnis = ( ( -100 * Zeit) / 100 ) + (50 + Verschiebung);
>
> Wenn Zeit von 0 - 100 geht, dann kann Ergebnis je nach Verschiebung auch
> negativ werden.


Er hat aber auch im Eröffnungspoting geschrieben, dass die erste 100 
hier

> Ergebnis = ( ( -100 * Zeit) / 100 ) + (50 + Verschiebung);
                 ****

eigentlich ein m ist mit einem Wertebereich von -200 .. 200. Fass diese 
100 und die 50 und die Verschiebung einfach nur als x-beliebige Werte 
auf, mit denen zur Zeit einfach nur getestet wird. Die werden sich 
sicherlich noch ändern.

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.