Skocz do zawartości

ATtiny85 - generacja PWM z f > 20 KHz i krokiem 0,5 us


FlyingDutch

Pomocna odpowiedź

11 godzin temu, kaczakat napisał:

Witam

Zrobiłem coś podobnego na attiny13, ale skok 1us, może przez zegar 9600000, na attiny45 po ustawieniu na 16MHz w Arduino (ja akurat mam core Attiny Microcontrollers) po prostu chodzi OK z krokiem 500n, więc pewnie rejestry są takie same i już nie sprawdzałem. Wypełnienie ustala się potencjometrem na PB2, wyjście PWM na PB1. PWM ma ~20kHz, pewnie zależy od egz.


#define LED PB1
void adc_setup (void)
{
    // Set the ADC input to PB2/ADC1
    ADMUX |= (1 << MUX0);
    ADMUX |= (1 << ADLAR);

    // Set the prescaler to clock/128 & enable ADC
    // At 9.6 MHz this is 75 kHz.
    // See ATtiny13 datasheet, Table 14.4.
    ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}

int adc_read (void)
{
    // Start the conversion
    ADCSRA |= (1 << ADSC);

    // Wait for it to finish
    while (ADCSRA & (1 << ADSC));

    return ADCH/2;
}

void pwm_setup (void)
{
    // Set Timer 0 prescaler to clock/8.
    // At 9.6 MHz this is 1.2 MHz.
    // See ATtiny13 datasheet, Table 11.9.
    TCCR0B |= (1 << CS01);

    // Set to 'Fast PWM' mode TOP=0xFF
   // TCCR0A |= (1 << WGM01) | (1 << WGM00);

    // Set to 'Fast PWM' mode TOP= OCR0A
    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    // co ciekawe ten WGM02 jest w innym rejestrze
    TCCR0B|= (1 << WGM02);


    OCR0A = 99;

    // Clear OC0B output on compare match, upwards counting.
//    TCCR0A |= (1 << COM0B1);
    // Set OC0B output on compare match, down counting.
    TCCR0A |= (1 << COM0B1)|(1 << COM0B0);
}

void pwm_write (int val)
{
    OCR0B = val;
}

int main (void)
{


    // LED is an output.
    DDRB |= (1 << LED);

    adc_setup();
    pwm_setup();

    while (1) {
        // Get the ADC value
       uint8_t adc_in = adc_read();
        // Now write it to the PWM counter

        pwm_write(adc_in);
    }
}

Cześć,

dzięki za kod. W weekend wypróbuję.

Pozdrawiam

 

Link do komentarza
Share on other sites

Gość es2

Nie widzę nigdzie informacji o wymaganej rozdzielczości. Jeśli wystarczy 8-bit to nie trzeba PLL. Nawet przy 8MHz uzyska się 31.250Hz rozdzielczość  125ns.

Link do komentarza
Share on other sites

Dnia 7.12.2018 o 01:34, kaczakat napisał:

Witam

Zrobiłem coś podobnego na attiny13, ale skok 1us, może przez zegar 9600000, na attiny45 po ustawieniu na 16MHz w Arduino (ja akurat mam core Attiny Microcontrollers) po prostu chodzi OK z krokiem 500n, więc pewnie rejestry są takie same i już nie sprawdzałem. Wypełnienie ustala się potencjometrem na PB2, wyjście PWM na PB1. PWM ma ~20kHz, pewnie zależy od egz.

Cześć,

sprawdziłem dzisiaj ten kod na ATtiny85 (Atmel Studio 7 + AVR-ISP-MK2) i nie działa (nie generuje PWM na pinie PB1). Odczyty z ADC zastąpiłem po prostu wartością 128 i wyeliminowałem funkcje ADC  bo są tu zbędne. Wydaje mi się, że dla timera zero są inne piny nim sterowane niż PB1, ale mogę się mylić.

Pozdrawiam

Link do komentarza
Share on other sites

Gość es2
3 godziny temu, FlyingDutch napisał:

Wydaje mi się, że dla timera zero są inne piny nim sterowane niż PB1, ale mogę się mylić.

