Atmega16 generovani analogove hodnoty pwm signalem na vystup

Zdravim, potreboval bych pomoct, potrebuji na vystupu ADC7 (porty nastavene) priradit pwm signalem 0-5V. Nevim jak ten PWM nastavit aby bylo brano jako 0-5V ani ten prevod moc nechapu. Koukam do toho a hledam neco cele dopoledne a nejsem schopny nic najit:-( (zacatecnik, prosim o trpelivost se mnou:-) )

Na výstup mcu bez DA převodníku analogovou hodnotu nedostaneš. Jedině výstup z pwm (ale to není ještě analog) a ten je pak třeba vyfiltrovat RC článkem nebo aktivním filtrem (kdyby byl zatížen).
Máš nějaký zvláštní důvod proč pin ADC7? Tam totiž nejde použít hw pwm, musel bys to generovat programově.
HW výstupy použitelné pro pwm jsou OC0, OC1A a OC1B.

Ja vim ze ne, proto je treba generovat ten pwm. takze ani pwm to nebude uplne chpano jako 0-5V? To prave nechapu podle toho co mi radi…No za tim vystupem ADC7 mam RC paralelne a operacni zesilovac 2x aby z toho udelal 0-10V. Ja elektru zas tak moc nerouzmim a desku jsem nenavrhoval ja, ale melo by to byt v poradku. Tak to jsem z toho jelen, fakt uz si nevim rady…

Když nerozumíš elektru, tak proč řešíš takové úlohy.
Není to domácí práce ze školy?

Dej nám alespoň nástin toho zapojení za pinem ADC7 ať víme o čem je řeč. Jesli tam je jakejsi filtr, tak to snad půjde.

PWM generuje obdélníkové pulzy se střední hodnotou, jakou té PWM nastavíš. Onen filtr z té střední hodnoty obdélníkového signálu teprve udělá “nějakou” analogovou hodnotu.
Pokud máš už hotový filtr, tak tě to nemusí moc tlačit, ale bylo by vhodné znát mezní frekvenci onoho filtru (nebo alespoň zapojení a hodnoty součástek).
Pak by se hodilo vědět, jakou maximální frekvenci na výstupu požaduješ (tedy přibližně jak často musíš měnit hodnotu). Do té doby se nedá nic moc navrhovat.

Jasne, ja vim, uz pomalu vim jak na to, vsecko je tady:

Za ADC7 je RC clanek, R = 10K, C = 100 uF, pak ten operacni zesilovac 2x, nevim jestli jsem jiz zminoval. Mel jsem to zrejme delat CTC kdyz FastPWM ma OCR0 vystup jinde, jenze pak mi rekli at klidne pouziji FastPWM a kdyz nastavim preruseni v TIMSK a povolim globalni v programu, ze jde ten pin zmenit. Nastaveni registru v pohode, jenze s Ceckem taky trosku zoufam. Jak tam mam pak priradit jiny pin??:slight_smile:

Jaký použiješ režim je vpodstatě jedno, ale zrovna CTC se pro pwm nehodí. Ten Fast PWM je co potřebuješ.
Vyrob si přerušení od přetečení timeru - tam budeš nastavovat do “1” ten pin, který má sloužit jako výstup PWM.
Potom dopiš přerušení od compare match stejného timeru - zde se pin nuluje. To je vše.
10k + 100u => T = 1s. Rychlost přetýkání timeru by to chtělo alespoň 10ti násobnou, tedy >10Hz.

Když se nebude dařit, tak sem dej kus programu, co by měl generovat výstup a rozchodíme ho.

Jasne, takze preddelicka 1 a vychazi to o frekvenci 43200 (krystal 11.0592 Mhz). Bylo mi receno cim vetsi tim lepsi, na urcite hodnote nezalezi, ne?

Mno prerusit prerusim, ale ani samotne C neni zatim muj pritel a to nastaveni pinu jsem nepochopil:-(

Tak tady je to orezane jen na tuto funkci co mam…

void init_port(void) //nastaveni portu
{
DDRA = 0B10000000;
PORTA = 255;

DDRD = 0B00100011;
PORTD = 255;

int read_ADC1(void) //nastaveni ADC prevodniku
{
ADMUX = 0b00000000; //kanál 0
ADCSRA = 0b10000101;

  ADCSRA |= (1<<ADSC);   //Start prevodu
  while ((ADCSRA & (1 << ADSC)) == 1){};
  u = ADC ;
  return u;

void init_PWM1(void) //nastaveni PWM a preruseni
{
TCCR0 = 0b01001001;
TIMSK = 0b00000011;

  OCR0 = 0;
  TCNT0 = 0;

}

void PWM1(int pulse) //funkce PWM
{
OCR0 = pulse*256/1024; //prirazena digitalni hodnota
//bude prepocitana na interval 0-256
}

int main(void) //program

  init_port();
  init_PWM1();
  
  sei();                             //povoleno preruseni

  PWM1(read_ADC1());      //prectena hodnota z ADC a udelane PWM

  
  ISR(TIMER0_OVF_vect);      //preruseni pro preteceni

  ISR (TIMER0_COMP_vect);  //preruseni pro TNT0 = OCR0

//bohuzel je to vse co se mi podarilo zjistit, nevim jak priradit jiny port…a rikas ze po tom druhem preruseni se to vynuluje…no teoreticky by mohl porad zustat jako vystupni toho PWM ten ADC7 ne? Diky moc!!

nebo to preruseni melo byt uz v te inicializaci toho PWM…akorat nevim jak tam hodit ten jiny pin:-(

Trochu jsem tvůj kód upravil… Nezkoušel jsem to, ale snad pofrčí.
main.c (1.29 KB)

Diky moc!!! Jj, vidim, jeste si to doorezal ciste jen na zmenu pinu. Jj, akorat ja to budu posilat na PA7 z PA1 bude brat ty hodnoty pro generovani pwm:-) takze tam jen zmenim PA7:-) Ale jedna vec jeste. Rikal si ze aspon 10kH na to pwm a nastavil si s preddelickou 64, takze to necham jak jsem mel na preddelicku 1 ne? (jen tak pro jistotu):slight_smile:

Diky mockrat!!

Ano, to jsem zapoměl okomentovat. Kdyby jel timer bez děličky, tak by byla programová pwm velice nepřesná. Trvá totiž určitou dobu, než se vyvolá a obslouží přerušení. Kdybys tedy generoval malou hodnotu, třeba “3”, musel by být pin v “1” pouhé 3 takty procesoru a za tu dobu se přerušení nestačí ani vyvolat, natož obsloužit. Použitím děličky 64 dáš procesoru čas minimálně 64 taktů na obsluhu, to už vpohodě zmákne.

Mimochodem - nepsal jsem 10kHz, ale >10Hz :wink:

ajo:-) Dik:D

Mam jeste jeden dotaz. Resim pomalejsi odezvu v PC. A zajima me jak nejlepe nastavit ten RC clanek pro prevod PWM. NEjdriv jsem chtel jen vymenit elektrolyt za tantal, ale pak mi rekli ze to asi nejak extra poznat nepujde… ze muzu se zvysovanim kmitoctu PWM snizovat casovou konstantu RC clanku. Rikal si ze pro casovou konstantu 1s musi byt kmitocet aspon 10x vetsi. Mno a kdyz mam teda 675Hz tak jak zhryba mam snizit hodnoty na R/C clanku?:slight_smile: Nebo kde na to prijdu? Nechci desekrat prepajet a zjistovat jake je zvlneni signalu, ale vypadato ze tam je prostor pro zlepseni odezvy. Tak o kolik asi muzu snizit aby signal zustal s jistotou v pohode. Nepotrebuju to tlacit na max. Diky:-)

To záleží právě na dovolenym zvlnění.

Ja vim a nejde to nejak si odvodit? zvlvneni neni moc podstatne, jen do takove miry aby to spravne udavalo ten analogovy signal. Kdyz bys potreboval zrychlit odezvu a nemas oscilator?:slight_smile:

Ak nie je zvlnenie podstatne, nedavaj tam RC a vsetko bude fungovat. Akurat zvlnenie bude 100% :slight_smile:

To co potrebujes, je napriklad tu:

butkaj.com/fyzika2?id_menu=5 … d_left=499

No mozes sa v tom stratit, tak Ti skratene popisem princip.

Priebeh napatia na C pri nabijani je dany vztahom

u© =U*e(-t/RC);

Najvacsie zvlnenie je, ak sa snazis ma na vystupe U/2. Ak je U 5V, tak U/2 je 2.5V.

Tebe sa bude C cez RC clen (je samozrejmostou, ze z C snimas napatie pomocou OZ v neinvertujucom zapojeni kvoli vysokemu vstupnemu odporu. To tu nikto extra neuvadza, lebo je to taka samozrejmost akoze zajtra bude novy den) Nabijat najdlhsie po dobu 1/2 casu periody toho casovaca. To znamena, ze ak je frekv.vst casovaca napr. 1MHz a casovac je 8 bitovy,
potom je kriticky cas ((2^ 8 )/2)*1us = 128us.

Aby zvlnenie nepresiahlo 1LSB z 8bit prevodu (8bit preto, lebo pouzijeme citac od 0 do 255), potom:

e(-t/RC) < (1-1/(2^ 8 ))

t = 128us;
C zvolis 10uF
R sa rovna cca 3k3

alebo C = 1uF a R = 33k

C daj obycajnu keramiku, obycajne elyty maju dost vysoky seriovy odpor. To ale na obyc. multimetry prakticky nerozpoznas, takze tam skratka daj co mas po ruke. :slight_smile: Nema zmysel davat vacsie hodnoty R a C, lebo inak si velmi spomalujes reakciu na zelane zmeny vystupneho napatia. Az sa Ti moze stat, ze na vystupe budes chciet mat 0V a tie tam budu o 10 sekund. To si myslim nie je zamer DA vystupu s PWM.

Ako vznikla hodnota 1MHz.

Pre dany citac nastavujes nejaku vstupnu frekvenciu. Ta js dana hodinami MCU (RC, alebo Xtal, alebo externy generator) delena vstupnym preddelicom citaca. Ja som zobral za priklad, ze na vstupe to citaca (za preddelicom ) je 1MHz. Ty si tam dosat to, co tam mas nastavene. T.j. kombinacia frekvencie MCU a preddelica. Ak je na vstupe citaca 1MHz, citac meni svoj stav za 1us. Ak tam budes mat 11MHz (Xtal 11MHz a preddelic je 1), tak citac zmeni svoj stav 11x rychlejsie ako 1us. Z toho si to jednoducho odvodis. Nema zmysel ist do neviem akych frekvencii, tam sice staci dat RC clen s mensimi hodontami a teda rychlejsie reagujuci, mozu sa vsak zacat prejavovat rozne nelinearity a casove ofsety dane nabijanim a vybijanim parazitnych kapacit. Osobne by som vstupnu frekvenciu do citaca volil medzi od 0,1 do maximalne 0,5MHz.

Do citaca Ti VZDY ide frekvencia MCU delena delicom. Aj jednotka je deliaci pomer. :slight_smile:

Citac mas do 256 s tym, ze OCxx sa nastavuje (SET alebo RES, podla toho ako si navolis prislusne bity. Vhodne je aby bol vystup v log.1 pokial je stav citaca mensi ako hodnota v OCR), ak hodnota citaca dosiahne stav prislusneho OCR registra.

Ako som pisal, najvacie zvlnenie je ak sa C 1/2 casu nabija a potom sa druhu 1/2 casu nabija. Kedze chces simulovat DA, potom toto zvlnenie nesmie byt vacsie ako +/-0.5LSB, ja som v priklade uviedol zvlnenie +/-1LSB co je na jednoduche aplikacie este pripustne.
Mensie zvlnenie je zase zbytocne.

Takze kodik sa bude nabijat pocas 128 x cas vstupnej periody, u teba bude 1/(11059000/64)

tVST_F = 1/(11059000/64) ;

Ja som tVST_F dal rovne 1us (napriklad 8MHz RC interny oscilator s delickou 8 ), ty si tam daj co Tebe vyjde.

takze cas nabijania bude:
tNAB = 128 * tVST_F

no a tVYB bude taky isty, lebo som v polke intervalu a 2^8 je 256, takze polovica z toho je 128

tVYB = 128 * tVST_F

No a ty vies, ze napatie na kondiku sa sprava podla vstahu s exponentom. Kedze exponent zavisi od casu, Zvol si hodnotu C a R si vypocitaj podla Tvojho casu (u mna to bolo 128 * 1us = 128us, Pre tvoj preddelic si tam daj hodontu aka ti vyjde).Ako hodnoru R potom daj najblizsiu vyssiu z radu E12.

Skratka za tento cas nesmie napatie na kondiku vzrast/poklesnut o spomynany LSB, co je pri 8 bitovom prevodniku 1/(2^8 ) = 1/256

Cauec, jasne pochopil jsem to, jedine cim jsem si nebyl jisty je ta jednicka od ktere odecitas 1/256 tady: e(-t/RC) < (1-1/(2^ 8 ))

Jeslti to ma byt proste jednicka nebo tam dosazujes tu svoji 1us?

vypocetl jsem to ale nevim…kdyz tam dam danou konfiguraci tak vystup je misto 0-10V o dost mensi…neni duvod spatneho nastaveni ze to tak usekne? KDyz tam dam nejaky mnohem mensi tak ten rozsah je jak ma byt, akorat signal je s vice chybama…zajima me ale to useknuti…myslel jsem zeto je tim velkym odporem kdyz tam bylo 10k a 100uF kondik, ale kdyz dam 33uF kondik a 6k2 odpor podle toho jak si mi to napsal tak je to useknuti taky tak nejak…