Forum: Mikrocontroller und Digitale Elektronik Schaltung korrekt für LED Fader mit ATMega32?!


von Steffen P. (steffen_p)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin zur Zeit dabei 3 Güterwagen meiner Modellbahn umzubauen. Die 
originale Platine der Herstellers leucht einfach nur wenn der Wagen auf 
den Gleisen steht und das ist mir einfach zu fade. Deswegen dachte ich 
mir, einen Fadereffekt einzusetzen. Das ganze habe ich bereits mit einem 
LM324D und einem TL494BD gemacht mit mäßigem Erfolg. Das Poti für die 
Helligkeit beeinflusst die Geschwindigkeit der PWM und dazu leuchten die 
Platinen unterschieldich schnell und hell.
Zudem würde ich gerne ein paar Bauteile einsparen. Mit Mikrocontroller 
habe ich keinerlei Erfahrung aber ich habe hier ein Tutorial dafür 
gefunden

https://www.mikrocontroller.net/forum/mikrocontroller-elektronik

Die Schaltung sieht vorläufig mal so aus. Ich muss nur noch rausfinden 
wo ich den Sockel für die ISP Programmierung anschließe. Funktioniert 
die Schaltung so wie ich es mir gedacht habe bzw. auch verstanden? Kann 
ich das Programm aus dem Tutorial einfach so übernehmen?

Zum programmieren habe ich ein Arduino Uno Board.

von Horst (Gast)


Lesenswert?

D1 ist überflüssig, an jeden Vcc gehört ein 100nF gegen GND
Der IPS-Connector gehort an die Pins 1-4+Vcc+GND
R1 ist etwas klein, 10k sind üblich
Ob Du die LEDs so ansteuern kannst, kommt auf die Typen und elektrischen 
Daten an.

Die Aufgabe könnte auch ein Tiny45 machen, mit einem Viertel des 
Platzen.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Das alte Mega32 Schlachtschiff ist genau das, welches für deine Zwecke 
am wenigsten geeignet ist, es ist gross und hat zuwenig PWM Ausgänge. 
Spar dir den für andere Basteleien. Ein z.B. Mega48/88/168/328 hat schon 
mal 6 fertige PWM Kanäle.
Der Tiny461/861 hat 6 Kanäle (davon 2 nur als Software) und ein recht 
kleines Gehäuse, was dem Einbau zugute kommt.

von Steffen P. (steffen_p)


Angehängte Dateien:

Lesenswert?

So, ich habe mich jetzt für den ATMega88-20AU entschieden. Das Layout 
ist hoffentlich auch soweit richtig.
Das Programm habe ich noch soweit angepasst und hoffe das es so 
passt...!?

//********************************************************************** 
****
//*
//*  LED fading test
//*  uses exponential PWM settings to achive visual linear brightness
//*
//*  ATmega88 @ 8 MHz
//*
//********************************************************************** 
****

#include <avr/io.h>
#include <avr/pgmspace.h>

#define F_CPU 8000000L
#include <util/delay.h>

#define STK500 0

#if STK500
// inverted PWM on OC1A for STK500
#define INVERT_PWM (1 << COM1A0)
#else
// non-inverted PWM on OC1A
#define INVERT_PWM 0
#endif // STK500

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
};

/*

  Diese Tabellen sind nicht nach der Theorie (s. oben) berechnet, 
sondern wie folgt:
  a = Anzahl an Schritte (4, 8, 16, 32, 64, 256)
  b = Auflösung des PWM's (256, 1024, 65536)
  y = Errechneter Wert an einer stelle x
      y = 0 wenn x = 0
      y = pow(2, log2(b-1) * (x+1) / a) wenn x > 0

  Gerne wird auch diese alternative Formel genutzt:
      y = pow(2, log2(b) * (x+1) / a) - 1

  Obige Funktionen wurden in den LibreOffice Calc Sheet eingearbeitet.
*/

// long, variable delays

void my_delay (uint16_t milliseconds)
{
    for (; milliseconds > 0; milliseconds--)
        _delay_ms (1);
}

void pwm_up_down (const uint16_t pwm_table[], int16_t size, uint16_t 
delay)
{
    int16_t tmp;

    for (tmp = 0; tmp < size; tmp++)
    {
        OCR1A = pgm_read_word (& pwm_table[tmp]);
        my_delay (delay);
    }

    for (tmp = size-1; tmp >= 0; tmp--)
    {
        OCR1A = pgm_read_word (& pwm_table[tmp]);
        my_delay (delay);
    }
}

// 16-Bit PWM with 256 different settings

void pwm_16_256 (uint16_t delay)
{
    // 16 Bit Fast PWM
    TCCR1A = 0x82 | INVERT_PWM;
    // stop timer
    TCCR1B = 0;
    // TOP for PWM, full 16 Bit
    ICR1 = 0xFFFF;
    // prescaler 1 -> ~122 Hz PWM frequency
    TCCR1B = (1 << WGM12) | (1 << WGM13) | 1;

    pwm_up_down (pwmtable_16, 256, delay);
}

int main (void)
{
    int8_t i;
    // delay in milliseconds for one fading step
    int16_t step_time = 400;

    // LED uses OC1A
    DDRD &= ~(1 << PD0);
    DDRD &= ~(1 << PD1);
    DDRD &= ~(1 << PD2);
    DDRD &= ~(1 << PD3);
    DDRD &= ~(1 << PD4);

    // test all fading routines

    while (1)
    {

        for (i=0; i<3; i++) pwm_16_256 (step_time/16);
        my_delay (1000);
    }

    return 0;
}

