Forum: Mikrocontroller und Digitale Elektronik Pause/Unterbrechung beim PWM fading einfügen


von Jens S. (kunbsi)


Lesenswert?

Hallo,
folgendes Script funktioniert bereits prima.
1
int
2
main(void)
3
{
4
        uint16_t delay = DELAY_MIN;
5
        uint8_t dir = 0;
6
7
        /* setup */
8
        DDRB = 0b00000001; // set LED pin as OUTPUT
9
        PORTB = 0b00000001; // set LED pin to HIGH
10
11
        /* loop */
12
        while (1) {
13
14
        PORTB &= ~(_BV(LED_PIN)); // LED off
15
                _delay_loop_2(delay);
16
17
                PORTB |= _BV(LED_PIN); // LED on
18
                _delay_loop_2(DELAY_MAX - delay);
19
20
                if (dir) { // fade-in
21
                        if (++delay >= (DELAY_MAX - 1)) dir = 0;
22
      
23
                } else { // fade-out
24
            if (--delay <= DELAY_MIN) dir = 1;
25
                }
26
        }
27
}

Es handelt sich dabei um eine LED, die an und aus gefadet wird.
Nun möchte ich aber, das die LED für X Sekunden aus bleibt und dann 
wieder heller wird.
Kann mir jemand sagen wie und wo ich das einbauen muss?

Vielen Dank

von aSma>> (Gast)


Lesenswert?

Servus,
was du machen willst, nennt sich pollen, wenn dieses Programm fkt., dann 
könntest du diese Aufgabe mit einer ISR erledigen.
1
        /* loop */
2
        while (1) {
3
/*
4
        PORTB &= ~(_BV(LED_PIN)); // LED off
5
                _delay_loop_2(delay);
6
7
                PORTB |= _BV(LED_PIN); // LED on
8
                _delay_loop_2(DELAY_MAX - delay);
9
*/
10
       
11
            if (dir) { // fade-in           
12
                for(; delay >= DELAY_MAX; delay++){
13
                   pwm+=1; //hier die richtigen Register setzen!
14
                _delay_loop_2(100); //100ms delay
15
                }
16
                dir=0; //led tauscht den Zustand
17
18
            } else { // fade-out
19
                for(; delay == 0; delay--){
20
                   pwm+=1; //hier die richtigen Register setzen!
21
                _delay_loop_2(100); //100ms delay          
22
                }
23
                dir=1; //led tauscht den Zustand
24
            }
25
        }//end loop

Du müssest nur noch die Ausgänge der LED richtig initialisieren!

mfg

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Jens S. schrieb:
> Kann mir jemand sagen wie und wo ich das einbauen muss?
1
                } else { // fade-out
2
            if (--delay <= DELAY_MIN) dir = 1; <== HIER
3
                }
 etwa so:
1
                } else { // fade-out
2
                    if (--delay <= DELAY_MIN) {
3
                        PORTB &= ~(_BV(LED_PIN)); // LED off
4
                       _delay_loop_2(2000); //2000ms delay - Wenn's geht
5
                       dir = 1;
6
                    }
7
                }

von M. K. (sylaina)


Lesenswert?

Welcher Atmega/Attiny wird denn benutzt und warum nicht die Hardware-PWM 
benutzen? Das wäre etwas günstiger.

von Jens S. (kunbsi)


Lesenswert?

Vielen Dank für die Antworten .
Der Controller ist ein Attiny13.

Wie könnte ich denn zum Vergleich die Hardware pwm verwenden?

von M. K. (sylaina)


Lesenswert?

Schau dir mal das Datenblatt dazu an. Mit Timer0 kann z.B. eine 8 bit 
Hardware-PWM realisiert werden.

von M. K. (sylaina)


Lesenswert?

Ich hab mal auf die Schnelle was zusammengestrickt, dürfte so gehen als 
Beispiel:
1
/* Name: main.c
2
 * Author: <insert your name here>
3
 * Copyright: <insert your copyright message here>
4
 * License: <insert your license reference here>
5
 */
6
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include <avr/sleep.h>
10
11
//globals
12
volatile uint16_t myInt = 0;
13
volatile uint8_t upDown = 0;
14
15
//functions
16
void setUpAvr(void);
17
18
int main(void)
19
{
20
    setUpAvr();
21
    
22
    for(;;){
23
        /* insert your main loop code here */
24
    set_sleep_mode(SLEEP_MODE_IDLE);
25
    sleep_mode();
26
    }
27
    return 0;   /* never reached */
28
}
29
30
void setUpAvr(void){
31
    /* insert your hardware initialization here */
32
  
33
    //PWM Pin als Ausgang definieren
34
    DDRB |= (1 << PB0);
35
    //setUp Timer0
36
    TIMSK0 |= (1 << TOIE0);
37
    TCCR0A |= (1 << COM0A1)|(1 << WGM01)|(1 << WGM00);
38
    TCCR0B |= (1 << CS00);
39
    OCR0A = 0;
40
    //enable interrupts
41
    sei();
42
}
43
ISR(TIMER0_OVF_vect){
44
  myInt++;
45
  if (myInt >=15) {
46
    if (OCR0A < 255 &&
47
      upDown == 0) {
48
      OCR0A++;
49
    }else if (OCR0A != 0) {
50
      OCR0A--;
51
      upDown = 1;
52
    } else {
53
      upDown = 0;
54
    }
55
56
    myInt = 0;
57
  }
58
}
Das dürfte die PWM an OCR0A immer von 0 auf 255 hochlaufen lassen und 
anschließend runter laufen lassen. Läuft der ATtiny13 mit 1 MHz dann 
dürfte der Zustand myInt = 15 ca. alle 4 ms auftreten. Das PWM-Register 
wird damit also alle 4 ms um eins erhöht/erniedrigt. Um also die PWM 
somit von 0% auf 100% zu bekommen braucht es damit eine Zeit von ca. 1 
Sekunde.

Das soll nur als Beispiel dienen, hab ich eben so ohne Kontrolle aus dem 
Bauch heraus runtergekritzelt.

EDIT:

Der Sleep-Kram ist meinem 08/15-Standard geschuldet und nicht wirklich 
erforderlich aber auch nicht ganz unvorteilhaft ;)

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.