Změna výstupní frekvence PWM beze změny vzorkovací frekvence

ahoj,
tak ještě to není úplně ono.
po stisku tlačítka (inf=1) se přepne na PWM B,ale po puštění a vrácení na nulu se už na PWM A nepřepne. zřejmně zůstává bitově nastavená na 1 nebo ta smyčka jede nějak divně. :question:

EDIT:
tak už to jede, chyba byla mezi PC a klávesnicí na mej straně :smiley:

Funkční to je, je to super, ale ještě by to chtělo trochu zrychlit reakci na to přerušení. Já potřebuju aby to reagovalo na cca 22 us dlouhý impulsy ( který bude detekovat ta dioda) s periodou cca 600 us. je to vůbec tedy reálné aby to ten program dokázal takhle rychle obsloužit?

Vpohodě, jen je už nutné přejít k přerušení, teď to jen kontroluje pin. Chceš to na PB0, PD2 nebo PD3?
Má se to přepnout okamžitě, nebo to má nejdřív dokončit pwm pulz?
K čemu je to dobrý přepínat takhle pomalej signál na 22us na jinej pin? To tam rovnou můžeš poslat jen “1” nebo zkopírovat PWM A a pak ji shodit. Přijde mi zbytečný mít kvůli tomu nastartovanou druhou pwm. Mimochodem - při tak krátkých časech by už nebylo od věci zvednout frekvenci aspoň na těch interních 8MHz :wink:.

