Forum: Haus & Smart Home Einschaltverzögerung Bodenstrahler mit BM


von s-buali (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem. Ich will in meine Hofeinfahrt 4-5
LED-Bodenstrahler einbauen. Nun kam mir die Idee einer verzögerten
Einschaltung der einzelnen Strahler. Sprich ähnlich wie bei einem
Lauflicht, soll beim Auslösen eines Bewegungsmelders zu erst der 1.
Strahler, dann zeitlich versetzt der 2. Strahler und so weiter,
eingeschalten werden. Bei erreichen des 4 bzw 5. Strahler sollen alle in
einer Art Selbsthaltung bleiben, bis die "Einschaltzeit" des
Bewegungsmelders alle Strahler gleichtzeitig abschält.

vielleicht noch zu Ergänzung:

habe die Bodenstrahler noch nicht gekauft um etwas flexibel zu bleiben.
Solche Bodenstrahler gibt es meines Wissens mit 230 V und 12 V.

Nun habe ich grobe Kenntnisse im Bereich Elektronik aber komme nicht
selber auf eine Lösung und bitte um Hilfe. Zeit-Relais sind mir
eigentlich generell zu teuer, da ich ja mehrere bräuchte.

Hat mir jemand eine gut umsetzbare und kostengünstige Lösung?

Vielen Dank schon im Voraus

Grüße

s-buali

von Frank (Gast)


Lesenswert?

Ganz ohne Elektronik (-Kenntnisse) wirds nicht gehen. Das Projekt 
besteht aus vier Teilen, das macht die Sache sehr übersichtlich. Es geht 
sicher auch viel kompakter ("einfacher" - entsprechende Beiträge werden 
nicht lange auf sich warten lassen), aber dann ist es nicht gut für 
Anfänger geeignet.

a) die Leistungsschalter für die Lampen, optisch potentialgetrennt
b) die Steuerung für das Zeitverhalten
c) dem Empfänger/Auslöser
d) Netzteil für b u. c

Die kann man alle einzeln aufbauen, testen und wenn sie funktionieren 
zusammen in ein Gehäuse Setzen und in Betrieb nehmen.

zu a) da würde ich Solid-State-Relais nehmen. Einfach aunzusteuern, ohne 
Verschleiß

zu b) ICH würde da einen MC nehmen, es geht aber auch mit einem Zähler 
oder Schieberegister nebst Taktgenerator aus Logikbausteinen - je nach 
Vorliebe. Oder so einen LED-Bar-Controller für Audioanzeigen an einem 
sich ladenden Kondensator.

zu c) ist im einfachsten Fall ein Schalter. Oder ein IR- bzw. 
Funkempfäger. Kann auch ein Relais sein, was z.B. vom Gartentorantrieb 
nebenbei mit ausgelöst wird

zu d) ohne große Erklärung

von Hugo P. (portisch)


Angehängte Dateien:

Lesenswert?

Ich habe sowas für mein Stiegenlicht umgesetzt.
Aber um einen µC wirst du nicht rumkommen.

Mein System läuft auf 12V.

Wenn die 12V vom Netzteil kommen fährt der µC an. Je nach Input Pin 
PINB0 wird das Lauflicht von unten oder oben gestartet. Zusätzlich habe 
ich die SoftPWM übernommen, damit ich die Leitungslängen zu den 
einzelnen Lichter kompensiert werden kann.

PINB1 dient dazu, da eine Stiege nur 9 Lichter hat und die andere 11.
Über DelayBetweenPINs kann die Verzögerung der einzelnen Lichter 
eingestellt werden.

Funktioniert einwandfrei!
1
/*
2
    Eine 8-kanalige PWM mit intelligentem Lösungsansatz
3
 
4
    ATmega32 @ 8 MHz
5
 
6
*/
7
 
8
// Defines an den Controller und die Anwendung anpassen
9
 
