Pomoc s kodem v C pro ATtiny13A

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

Pomoc s kodem v C pro ATtiny13A

#1 Příspěvek od JirkaZ »

Zdravím,

byl by někdo z přítomných schopen a zejména ochoten mi pomoct s kódem v C pro ATtiny13A?

O co jde: potřebuji udělat úplně jednoduchý modul zajišťující pomalý analogový track and hold (podrobněji na schématu v příloze).

Jako skvělou inspiraci jsem našel https://adnbr.co.uk/articles/adc-and-pwm-basics . Je tam asi skoro všechno*, nicméně jako programátorský laik nejsem schopen ty ukázky "učesat a slepit" do jednoho zdrojového souboru, který bych předhodil překladači (nejspíš avr-gcc).

Jako alternativu (pro mě asi lepší) zvažuji Arduino IDE, kde jsem si už doinstaloval podporu pro ATtiny13, ale zůstávám "zaseknutý" na oné neschopnosti kód z příkladů "učesat a slepit".

(*) V ukázkových příkladech chybí mnou požadovaná klíčová funkce /HOLD a není tam ani použitý watchdog

Výstupem pro mě by tedy měl být jeden textový soubor (co nejvíce podobný těm příkladům a s ponechanými komentáři), který bych si už dále sám upravoval a současně se na tom učil.

Pokud by to nebylo triviální, můžeme se dohodnout na vhodné odměně.

Díky

--
Jirka
Přílohy
track_and_hold.png

Uživatelský avatar
ZdenekHQ
Administrátor
Administrátor
Příspěvky: 25593
Registrován: 21 črc 2006, 02:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#2 Příspěvek od ZdenekHQ »

Mám dojem, že jdeš s kanónem na vrabce.

Ten obvod se správně jmenuje "sample and hold". Pokud je sepnuto, napětí na výstupu odpovídá napětí na vstupu. Pokud je rozepnuto, drží hodnotu. Procesor netřeba. Technicky to lze zapojit tak, že se na "hold" přepíná až při změně řídícího signálu, jinak ten kondík vůbec není v cestě signálu.

Nakonec případná analogová filtrace bývá taky daleko efektivnější.

Převod na PWM na výstupu je taky daleko jednodušší, nejsi limitovaný taktem procesoru.
Naposledy upravil(a) ZdenekHQ dne 28 kvě 2021, 14:54, celkem upraveno 1 x.
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]

Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

#3 Příspěvek od JirkaZ »

ZdenekHQ píše:Mám dojem, že jdeš s kanónem na vrabce.

Ten obvod se správně jmenuje "sample and hold". Pokud je sepnuto, napětí na výstupu odpovídá napětí na vstupu. Pokud je rozepnuto, drží hodnotu. Procesor netřeba.

Nakonec případná analogová filtrace bývá taky daleko efektivnější.

Převod na PWM na výstupu je taky daleko jednodušší.
Bohužel nikoliv.

Analogový sample and hold je sice teoreticky možný, ale reálně není s rozumnou součástkovou základnou schopen udržet hold hodnotu déle než řekněme jednotky, max. desítky minut. Já to potřebuju teoreticky "na furt", lépe řečeno do doby vypnutí obvodu.

Jsem založením analogový hw elektronik s praxí mnoho desítek let a nepochybuj o tom, že kdyby to bylo možné, už dávno jsem tu dvojici OZ, spínač, kondenzátor a pár odporů použil...

Uživatelský avatar
ZdenekHQ
Administrátor
Administrátor
Příspěvky: 25593
Registrován: 21 črc 2006, 02:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#4 Příspěvek od ZdenekHQ »

Ta informace "na furt" je někde v zadání?
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]

Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

#5 Příspěvek od JirkaZ »

ZdenekHQ píše:Ta informace "na furt" je někde v zadání?
Ne, v zadání není, je nepřímo obsažena už v principu řešení a pro něj není podstatná.

Opravdu nepotřebuju nic jiného, než na co jsem se ptal. Čili ani nespecifikuju momentálně nepodstatné věci, vše důležité je ve schématu.

Uživatelský avatar
ZdenekHQ
Administrátor
Administrátor
Příspěvky: 25593
Registrován: 21 črc 2006, 02:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#6 Příspěvek od ZdenekHQ »

Děláš klasickou chybu, že navrhneš pouze vlastní řešení a nenapíšeš PROČ. Pak se nediv podobným reakcím. Tak hodně štěstí.
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#7 Příspěvek od lesana87 »