Sprawdź w nocie katalogowej.

Ponadto, Tiny13 i Tiny85 maja różne timery.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Jak wpisałeś 128 to  faktycznie nie będzie działać. Po to jest potencjometr i led by działanie PWM można było zobaczyć, a trudniej skopać, więc jak już to trzeba ustawić na połowę zakresu, tu akurat 49 (OCR0A wpisane jest na sztywno 99, regulujesz OCR0B 0-99, 100 kroków). 

Kod był dla Arduino, dla Eclipse trzeba dopisać linijkę #include <avr/io.h> , a dla AS jeszcze FCPU. Przy przeklejaniu dodaje trzy kropki/apostrofy (niedrukowalne w okienku tu na forum) w funkcji adc_setup i na końcu, nie wiem skąd, załączam plik z kodem.

Modyfikacje sobie rób jak już będziesz widział efekt. Nawet jakby faktycznie ustawienia i rejestry były inne to chyba idea działania jest ważna, a nie nazwy rejestrów, które po porównaniu PDF obu procków po prostu się podmienia.

PWMAttiny45_03.jpg

sketch_dec13aattinyPWM.zip

222.jpg

1111.jpg

AttinyPWM03.jpg

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Gość es2
4 godziny temu, kaczakat napisał:

a dla AS jeszcze FCPU.

FCPU należy ustawiać w projekcie a nie kodach źródłowych.

Edytowano przez es2
Link do komentarza
Share on other sites

(edytowany)
8 godzin temu, kaczakat napisał:

Jak wpisałeś 128 to  faktycznie nie będzie działać. Po to jest potencjometr i led by działanie PWM można było zobaczyć, a trudniej skopać, więc jak już to trzeba ustawić na połowę zakresu, tu akurat 49 (OCR0A wpisane jest na sztywno 99, regulujesz OCR0B 0-99, 100 kroków). 

Kod był dla Arduino, dla Eclipse trzeba dopisać linijkę #include <avr/io.h> , a dla AS jeszcze FCPU. Przy przeklejaniu dodaje trzy kropki/apostrofy (niedrukowalne w okienku tu na forum) w funkcji adc_setup i na końcu, nie wiem skąd, załączam plik z kodem.

Modyfikacje sobie rób jak już będziesz widział efekt. Nawet jakby faktycznie ustawienia i rejestry były inne to chyba idea działania jest ważna, a nie nazwy rejestrów, które po porównaniu PDF obu procków po prostu się podmienia.

Cześć,

bardzo Ci dziękuję - rzeczywiście kod działa prawidłowo (przestawiłem prescaler na brak podziału).

Wklejam kod dla Atmel Studio (cz. PWM = 22 KHz):

#include <avr/io.h>

#define F_CPU (16000000UL)
#define LED PB1


void pwm_setup (void)
{
	// Set Timer 0 prescaler to clock/8.
	// At 9.6 MHz this is 1.2 MHz.
	// See ATtiny13 datasheet, Table 11.9.
	TCCR0B |= (1 << CS00);

	// Set to 'Fast PWM' mode TOP=0xFF
	// TCCR0A |= (1 << WGM01) | (1 << WGM00);

	// Set to 'Fast PWM' mode TOP= OCR0A
	TCCR0A |= (1 << WGM01) | (1 << WGM00);
	// co ciekawe ten WGM02 jest w innym rejestrze
	TCCR0B|= (1 << WGM02);


	OCR0A = 90;

	// Clear OC0B output on compare match, upwards counting.
	//    TCCR0A |= (1 << COM0B1);
	// Set OC0B output on compare match, down counting.
	TCCR0A |= (1 << COM0B1)|(1 << COM0B0);
}

void pwm_write (int val)
{
	OCR0B = val;
}

int main(void)
{
    /* Replace with your application code */
    // LED is an output.
    DDRB |= (1 << LED);

    //adc_setup();
    pwm_setup();

    while (1) 
    {
        // Get the ADC value
        uint8_t adc_in = 34;
        // Now write it to the PWM counter

        pwm_write(adc_in);
    }
}

Pozdrawiam

Edytowano przez FlyingDutch
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.