10
#define F_CPU         12000000L          // Systemtakt in Hz
11
#define F_PWM         100L               // PWM-Frequenz in Hz
12
#define PWM_PRESCALER 8                  // Vorteiler für den Timer
13
#define PWM_STEPS     256                // PWM-Schritte pro Zyklus(1..256)
14
#define PWM_PORT_1    PORTD              // Port für PWM
15
#define PWM_DDR_1     DDRD               // Datenrichtungsregister für PWM
16
#define PWM_PORT_2    PORTC              // Port für PWM
17
#define PWM_DDR_2     DDRC               // Datenrichtungsregister für PWM
18
#define PWM_CHANNELS  11                 // Anzahl der PWM-Kanäle
19
20
// ab hier nichts ändern, wird alles berechnet
21
 
22
#define T_PWM (F_CPU/(PWM_PRESCALER*F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
23
//#define T_PWM 1   //TEST
24
 
25
#if ((T_PWM*PWM_PRESCALER)<(111+5))
26
    #error T_PWM zu klein, F_CPU muss vergrössert werden oder F_PWM oder PWM_STEPS verkleinert werden
27
#endif
28
 
29
#if ((T_PWM*PWM_STEPS)>65535)
30
    #error Periodendauer der PWM zu gross! F_PWM oder PWM_PRESCALER erhöhen.   
31
#endif
32
// includes
33
 
34
#include <stdint.h>
35
#include <string.h>
36
#include <avr/io.h>
37
#include <avr/interrupt.h>
38
#include <util/delay.h>
39
 
40
// globale Variablen
41
42
uint16_t PINFreigabe = 0;
43
uint8_t DelayBetweenPINs = 50;          // verzögerung zwischen den ausgängen
44
 
45
uint16_t pwm_timing[PWM_CHANNELS+1];          // Zeitdifferenzen der PWM Werte
46
uint16_t pwm_timing_tmp[PWM_CHANNELS+1];      
47
 
48
uint16_t  pwm_mask[PWM_CHANNELS+1];            // Bitmaske für PWM Bits, welche gelöscht werden sollen
49
uint16_t  pwm_mask_tmp[PWM_CHANNELS+1];        // ändern uint16_t oder uint32_t für mehr Kanäle
50
 
51
uint8_t  pwm_setting[PWM_CHANNELS];           // Einstellungen für die einzelnen PWM-Kanäle
52
uint8_t  pwm_setting_tmp[PWM_CHANNELS+1];     // Einstellungen der PWM Werte, sortiert
53
                                              // ändern auf uint16_t für mehr als 8 Bit Auflösung  
54
 
55
volatile uint8_t pwm_cnt_max=1;               // Zählergrenze, Initialisierung mit 1 ist wichtig!
56
volatile uint8_t pwm_sync;                    // Update jetzt möglich
57
 
58
// Pointer für wechselseitigen Datenzugriff
59
 
60
uint16_t *isr_ptr_time  = pwm_timing;
61
uint16_t *main_ptr_time = pwm_timing_tmp;
62
 
63
uint16_t *isr_ptr_mask  = pwm_mask;              // Bitmasken fuer PWM-Kanäle
64
uint16_t *main_ptr_mask = pwm_mask_tmp;          // ändern uint16_t oder uint32_t für mehr Kanäle
65
 
66
// Zeiger austauschen
67
// das muss in einem Unterprogramm erfolgen,
68
// um eine Zwischenspeicherung durch den Compiler zu verhindern
69
 
70
void tausche_zeiger(void) {
71
    uint16_t *tmp_ptr16;
72
    uint16_t *tmp_ptr8;                          // ändern uint16_t oder uint32_t für mehr Kanäle
73
 
74
    tmp_ptr16 = isr_ptr_time;
75
    isr_ptr_time = main_ptr_time;
76
    main_ptr_time = tmp_ptr16;
77
    tmp_ptr8 = isr_ptr_mask;
78
    isr_ptr_mask = main_ptr_mask;
79
    main_ptr_mask = tmp_ptr8;
80
}
81
 
82
// PWM Update, berechnet aus den PWM Einstellungen
83
// die neuen Werte für die Interruptroutine
84
 