von holger (Gast)


Lesenswert?

>Das Programm habe ich noch soweit angepasst und hoffe das es so
>passt...!?

Was soll das Fragezeichen? Probier es aus.
Zwei LEDs in Reihe wird bei Rot und Grün evtl. funktionieren,
bei Blau und Weiss sicher nicht.

Und ist das eigentlich so schwer sich das Bils was man posten
möcht mal selber anzuschauen? Da ist kaum was zu erkennen.

von Steffen P. (steffen_p)


Angehängte Dateien:

Lesenswert?

Stimmt, schon wieder vergessen. Ich möchte 2 grüne LEDs verwenden.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Steffen P. schrieb:
> // LED uses OC1A
>     DDRD &= ~(1 << PD0);
>     DDRD &= ~(1 << PD1);
>     DDRD &= ~(1 << PD2);
>     DDRD &= ~(1 << PD3);
>     DDRD &= ~(1 << PD4);

Da stimmt was nicht. Ohne die restliche Logik zu verfolgen, sieht man 
schon, das hier kein einziger Ausgang deklariert wird. Wenn du OC1A als 
PWM Ausgang nurzen möchtest, solltest du zumindest ein
1
PORTB |= (1 << PB1);
 während der Initialisierung ausführen. PB1 ist der PWM Ausgang OC1A, 
siehe Datenblatt.
Die Schaltung passt auch in keiner Weise zum Programm.

: Bearbeitet durch User
von Draco (Gast)


Lesenswert?

Aaaalso:
1
    DDRD &= ~(1 << PD0);
2
    DDRD &= ~(1 << PD1);
3
    DDRD &= ~(1 << PD2);
4
    DDRD &= ~(1 << PD3);
5
    DDRD &= ~(1 << PD4);
6
7
//Wird zu:
8
9
    DDRB &= ~((1<< PD0) | (1<< PD1) | (1<< PD2) | (1<< PD3) | (1<< PD4));

Und das:
1
TCCR1B = (1 << WGM12) | (1 << WGM13) | 1;
2
3
// Macht das, was fällt dir auf:
4
5
TCCR1B = (1<< WGM12);
6
TCCR1B = (1<< WGM13);
7
TCCR1B = 1;

So beim überfliegen aufgefallen.

von Steffen P. (steffen_p)


Lesenswert?

Matthias S. schrieb:
>> // LED uses OC1A
>>     DDRD &= ~(1 << PD0);
>>     DDRD &= ~(1 << PD1);
>>     DDRD &= ~(1 << PD2);
>>     DDRD &= ~(1 << PD3);
>>     DDRD &= ~(1 << PD4);
>
> Da stimmt was nicht. Ohne die restliche Logik zu verfolgen, sieht man
> schon, das hier kein einziger Ausgang deklariert wird. Wenn du OC1A als
> PWM Ausgang nurzen möchstest, solltest du zumindest ein
PORTB |= (1 <<  PB1);
>  während der Initialisierung ausführen. PB1 ist der PWM Ausgang OC1A,
> siehe Datenblatt.

Ich muss zugeben das ich nur die Teile raus gelöscht habe die ich nicht 
verwenden möchte. Verwenden wollte ich PD0 - PD4. Muss ich, da ich 5 
Pins verwenden diesen Schritt
void pwm_up_down (const uint16_t pwm_table[], int16_t size, uint16_t
delay)
{
    int16_t tmp;

    for (tmp = 0; tmp < size; tmp++)
    {
        OCR1A = pgm_read_word (& pwm_table[tmp]);
        my_delay (delay);
    }

    for (tmp = size-1; tmp >= 0; tmp--)
    {
        OCR1A = pgm_read_word (& pwm_table[tmp]);
        my_delay (delay);
    }
}
für jeden Pin eingeben?
Woran erkenne ich eigentlich welcher Pin PWM unterstützt?

> Die Schaltung passt auch in keiner Weise zum Programm.
Ok, ich dachte, es reicht wenn ich meine LEDs an die Pins lege die ich 
auch vorhabe zu verwenden.

von Steffen P. (steffen_p)


Lesenswert?

Draco schrieb:
> Und das:
>
> TCCR1B = (1 << WGM12) | (1 << WGM13) | 1;
>
> // Macht das, was fällt dir auf:
>
> TCCR1B = (1<< WGM12);
> TCCR1B = (1<< WGM13);
> TCCR1B = 1;

Ich würde sagen das es auf das gleiche heraus kommt, nur mit dem 
Unterschied das es vereinfacht geschrieben ist.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Steffen P. schrieb:
> Woran erkenne ich eigentlich welcher Pin PWM unterstützt?

Aus dem f*ing Manual. Im Datenblatt unter Pin Configuration siehst du 
z.B. OC1A und OC1B. Diese Ausgänge können mit den OC Registern A und B 
des Timers1 PWM moduliert werden. Das entsprechende für OC0A und OC0B, 
sowie OC2A und OC2B - summa summarum 6 Hardware PWM Kanäle mit 3 Timern.

Steffen P. schrieb:
>> TCCR1B = (1<< WGM12);
>> TCCR1B = (1<< WGM13);
>> TCCR1B = 1;
>
> Ich würde sagen das es auf das gleiche heraus kommt, nur mit dem
> Unterschied das es vereinfacht geschrieben ist.

Da solltest du nochmal drüber nachdenken, was so ein Gleichheitszeichen 
bedeutet.

: 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.