Wie rechnet der uc?

Gast #1635446
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
Gast #1635498
Lesenswert?

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

3
int16_t Verschiebung = 0;
4
uint8_t Ergebnis;
5

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

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

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

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

26
}
Gast #1635507
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
Persönliche Seite #1635508
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:
1
> if ( Ergebnis > 255 ) OCR1A = pgm_read_word( &pwmtable_16 [255] );
2
> if ( Ergebnis < 0 ) OCR1A = pgm_read_word( &pwmtable_16 [0] );
3
> if ( Ergebnis > 255 ) OCR1B = pgm_read_word( &pwmtable_16 [255] );
4
> if ( Ergebnis < 0 ) OCR1B = pgm_read_word( &pwmtable_16 [0] );
5
> OCR1B = pgm_read_word( &pwmtable_16 [Ergebnis] );
#1635541
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
>
1
> Ergebnis = ( ( 100 * Zeit) / 100 ) + (50 + Verschiebung);
2
> if ( Ergebnis > 255 ) OCR1A = pgm_read_word( &pwmtable_16 [255] );
3
> if ( Ergebnis < 0 ) OCR1A = pgm_read_word( &pwmtable_16 [0] );
4
> OCR1A = pgm_read_word( &pwmtable_16 [Ergebnis] );
5

6
>

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
1
  Ergebnis = ( ( 100 * Zeit) / 100 ) + (50 + Verschiebung);
2
  if ( Ergebnis > 255 )
3
    Ergebnis = 255;
4
  else if ( Ergebnis < 0 )
5
    Ergebis = 0;
6

7
  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.
Gast #1635551
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.
Gast #1635602
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?
Persönliche Seite #1635614
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...
#1635638
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?
Gast #1635700
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?
Gast #1635721
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;
#1635722
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

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