85
void pwm_update(void) {
86
 
87
    uint8_t i, j, k;
88
    uint16_t m1, m2, tmp_mask;                   // ändern uint16_t oder uint32_t für mehr Kanäle    
89
    uint8_t min, tmp_set;                       // ändern auf uint16_t für mehr als 8 Bit Auflösung
90
 
91
    // PWM Maske für Start berechnen
92
    // gleichzeitig die Bitmasken generieren und PWM Werte kopieren
93
 
94
    m1 = 1;
95
    m2 = 0;
96
    for(i=1; i<=(PWM_CHANNELS); i++) {
97
        main_ptr_mask[i]=~m1;                       // Maske zum Löschen der PWM Ausgänge
98
        pwm_setting_tmp[i] = pwm_setting[i-1];
99
        if (pwm_setting_tmp[i]!=0) m2 |= m1;        // Maske zum setzen der IOs am PWM Start
100
        m1 <<= 1;
101
    }
102
    main_ptr_mask[0]=m2;                            // PWM Start Daten 
103
 
104
    // PWM settings sortieren; Einfügesortieren
105
 
106
    for(i=1; i<=PWM_CHANNELS; i++) {
107
        min=PWM_STEPS-1;
108
        k=i;
109
        for(j=i; j<=PWM_CHANNELS; j++) {
110
            if (pwm_setting_tmp[j]<min) {
111
                k=j;                                // Index und PWM-setting merken
112
                min = pwm_setting_tmp[j];
113
            }
114
        }
115
        if (k!=i) {
116
            // ermitteltes Minimum mit aktueller Sortiertstelle tauschen
117
            tmp_set = pwm_setting_tmp[k];
118
            pwm_setting_tmp[k] = pwm_setting_tmp[i];
119
            pwm_setting_tmp[i] = tmp_set;
120
            tmp_mask = main_ptr_mask[k];
121
            main_ptr_mask[k] = main_ptr_mask[i];
122
            main_ptr_mask[i] = tmp_mask;
123
        }
124
    }
125
 
126
    // Gleiche PWM-Werte vereinigen, ebenso den PWM-Wert 0 löschen falls vorhanden
127
 
128
    k=PWM_CHANNELS;             // PWM_CHANNELS Datensätze
129
    i=1;                        // Startindex
130
 
131
    while(k>i) {
132
        while ( ((pwm_setting_tmp[i]==pwm_setting_tmp[i+1]) || (pwm_setting_tmp[i]==0))  && (k>i) ) {
133
 
134
            // aufeinanderfolgende Werte sind gleich und können vereinigt werden
135
            // oder PWM Wert ist Null
136
            if (pwm_setting_tmp[i]!=0)
137
                main_ptr_mask[i+1] &= main_ptr_mask[i];        // Masken vereinigen
138
 
139
            // Datensatz entfernen,
140
            // Nachfolger alle eine Stufe hochschieben
141
            for(j=i; j<k; j++) {
142
                pwm_setting_tmp[j] = pwm_setting_tmp[j+1];
143
                main_ptr_mask[j] = main_ptr_mask[j+1];
144
            }
145
            k--;
146
        }
147
        i++;
148
    }
149
 
150
    // letzten Datensatz extra behandeln
151
    // Vergleich mit dem Nachfolger nicht möglich, nur löschen
152
    // gilt nur im Sonderfall, wenn alle Kanäle 0 sind
153
    if (pwm_setting_tmp[i]==0) k--;
154
 
155
    // Zeitdifferenzen berechnen
156
 
157
    if (k==0) { // Sonderfall, wenn alle Kanäle 0 sind
158
        main_ptr_time[0]=(uint16_t)T_PWM*PWM_STEPS/2;
159
        main_ptr_time[1]=(uint16_t)T_PWM*PWM_STEPS/2;
160
        k=1;
161
    }
162
    else {
163
        i=k;
164
        main_ptr_time[i]=(uint16_t)T_PWM*(PWM_STEPS-pwm_setting_tmp[i]);
165
        tmp_set=pwm_setting_tmp[i];
166
        i--;
167
        for (; i>0; i--) {
168
            main_ptr_time[i]=(uint16_t)T_PWM*(tmp_set-pwm_setting_tmp[i]);
169
            tmp_set=pwm_setting_tmp[i];
170
        }
171
        main_ptr_time[0]=(uint16_t)T_PWM*tmp_set;
172
    }
173
 
174
    // auf Sync warten
175
 
176
    pwm_sync=0;             // Sync wird im Interrupt gesetzt
177
    while(pwm_sync==0);
178
 
179
    // Zeiger tauschen
180
    cli();
181
    tausche_zeiger();
182
    pwm_cnt_max = k;
183
    sei();
184
}
185
 