Tak jsem ti to slepila dohromady, ale nemám to teď na čem vyzkoušet. :D

Kód: Vybrat vše


// 9.6 MHz, built in resonator
#define F_CPU 9600000
#define PWM_OUT 1 //PWM output on PB1
#define HOLD 4 // HOLD signal on PB4

#include <avr/io.h>

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

void pwm_setup(void)
{
    // Set Timer 0 prescaler to clock/8.
    // At 9.6 MHz this is 1.2 MHz.
    TCCR0B |= (1 << CS01) | (1 << CS00);
    // Set to 'Fast PWM' mode
    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    // Clear OC0B output on compare match, upwards counting.
    TCCR0A |= (1 << COM0B1);
}

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

// ... adc_setup, adc_read, pwm_setup, pwm_write ...

int main (void)
{
    int adc_in;

    // LED is an output.
    DDRB |= (1 << PWM_OUT);
    DDRB &= ~(1<<HOLD); // Makes HOLD pin of PORTB as Input

    adc_setup();
    pwm_setup();
    while (1) {
        // Get the ADC value
        adc_in = adc_read();
        if (PINB & (1<<HOLD)) {
             // Now write it to the PWM counter
            pwm_write(adc_in);
        }
    }
}

Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

#8 Příspěvek od JirkaZ »

lesana87 píše:Tak jsem ti to slepila dohromady, ale nemám to teď na čem vyzkoušet. :D
Díky moc, ATtiny13 budu mít k dispozici až příští týden, dám vědět.

Mimochodem jsem si nevšiml, že na původním odkazu https://adnbr.co.uk/articles/adc-and-pwm-basics je až dole další odkaz na https://gist.github.com/adnbr/9289235 a tam je ten mnou požadovaný "učesaný a slepený" kód z příkladů vcelku... Samozřejmě tam není funkce /HOLD.

Watchdog v Tebou slepeném kódu zatím zřejmě není, šel by dopsat?

Uživatelský avatar
Mahoney
Příspěvky: 347
Registrován: 26 říj 2019, 02:00

#9 Příspěvek od Mahoney »

Šel.

Uživatelský avatar
bdn
Příspěvky: 436
Registrován: 16 led 2020, 01:00

#10 Příspěvek od bdn »

Přidání watchdogu pro kód výše.
první číslo znamená, číslo řádku, kam nakopírovat...

Kód: Vybrat vše

/* 7 */ #include <avr/wdt.h>
/* 57 */ wdt_enable(WDTO_500MS);
/* 59 */  wdt_reset();
Mimochodem kód výše je 8bit. ADC hodnota a 8bit. PWM. Modernější např. attiny1614 má 16bit. timer, takže PWM zde může být 16bit. rozlišení...

Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

#11 Příspěvek od JirkaZ »

bdn píše:Přidání watchdogu pro kód výše.
první číslo znamená, číslo řádku, kam nakopírovat...

Kód: Vybrat vše

/* 7 */ #include <avr/wdt.h>
/* 57 */ wdt_enable(WDTO_500MS);
/* 59 */  wdt_reset();
Díky moc, zkusím v týdnu, až budu fyzicky mít tu ATtiny13A. Napíšu sem výsledek.
bdn píše: Mimochodem kód výše je 8bit. ADC hodnota a 8bit. PWM. Modernější např. attiny1614 má 16bit. timer, takže PWM zde může být 16bit. rozlišení...
Ano, já vím, že ATtiny13 má osmibitový PWM a že v tom kódu se využívá jen horních 8 bitů z 10bit ADC (autor to popisuje na zdrojové stránce).

Jenže: existuje ATtiny (popř. prostě nějaký Atmel) v osmivývodovém pouzdře a s 10bit ADC i PWM? Při zběžném hledání jsem neuspěl, našel jsem pouze PICy a tam bych potřeboval, aby mi někdo vhodný program napsal úplně komplet... Osmivývodové pouzdro potřebuju kvůli místu na DPS.

Uživatelský avatar
Mahoney
Příspěvky: 347
Registrován: 26 říj 2019, 02:00

#12 Příspěvek od Mahoney »

Ten kód bude víceméně stejný, jen pojistky, inicializace a jména registrů se budou lišit. Vhodné MCU jsou PIC12F683, PIC12F1501, PIC12F1822 (či 12F1840). Víc teď nemůžu pomoci, snad se toho někdo chytne.

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#13 Příspěvek od FHonza »

JirkaZ píše: Jenže: existuje ATtiny (popř. prostě nějaký Atmel) v osmivývodovém pouzdře a s 10bit ADC i PWM?
ATtiny212, ATtiny412

Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

#14 Příspěvek od JirkaZ »

FHonza píše:
JirkaZ píše: Jenže: existuje ATtiny (popř. prostě nějaký Atmel) v osmivývodovém pouzdře a s 10bit ADC i PWM?
ATtiny212, ATtiny412
Aha, díky... ATtiny212 je dokonce o fous levnější než ATtiny13 a sem tam se dá i sehnat. No, uvidíme...

Uživatelský avatar
JirkaZ
Moderátor
Moderátor
Příspěvky: 1429
Registrován: 26 úno 2021, 01:00

#15 Příspěvek od JirkaZ »

Tak po dalších neumělých úpravách z mé strany vzniklo něco jako funkční kód, osobně úspěšně ověřený s ATtiny13A.

Maximalizoval jsem frekvenci PWM (původní kód poskytoval cca 550 Hz, nyní cca 35,71 kHz), dvojnásobně zrychlil A/D převodník, použil pro něj vnitřní referenci 1,1 V . Jo a 8 bitů PWM stačí (lépe řečeno musí stačit)...

Pro mě je zajímavé, že tento kód lze vložit do Arduino IDE (samozřejmě při nastavení správné "desky", zde MCU na ATtiny13), kompilace normálně proběhne bez chyb a stejně tak se exportuje i výsledný *.hex. Čili není třeba se zabývat s avr-gcc v konzoli a s hledáním správných parametrů překladu.

Pak už jen vhodný programátor a je hotovo ;-)

Tímto děkuji všem zúčastněným...

Kód: Vybrat vše

// Track and hold (sample and hold) circuit with ATtiny13A
// voltage input on pin 7 (PB2/ADC1), PWM output on pin 6 (PB1),
// control input (H=track, L=hold) on pin 3 (PB4)
// fclk 9.6 MHz, built in resonator
// original source: https://adnbr.co.uk/articles/adc-and-pwm-basics
// original source: https://gist.github.com/adnbr/9289235
// modification: http://www.ebastlirna.cz/modules.php?name=Forums&file=viewtopic&p=1175950

#define F_CPU 9600000
#define PWM_OUT 1 //PWM output on PB1
#define HOLD 4 // HOLD signal on PB4

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

void adc_setup (void)
{
    // Set the ADC input to PB2/ADC1
    ADMUX |= (1 << MUX0);
    ADMUX |= (1 << ADLAR);
    ADMUX |= (1 << REFS0); // set ADC ref. to internal ref. 1.1V

    // Set the prescaler to clock/128 & enable ADC (fclk for ADC cca 75 kHz)
    //ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
    // Set the prescaler to clock/64 & enable ADC (fclk for ADC cca 150 kHz)
    ADCSRA |= (1 << ADPS1) | (0 << ADPS0) | (1 << ADEN);
}

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

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

    return ADCH;
}

void pwm_setup(void)
{
    // Set Timer 0 prescaler to fclk/n
    //TCCR0B |= (1 << CS01) | (1 << CS00);//n=64, fpwm cca 550 Hz
    //TCCR0B |= (1 << CS01) | (0 << CS00);//n=8, fpwm cca 4.464 kHz
    TCCR0B |= (0 << CS01) | (1 << CS00);//n=1=no prescaling, fpwm cca 35.71 kHz
    // Set to 'Fast PWM' mode
    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    // Clear OC0B output on compare match, upwards counting.
    TCCR0A |= (1 << COM0B1);
}

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

// ... adc_setup, adc_read, pwm_setup, pwm_write, watchdog ...

int main (void)
{
    int adc_in;

    // LED is an output.
    DDRB |= (1 << PWM_OUT);
    DDRB &= ~(1<<HOLD); // Makes HOLD pin of PORTB as Input

    adc_setup();
    pwm_setup();
    wdt_enable(WDTO_500MS);
    while (1) {
        // Get the ADC value
        wdt_reset();
        adc_in = adc_read();
        if (PINB & (1<<HOLD)) {
             // Now write it to the PWM counter
            pwm_write(adc_in);
        }
    }
}

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“