no, pokud by to bylo možný, tak to klidně nech na PB0 (ted je tam tušim ta fotodioda. f CPU klidně možno zvýšit, nechám si od tebe poradit, neni problém ani s ext. oscilátorem…
no a ten signál by bylo dobrý kdyby se to přepínalo zrovna v místě, kde se to nachází.

Nevím, asi bych nechal ty piny D volný, kdyby se třeba někdy k tomu chtělo eště něco připojit, třeba displej nebo nějaký další sračičky …

Zůstává to tedy na PB0 (ICP1), přerušení input capture.
main.c (3.39 KB)

zítra to zkusim,
jen se možná blbě,ale přece zeptam.
nikde jsem tu neviděl definovanou f CPU na 8 MHz. ptam se proto, že mam nastaveno v AVR studiu 1MHz, jestli to na sebe má nějaký vliv??
bo jak to je ted nakonfigurovaný a příp. jestli amm udělat nějaký změny třeba i v nastavení AVR sudia

Definice frekvence v nastavení projektu je jen informace pro překladač (např. pro funkce z knihovny delay.h"), na skutečnou frekvenci procesoru nemá žádnej vliv. Zdroj hodin a u interního rc tedy i frekvence se nastavuje pomocí fuses. Tovární nastavení je právě 1MHz. Nastavení pro 8MHz najdeš v datasheetu. Dej si bacha, co je je “0” a co “1”.
Bude potřeba taky upravit nastavení timeru v programu aby jel přes děličku, jinak by se ti zrychlil i generovanej signál.

:open_mouth: :astonished: noo… to bude oříšek to nastavit… :smiley:

Ahoj,
po delší pauze se opět pracuje na zařízení. Opět bych chtěl poprosit, zda by bylo možné mi trochu ( možná trochu víc pomoci s programovým vybavením). Analogová část zdá se být konečně dokončena, akorát je třeba celou koncepci upravit a s tím i program.

Co bych potřeboval.

Na Připojeném obrázku jsem se pokusil naznačit o co půjde.
Od zařízení se očekává to, že ATMEGA8L bude generovat 2 kanálově shodnou PWM křivku. tato křivka by měla být po seriovém kanálu dopravena do ADC převodníku, odtud ji již bude zpracovávat analogový obvod. Potřebuji, aby bylo možné pomocí 4 tlačítek ( snižovací a zvyšovací) vybírat hodnoty koeficientů z 2 tabulek.

První bude měnit nastavení časovače PWM dle asi 4 přednastavených koeficientů tak aby se měnila výstupní frekvence obou PWM. Vždy vzhledem k základní PWM.

Druhá tabulka bude obsahovat např rovněž 4 “hodnoty” ( řádky). Každý tento řádek ale bude obsahovat 2 koeficienty ( na obr X11- X14 a X21- X24, které budou příslušet PWM1 a PWM2).

Výběrem řádku by se měla měnit amplituda každé PWM zvlášť. tzn, že např. bude základní amplituda 2V, ale v řádku 2 bude koeficient X11= 0,8 a X21= 1,2. pak PWM1 bude =1,6V a PWM2= 2,4V. Každá další změna by se měla vztahovat k základnímu nastavení PWM, ne k poslední navolené hodnotě.

celá tato sranda slouží k paralelnímu chodu 2 dalších zařízení, které pracují se syntézou těchto 2 signálů.

U té frekvence je to jednodušší… alespon doufam.

Současné nastavení programu je, že se generuje jedna PWM, mám k dispozici 2 tlačítka s dvěmi koeficienty ( konstantami) pro změnu frekvence. Jinak asi nic.

Program přikládám zde.

#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr\pgmspace.h>

#define TLACITKA_PORT PORTB
#define TLACITKA_PIN PINB
#define TL1 PB6
#define TL2 PB7
#define INF PB0

#define TLACITKO_1 (!(TLACITKA_PIN & (1<<TL1)))
#define TLACITKO_2 (!(TLACITKA_PIN & (1<<TL2)))
#define INFRA (TLACITKA_PIN & (1<<INF))

volatile unsigned char repeate = 100, j = 1, i = 0;

const uint8_t plethysmcurve] PROGMEM= //256 hodnot
{
0x0,0x3,0x6,0x9,0xC,0xF,0x12,0x15,0x18,0x1B,0x1E,0x21,0x24,0x27,0x2A,0x2D,
0x30,0x33,0x36,0x39,0x3C,0x3F,0x42,0x45,0x48,0x4B,0x4E,0x51,0x54,0x57,0x5A,0x5D,
0x60,0x63,0x66,0x69,0x6C,0x6F,0x72,0x75,0x78,0x7B,0x7E,0x81,0x84,0x87,0x8A,0x8D,
0x90,0x93,0x96,0x99,0x9C,0x9F,0xA2,0xA5,0xA8,0xAB,0xAE,0xB1,0xB4,0xB7,0xBA,0xBD,
0xC0,0xC3,0xC6,0xC9,0xCC,0xCF,0xD2,0xD5,0xD8,0xDB,0xDE,0xE1,0xE4,0xE7,0xE9,0xEB,
0xEC,0xEF,0xF0,0xF1,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFC,0xFD,0xFE,
0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFD,0xFD,0xFC,0xFA,0xF9,0xF8,0xF7,0xF6,0xF5,0xF5,
0xF3,0xF2,0xF1,0xF1,0xF0,0xEE,0xEC,0xEB,0xEA,0xE9,0xE8,0xE6,0xE4,0xE2,0xE0,0xDE,
0xDC,0xDA,0xD8,0xD6,0xD4,0xD2,0xD0,0xCE,0xCC,0xCA,0xC8,0xC6,0xC4,0xC2,0xC0,0xBE,
0xBC,0xBA,0xB8,0xB7,0xB5,0xB4,0xB4,0xB5,0xB6,0xB7,0xB8,0xBA,0xBB,0xBD,0xBE,0xC0,
0xC1,0xC3,0xC4,0xC5,0xC6,0xC8,0xC9,0xCB,0xCC,0xCD,0xCE,0xCE,0xCE,0xCD,0xCD,0xCC,
0xCB,0xCA,0xC8,0xC6,0xC6,0xC4,0xC3,0xC1,0xBF,0xBD,0xBC,0xBA,0xB8,0xB6,0xB4,0xB2,
0xB0,0xAE,0xAC,0xAA,0xA8,0xA6,0xA4,0xA2,0xA0,0x9E,0x9C,0x9A,0x98,0x96,0x93,0x90,
0x8D,0x8A,0x87,0x84,0x81,0x7E,0x7B,0x78,0x75,0x72,0x6F,0x6C,0x69,0x66,0x63,0x60,
0x5D,0x5A,0x57,0x54,0x51,0x4E,0x4B,0x48,0x45,0x42,0x3F,0x3C,0x39,0x36,0x33,0x30,
0x2D,0x2A,0x27,0x24,0x21,0x1E,0x1B,0x18,0x15,0x12,0xF,0xC,0x9,0x6,0x3,0x0,
};

ISR(TIMER1_COMPA_vect)
{
if(!INFRA)
{
// infra = 0, pwm A jede
if(–j == 0)
{
OCR1A=pgm_read_byte(&plethysmcurve*);
j = repeate;
}
}
else
{
// infra = 1, pwm A zastavit, pokracuje B
TCCR1A &= ~(1<<COM1A1); // zastavit pwm A (vystup = 0)
TIMSK &= ~(1<<OCIE1A); // vypnout preruseni pwm A
if(–j == 0)
{
OCR1B=pgm_read_byte(&plethysmcurve*);
j = repeate;
}
else
{
OCR1B=pgm_read_byte(&plethysmcurve*);
}
TCCR1A |= (1<<COM1B1); // spustit pwm B
TIFR |= 1<<OCF1B; // vynulovat priznak preruseni pwm B
TIMSK &= ~(1<<OCIE1B); // zapnout preruseni pwm B
}
}

ISR(TIMER1_COMPB_vect)
{
//
if(INFRA)
{
// infra = 1, pwm B jede
if(–j == 0)
{
OCR1B=pgm_read_byte(&plethysmcurve*);
j = repeate;
}
}
else
{
// infra = 0, pwm B zastavit, pokracuje A
TCCR1A &= ~(1<<COM1B1); // zastavit pwm B (vystup = 0)
TIMSK &= ~(1<<OCIE1B); // vypnout preruseni pwm B
if(–j == 0)
{
OCR1A=pgm_read_byte(&plethysmcurve*);
j = repeate;
}
else
{
OCR1A=pgm_read_byte(&plethysmcurve*);
}
TCCR1A |= (1<<COM1A1); // spustit pwm A
TIFR |= 1<<OCF1A; // vynulovat priznak preruseni pwm A
TIMSK &= ~(1<<OCIE1A); // zapnout preruseni pwm A
}
}

void main(void)
{
TLACITKA_PORT |= 1<<TL1 | 1<<TL2; // zapnout pull-upy u tlacitek
DDRB |= 1<<PB2 | 1<<PB1; // pwm piny jako vystupy

            DDRD=0x00;                      // PortD jako vstup 
            PORTD=0xFF;                    // zapnout pull-upy

            OCR1A=80;                        // inicializace OCR1A hodnoty 
                                            
            TCCR1A |= 1<<COM1A1 | 1<<WGM10;                // PWM, Phase Correct, 8-bit,
            // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when downcounting.
            TCCR1B |= 1<<CS10;      // spustí časovač bez předděličky (start timer without prescaler ) 
            TIMSK |= 1<<OCIE1A;   // Timer/Counter1, Output Compare A atch Interrupt Enable
            sei();                                     // enable global interrups 

            for(;;) 
            {
                           //nekonečná smycka,preruseni pracuje 
                           if(TLACITKO_1) repeate = 100;
                           if(TLACITKO_2) repeate = 50;
            } 

}
img547.imageshack.us/i/fotoc5097.jpg/

:arrow_right: administrator: příspěvek byl upraven*****

:arrow_right: administrator: přiloženy externí soubory*

Mám takový zvláštní pocit, že si pleteš pojmy s dojmy.

Výstup PWM není serializované číslo (jako na uartu nebo spi) ani křivka, ale obdélník (0 - +Vcc) se střídou (a tedy i střední hodnotou) rovnou hodnotě v pwm registru. Teprve pokud budeš pwm měnit podle nějaké křivky, tak střední hodnota pwm bude té křivce odpovídat, stále to ale bude obdélník. Nemá tedy žádný smysl posílat sériově do ADC. Jednak je pwm výstup 1 pin (nehrozí tedy, že bys to posílal paralelně, nanejvýš vícekanálově) a za druhé to není analogová spojitá hodnota do té doby, než z něho dostaneš střední hodnotu (filtrem, rc článkem, převodníkem střída/napětí). Navíc jaký by mělo význam (i třeba již získanou střední hodnotu) posílat do AD převodníku, když má navazovat analogové zpracování?

nemalo to byt DA prevodnik ?

Aha, no, tak se nebudu ohánět termínama a zeptam se spíš, jak to lz udělat…
abych mohl řídit signál vystupující z ATMEGy způsobem, jakej sem popsa.
Potřebuju měnit frekvenci obou PWM současně podle předdefinovaných koeficientů jak jsme popsal… příp. i realizace pomocí více tlačítek. A potřebuji řídit amplitudu obou PWM dle předem nastavených koeficientů. Jak jsem popsal, klidně i pomocí tlačítek, kdy každému tlačítku by byla přednastavena konkrétní dvojice parametrů, ktreré by danou PWM upravili v daném poměru.

momentálně to funguje na 1PWM, kdy je výstup přes RC člen vyhlazen a dále zpracováván rozdvojeně. analogově je každý kanál ( pouze amplituda) upraven k vyhovujícímu poměru. Proto jsem myslel, že by bylo dobrý maximum nacpat do toho mikroprocesoru aby se omezilo to šílenství okolo.

Proto se ptám, je moje myšlenka s pomocí externího DAC převodníku realizovatelná? tím mám na mysli pomocí nějaké funkce dané PWM při stisku tlačítka říct… odečti od každé hodnoty v tabulce PWM1 hodnotu 4 a pro PWM2 přičti ke každé hodnotě +3 např. to vše vyslat seriovou komunikací, třeba tím USART na konkrétní DAC převodník a za ním teprv signál z každého kanálu vyhladit RC členem a dále zpracovávat??? nebo by to zvládl mikroprocesor toto zpracovat interně bez externího DAC převodníku??

Viděl jsem DDS generátory, které byly v postatě takto podobně realizovné .
je tedy možné tyto mé přestavy naplnit ve skutečnost? Omlouvám se, pokud by někoho uráželo, že se ptám na takové šílenosti, ale jsem v těhle věcech trochu víc mimo a bohužel nejsem schopen časově tyto otázky řešit sám samoukou :frowning:

Díky ATLANovi za opravu, máš pravdu, má to být DAC…

Díky :frowning: :confused:

DDS generuje čísla a ta pak posílá do DA převodníku.
DA převodník samozřejmě použít můžeš, né však ve spojení s pwm. PWM s RC článkem je totiž již samo o sobě DA převodník (na výstupu máš přeci spojitou hodnotu že). Do DA převodníku musíš poslat číslo, aby ho převedl, jenže výstupem pwm (bez RC) jaksi žádné číslo není (digitální sériové ani paralelní). Takže tedy buď pwm s RC nebo DA. Pokud ti však současný výstup za RC článkem po kvalitativní stránce (zvlnění, vyšší frekvenční složky) vyhovuje, je zbytečné přidávat další obvod.

Měnit amplitudu signálu generovaného pwm také samozřejmě lze. Né však přičtením/odečtením konstanty ke všem hodnotám - to by způsobilo ss posun. Hodnotu je třeba vynásobit právě nějakým koeficientem. Jelikož jsme na celočíselném mcu, bylo by to vhodné provést celočíselným postupem. Jak vynásobit celé číslo zlomkovým koeficientem tu také několikrát proběhlo (např. v tématech o vlhkostních senzorech).

Tedy ano, myšlenka je realizovatelná a je jedno, jesli jako DA použiješ externí obvod nebo pwm s rc článkem. Problém zůstává nezměněn - ony úpravy signálu je třeba dělat v MCU (alespoň frekvenci). Úpravy amplitudy si můžeš vybrat dle libosti - externě operákem (pro neprogramátora mnohem jednodušší než se snažit změnit sw) nebo programově. Přepínat amplitudy na 2 kanálech pomocí OZ vyžaduje zhruba 6 odporů, 1 dvojítý OZ a 2 spínače.

Tak jsem si trochu upravil představu o tom, jakými způsoby by se dala celá věc řešit.
1, nejelegantnější záležitostí by bylo už popsaný (ale blbě :slight_smile: ) posílání hodnot po seriovém kanálu do DAC převodníku, kdy by se tak muselo posílat asi dvoukanálově ( pro každou křivku), kdy by se navolením tlačítka zvolili konkrétní koeficienty, které by základní křivku ( hodnoty v tabulce) vynásobily, čímž by se upravila ta amplituda každé zvlášť a byla odeslána o seriovém kanálu do DAC a dále zprac. analogově.

2, druhá varianta by mohla být, že bych neměl tabulku s hodnotami křivky 1,ale měl bych pro každou křivku čtyři tabulky hodnot, kdy bych si pomocí tlačítka vybral konkrétní dvojici tabulek, z které by se pak pomocí PWM generoval signál. Je to takový kostrbatý řešení,ale pro moje účely by to asi stačilo i když to neni tak hezký jako to první.

3, třetí varianta je generování jedné PWM, která by se vyhladila RC článkem, za který by se dala dolní propust a klasický OZ v neinvertujícím zapojení, kdy by ve zpětné vazbě byl digitální potenciometr, kterým bych ovlivňoval zesílení OZ a tím vlastně měnil amplitudu křivky v daném kanálu. ten dig. potenciometr by měl být nastavitelný nějakou hodnotou vyslanou po stisku tlačítka z mikroprocesoru. samozřejmně, že celá věc by se se musela udělat pro 2 kanály. řešení to je taky, i když takové…

Najdu někoho, kdo by mi poradil, kterou cestou se vydat vzhledem k složitosti programování atd, příp. někoho, kdo by pomohl? jsem z toho volaký zmetený :confused: :cry: