Forum: Mikrocontroller und Digitale Elektronik Arduino LED Dimmen zeitgesteuert und logarithmisch -brauche hilfe


von Daniel (Gast)


Lesenswert?

Hallo,

ich möchte über meinem Aquarium eine LED dimmen.
Dazu habe ich einen Arduino Uno und eine DS1307 RTC.
Aus einem älteren Beitrag hier im Forum habe ich den Code.
Das war dieser Beitrag Beitrag "Propleme beim Zeitgesteuerten Dimmen einer LED"
Ich verwende jedoch kein LCD Display.


Nach ersten Tests läuft der Code.

Meine Frage: Wie kann ich in diesen Code verändern damit die LED fürs 
Menschliche auge gleichmäßig dimmt also logarithmisch.
Ich bin anfänger im Arduino Bereich und bin für eure Hilfe und 
Lösungsansätze wirklich dankbar. Ich weiß nicht in welche Richtung ich 
jetzt gehen muss.

Ach so, hier nochmal der Code wie ich Ihn jetzt benutze:
1
#include <Time.h>
2
#include <TimeLib.h>
3
#include "Wire.h"
4
5
int ledPin = 10;                                          // LED Pin setzen
6
7
#define DS1307_I2C_ADDRESS 0x68                          // I2C Adresse
8
char buffer[20] = "";
9
10
11
byte bcdToDec(byte val)
12
{
13
  return ( (val/16*10) + (val%16) );
14
}
15
16
17
//Zeit und Datum aus DS1307 auslesen und konvertieren
18
19
void getDateDs1307(int date[])
20
{
21
  Wire.beginTransmission(DS1307_I2C_ADDRESS);         // I2C-Kommunikation im Schreibmodus starten
22
  Wire.write(0x00);                                   // Registerzeiger auf 0 setzen
23
  Wire.endTransmission();                             // I2C-Kommunikation beenden 
24
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);            // I2C-Kommunikation im Lesemodus starten
25
26
  date[ 0 ] = bcdToDec(Wire.read() & 0x7f);        // Sekunden
27
  date[ 1 ] = bcdToDec(Wire.read());               // Minuten
28
  date[ 2 ] = bcdToDec(Wire.read() & 0x3f);        // Stunden
29
  date[ 3 ] = bcdToDec(Wire.read());               // Wochentag
30
  date[ 4 ] = bcdToDec(Wire.read());               // Tag
31
  date[ 5 ] = bcdToDec(Wire.read());               // Monat
32
  date[ 6 ] = bcdToDec(Wire.read());               // Jahr
33
}
34
35
/****************************************************************************************************
36
 */
37
void setup() {
38
  Wire.begin();                                      // I2C-Bus einrichten
39
40
41
  
42
}
43
44
/****************************************************************************************************
45
 */
46
void loop() {
47
48
  int datum[ 7 ];  
49
  int licht;
50
  char str[30];
51
  
52
  
53
getDateDs1307( datum );                            // Datum und Uhrzeit aus DS1307 holen
54
55
int maxlicht = 255;
56
long  dimmsekunde = datum[1]*60;
57
int gesamtdimmsekunden = 1800;  // Zeitliche Spanne des rauf und runter dimmens 1800sekunden sind eine halbe stunde
58
59
60
  // von Mitternacht bis 8 Uhr (7:59:59)
61
  // ist das Licht aus
62
  if( datum[2] < 8 ) {
63
    licht = 0;
64
  }
65
66
  // von 8 Uhr, bis 8 Uhr 30 berechnet sich eine Dimmstufe
67
  // hochdimmen!
68
  else if( datum[2] == 8 && datum[1] < 30 ) {
69
    licht = maxlicht * dimmsekunde / gesamtdimmsekunden;
70
  }
71
72
  // von 8:30 bis 17:59:59 ist das Licht an
73
  else if( datum[2] < 18 ){
74
    licht = 255;
75
  }
76
  // von 6 bis halb 7 wird wieder eine Dimmstufe berechnet
77
  // aber diesmal runterdimmen!
78
  else if( datum[2] == 18 && datum[1] < 30 ) {
79
    licht = maxlicht - (maxlicht * dimmsekunde / gesamtdimmsekunden);
80
  }
81
82
  // und für den Rest des Tages (kann dann nur noch nach halb 7 sein)
83
  // wird das Licht abgedreht
84
  else
85
    licht = 0;
86
87
  // jetzt noch schnell die Lampe tatsächlich anhand der
88
  // vorher bestimmten Werte einstellen
89
  analogWrite( 10, licht );
90
91
   // ... und der Benutzer will auch sehen wie spät es ist
92
  //sprintf( str, "%02d-%02d-%02d%02d:%02d:%02d",
93
                    // datum[4], datum[5], datum[6],
94
                     //datum[2], datum[1], datum[0] );
95
 
96
}

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Daniel schrieb:

> Meine Frage: Wie kann ich in diesen Code verändern damit die LED fürs
> Menschliche auge gleichmäßig dimmt also logarithmisch.

Man könnte das formelmässig korrigieren, indem man den Lichtwert erst 
durch eine Exponentialfunktion jagt, die ihn so "verzerrt", dass durch 
die logarithmische Kennlinie des Auges sich dann alles wieder 
ausgleicht. Gegen die Kennlinie des Auges kannst du nichts tun, die ist 
dir vorgegeben. Aber du kannst natürlich dieser vorgegebenen Kennlinie 
eine andere davorsetzen, so dass die logarithmische Kennlinie dann 
wieder alles gerade biegt.
An und für sich ist die Berechnung gar nicht mal so aufwändig. Aber im 
einfachsten Fall benutzt man dazu einfach eine Tabelle, in der diese 
Kennlinie schon eingearbeitet ist.
Du findest zb hier eine
https://www.mikrocontroller.net/articles/LED-Fading


Dann heisst es bei dir dann eben
1
    ....
2
3
    // exponentielle Kennlinie anwenden
4
    licht = tabelle[licht];
5
6
    // jetzt noch schnell die Lampe tatsächlich anhand der
7
    // vorher bestimmten Werte einstellen
8
    analogWrite( 10, licht );
9
10
    ....

von Daniel (Gast)


Lesenswert?

Hallo Karl Heinz,

danke für den Denkanstoß aber leider komme ich noch nicht weiter.

also, die Zeilen

const uint16_t pwmtable_16[256] PROGMEM =
{
    0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
    3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7,
    7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15,
    15, 16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
    31, 32, 33, 35, 36, 38, 40, 41, 43, 45, 47, 49, 52, 54, 56, 59,
    61, 64, 67, 70, 73, 76, 79, 83, 87, 91, 95, 99, 103, 108, 112,
    117, 123, 128, 134, 140, 146, 152, 159, 166, 173, 181, 189, 197,
    206, 215, 225, 235, 245, 256, 267, 279, 292, 304, 318, 332, 347,
    362, 378, 395, 412, 431, 450, 470, 490, 512, 535, 558, 583, 609,
    636, 664, 693, 724, 756, 790, 825, 861, 899, 939, 981, 1024, 1069,
    1117, 1166, 1218, 1272, 1328, 1387, 1448, 1512, 1579, 1649, 1722,
    1798, 1878, 1961, 2048, 2139, 2233, 2332, 2435, 2543, 2656, 2773,
    2896, 3025, 3158, 3298, 3444, 3597, 3756, 3922, 4096, 4277, 4467,
    4664, 4871, 5087, 5312, 5547, 5793, 6049, 6317, 6596, 6889, 7194,
    7512, 7845, 8192, 8555, 8933, 9329, 9742, 10173, 10624, 11094,
    11585, 12098, 12634, 13193, 13777, 14387, 15024, 15689, 16384,
    17109, 17867, 18658, 19484, 20346, 21247, 22188, 23170, 24196,
    25267, 26386, 27554, 28774, 30048, 31378, 32768, 34218, 35733,
    37315, 38967, 40693, 42494, 44376, 46340, 48392, 50534, 52772,
    55108, 57548, 60096, 62757, 65535
};

habe ich bereits schon einmal verwendet zusammen mit millis und ohne 
RTC.
Leider hatte ich dabei das Problem das dann immer ein FadeValue und 
Delay in der Funktion vor kam. Da ich einen BUZ11 verwende für meine 24V 
LED, gab es dann immer eine kurze Auszeit für die LED.

Ich komme jetzt nicht weiter wie ich den pwmtable auf zB 1800Sekunden 
verteile.

Gruß, Daniel

von Karl H. (kbuchegg)


Lesenswert?

Daniel schrieb:

> Ich komme jetzt nicht weiter wie ich den pwmtable auf zB 1800Sekunden
> verteile.

Das heisst also, du hast den Code nur abgeschrieben. Sauber. Das rächt 
sich jetzt.
Ich denke ich hab in dem von dir verlinkten Atikel mehr als ausführlich 
die Herleitung des Programmes mit dem damaligen Fragesteller 
durchbesprochen.

PS. Deine PWM geht nur von 0 bis 255 und nicht von 0 bis 65535. Daher 
wird dir diese Tabelle nicht viel helfen.
Du musst schon eine nehmen, in der keine grösseren Werte als 255 
vorkommen.
(die hat dann allerdings nur mehr 32 Dimmstufen).
Die hier zum Beispiel
1
const uint16_t pwmtable_8D[32] =
2
{
3
    0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
4
    27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255
5
};
allerdings musst du dann auch deine Berechnung
1
int maxlicht = 255;
entsprechend anpassen. Denn du hast ja keine 256 Dimm-Stufen mehr, 
sondern nur noch 32. Irgendeinen Tod musst du sterben. Entweder du 
akzeptierst, dass die Helligkeitszunahme nicht linear ist, oder du lässt 
einige Dimmstufen aus, damit du aus dem Rest zusammen mit der 
logarithmischen Kennlinie eine lineare Zunahme bauen kannst. Aber beides 
zusammen geht nicht.
(Oder aber du machst die PWM selber anstatt die vorgfertigte 
analog_write zu benutzen. Denn die kann eben nur 8 Bit PWM, mit Werten 
von 0 bis 255)

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.