186
// Timer 1 Output COMPARE A Interrupt
187
 
188
ISR(TIMER1_COMPA_vect) {
189
    static uint8_t pwm_cnt;        // ändern auf uint16_t für mehr als 8 Bit Auflösung
190
    uint16_t tmp;            // ändern uint16_t oder uint32_t für mehr Kanäle
191
 
192
    OCR1A += isr_ptr_time[pwm_cnt];
193
    tmp    = isr_ptr_mask[pwm_cnt];
194
 
195
    if (pwm_cnt == 0) {
196
    tmp &= PINFreigabe;
197
        PWM_PORT_1 = tmp;               // Ports setzen zu Begin der PWM
198
        PWM_PORT_2 = tmp >> 8;      // zusätzliche PWM-Ports hier setzen
199
    
200
        pwm_cnt++;
201
    }
202
    else {
203
    tmp &= PINFreigabe;
204
        PWM_PORT_1 &= tmp;              // Ports löschen
205
        PWM_PORT_2 &= tmp >> 8;      // zusätzliche PWM-Ports hier setzen
206
    
207
        if (pwm_cnt == pwm_cnt_max) {
208
            pwm_sync = 1;        // Update jetzt möglich
209
            pwm_cnt  = 0;
210
        }
211
        else pwm_cnt++;
212
    }
213
}
214
 
215
int main(void) {
216
  
217
  // Helligkeit für jeden PIN einstellen
218
  //                CN14 CN12 CN11 CN10 CN9  CN8  CN7  CN6  CN5  CN3  CN1
219
  uint8_t timing[PWM_CHANNELS]={243, 243, 244, 245, 246, 249, 249, 250, 253, 254, 255};
220
  uint8_t Anzahl = 9;
221
  uint8_t cnt;
222
  int i;
223
224
 
225
    // PWM Port einstellen
226
 
227
    PWM_DDR_1 = 0xFF;       // Port als Ausgang
228
    PWM_DDR_2 = 0x07;    // zusätzliche PWM-Ports hier setzen
229
  DDRB = 0x00;      // Port B als Input
230
  PORTB = 0x03;      // Pull Up auf PB0 und PB1 aktivieren
231
 
232
    // Timer 1 OCRA1, als variablen Timer nutzen
233
 
234
    TCCR1B = 2;             // Timer läuft mit Prescaler 8
235
    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten
236
 
237
    sei();                  // Interrupts global einschalten
238
  
239
  // Abfrage ob 9 oder 11 Pins benutzt werden sollen
240
  if ((PINB & (1<<PINB1)) == 0)
241
    Anzahl = 11;
242
 
243
  
244
    memcpy(pwm_setting, timing, PWM_CHANNELS);
245
    pwm_update();
246
  
247
  // Abfrage in welche Richtung gezählt werden soll  
248
  if ((PINB & (1<<PINB0)) == 0)
249
  {
250
    for (i=0; i<Anzahl; i++)
251
    {
252
      PINFreigabe |= (1 << i);
253
      
254
      for (cnt=0;cnt<DelayBetweenPINs;cnt++)
255
      {
256
        _delay_ms(1);
257
      }
258
    }    
259
  }
260
  else
261
  {
262
    for (i=Anzahl-1; i>=0; i--)
263
    {
264
      PINFreigabe |= (1 << i);
265
      
266
      for (cnt=0;cnt<DelayBetweenPINs;cnt++)
267
      {
268
        _delay_ms(1);
269
      }      
270
    }    
271
  }
272
  
273
while(1);
274
}

von Der Axel (Gast)


Angehängte Dateien:

Lesenswert?

Funktioniert einwandfrei!

/*
    Eine 8-kanalige PWM mit intelligentem Lösungsansatz

    ATmega32 @ 8 MHz

*/

im Anhang...

von Der Axel (Gast)


Lesenswert?


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.