+ Reply to Thread
Results 1 to 8 of 8

Thread: Nefunkcni pocitani vlozenych funkci

  1. #1

    Nefunkcni pocitani vlozenych funkci

    Zdravim, jde o naprogramovani AVR v cecku, mam nejaky potenciometr, z toho lezou ruzne hodnoty a ja se snazim jejich prubeh vylepsit, aby to moc neodskakovalo apod. K tomuto nereste detaily, mam jiny problem, ty filtry co mam v programu napsane mi nechteji pocitat.

    Takze ADC1 bere hodnoty z potenciometru a pak hodnoty posila do predem vlozenych funkci a vypocty by mely generovany na PWM signal funcki PWM1. Vsechno ostatni v pragramu je plne funkcni, kdyz tam zadavam hodnoty primo z ADC1 generovani pwm i jeho hardwarove osetreni je v cajku. Problem je kdyz tam dosadim hodnoty z adc upravene danymi funkcemi, vysledek je "stejny" jakoby tam hazeli rovnou to co z toho ADC aniz by probehl vypocet...nevim jestli to tam spatne volam nebo chybi neco v define nebo knihovna??? netusim.... pls help...zkouknete to, beztak to bude nejaka blbost, diky moc!!!!

    Code:
    #include <stdint.h>           // standard integer types
    
    #include <stdio.h>
    
    #include <stdlib.h>
    
    #include <avr/io.h>
    
    #include <avr/interrupt.h>
    
    #include <util/delay.h>
    
    #include <math.h>	//gaus
    
    #include "uart2.h"
    
    // ============================= DEFINE ===========================
    
    #define AVG_BUF_EXP 4
    #define AVG_BUF_LEN 16 // AVG_BUF_LEN = 2^AVG_BUF_EXP = 16 for AVG_BUF_EXP == 4 
    #define FIR_BUF_LEN 11
    
    int servo;
    
    // =========================== INIT PORTY =========================
    
    void init_port(void)
    {
    	DDRA  = 0B10000000;	
    	PORTA = 255;	
    	
    	DDRB  = 0B00001000;	
    	PORTB = 255;
    	
    	DDRD  = 0B00100011;	
    	PORTD = 255;	
    }
    
    // =========================== ADC READ ===========================
    
    int read_ADC1(void)
    {
    	ADMUX = 0b00000000;      //kanál 0
    	ADCSRA = 0b10000110;
    
    	ADCSRA |= (1<<ADSC); //Start conversion
    	while ((ADCSRA & (1 << ADSC)) == 64){};
    	return ADCW;
    }
    int read_ADC2(void)
    {
    	ADMUX = 0b00000001;      //kanál 1
    	ADCSRA = 0b10000110;
    
    	ADCSRA |= (1<<ADSC); //Start conversion
    	while ((ADCSRA & (1 << ADSC)) == 64){}; 
    	servo = 173+ADCW*43/256; //cteni z prevodniku a uprava hodnoty 1024 na rozsah 173-345 pro PWM2
    	return servo;
    }
    // ========================= INIT AVG ============================
    
    int avg(unsigned int newVal)
    {
       // funkce počítající klouzavý průměr z AVG_BUF_LEN-ti prvků
       // musí platit: max(newVal)*AVG_BUF_LEN < 65535 !!!
       // tedy např. pro 10bit vstup (max = 1023) smí být buffer dlouhý až 64 prvků (1023*64 < 65535)
       // Kdyby nestačil limit 65535, je nutné změnit "sum" na "long int" a modifikovat dle toho kód.
    
    	static unsigned int buff[AVG_BUF_LEN];
    	static unsigned int sum = 0;
    	static unsigned int *pLast = &(buff[0]); 
    	
    	sum -= *pLast;
    	sum += newVal;
    	*pLast = newVal;
    	pLast++;
    	if(pLast > &(buff[AVG_BUF_LEN-1])) pLast = &(buff[0]);   // end of buffer
    	return ((sum+( AVG_BUF_LEN / 2)) >> (AVG_BUF_EXP));  //( AVG_BUF_LEN / 2)) >> (AVG_BUF_EXP));   // divide by AVG_BUF_LEN
    }
    // ======================== INIT GAUSS ===========================
    
    unsigned char gauss(unsigned int newSample)
    {
       // 11th order FIR filter
       // y[n] = b0*x[n] + b1*x[n-1] + ...
       //                        b10 b9 b8  b7 ....                 b1 b0
       static unsigned char coef[] = {0, 1, 3, 8, 12, 16, 12, 8, 3, 1, 0};   // N(0,3)
                            // filter coefitients (gaussian), requires sum(coef) = 65535/255 = 257
                            // same length as "buff"
       static unsigned int buff[FIR_BUF_LEN];
       unsigned int sum = 0;
       unsigned char i;
    
       for(i=0; i<FIR_BUF_LEN-1; i++)   // posunout zpozdovaci linku
       {
          buff[i] = buff[i+1];
       }
       buff[FIR_BUF_LEN - 1] = newSample;   // vlozit novy vzorek
       
       for(i=0; i<FIR_BUF_LEN; i++)   // spocitat sumu
       {
          sum+= buff[i] * coef[i];
       }
    
       // divide by 256
       //return sum/4;
       return (unsigned char)(sum >> 8);
    }
    
    // ========================= INIT PWM =============================
    
    void init_PWM1(void)
    {
    	TCCR0 = 0b01101011;
    	
    	OCR0 = 0;
    	TCNT0 = 0;
    
    }
    
    void init_PWM2(void)
    {
          
    	TCCR1A = 0b10000010;          // 50 Hz -> 20ms / 3455 dílků
    	TCCR1B = 0b00011011;
                                        // -90°/0°/90° -> 173 - 259 - 345 (250 je stred)
    		                            //                
    	ICR1 = 3455;
    
    	TCNT1  = 0;
    	OCR1A = 0; 
    }
    // =========================== PWM ================================
    
    void PWM1(int pulse1)
    {
          
    	OCR0 = pulse1; 
    
    }
    
    
    void PWM2(int pulse2)
    {
          
    	OCR1A = pulse2; 
    
    }
    
    // ========================== PROG================================
    int main(void) 
    {
    
        uart_init();
        init_port();
        init_PWM1();
        init_PWM2();
    
    	
    	while(1){
    		
    		PWM1(read_ADC1()/4); 
    		//PWM1(avg(read_ADC1())/4);             
    		//PWM1(gauss(read_ADC1()));
    		PWM2(read_ADC2());                      
    		                      
    	}
    
    
    
    }
    Last edited by Werewolf; 11.06.2011 at 21:58.

  2. #2
    Na kód používaj tag code a napíš riadky, na ktorých sa vyskytuje chyba. Moc do toho programu nevidím a tomu popisu tiež moc nerozumiem. Napíš len mená funkcií a čo je ich vstupom, čo očakávaným výstupom a čo skutočným výstupom.
    Všetci chcú vaše dobro. Nedajte si ho vziať!!

  3. #3
    Ok, sorac, jsem tu prvne, chtel jsem to vlozit jako prilohu ale nechtel mi ten soubor zebrat...priste se polepsim.

    nevim jestli delas AVrka, jeslti nevis ze by mohla chybet knihovna nebo neco v definici? Ale myslim si ze to je ciste nejaka chybka v Cecku. Nastaveni portu neres, stejne jako cteni z ADC prevodniku, pak jsou dva filtry, prumer a gaussuv filtr. Ten prumer tam jenom prirazuje hodnoty z ADC1 do bufferu o delce 16 a dela z nich prumer, u toho gausse, jde o urcitou funkci ktera tam ani neni, je to zjednodusene tak ze tam jsou primo vlozene konstanty te funkce pro buffer o 11 prvcich a jde jenom o nasobeni pole bufferu (taky vkladane hodnoty z ADC1) s polem tech vlozenych konstant. To je vse, funkce by mely byt spravne napsany, tam by nemel byt problem, potvrdili mi ze to je spravne napsane. Potom ty pwmka taky neres, to je AVRko, to mam dobre, funguje. Pak az v hlavnim programu jeslti neni spatne to volani funkci. To PWM1 kde se odesilaji ty hodnoty je osmi bitove, proto tam mam u primem posilani z ADC1 deleni 4mi, z 0-1023 na 0-255. Stejne tak u toho prumeru (avg), a u toho gausse, je to uz predem vydelene v napsani te funkce. Takze v tom programu se vyznat moc nemusis, je tam vetsina jen nastaveni registru (AVR to je v cajku) a ty dve funkce, ktere jsou udajne opravdu dobre. Takze jde bud o zacatek progrmau, definice, nebo to volani funkce je spatne? Vzdycky pouziji jen jedno, bud prime PWM1(read_ADC1()/4), to funguje jak ma, odesila pwm signal ktery nasledne pomoci RC clanku je preveden na analogovou hodnotu 0-5V a pak jeste zesilen 2x na 0-10V (AVR a elektro vazne nemusis resit, mam to v poradku) Nebo odesilam s filtry: PWM1(avg(read_ADC1())/4) takze mel by v bufferu prumerovat postupne pridavane hodnoty (klasicky klouzavy prumerovy filtr) z ADC1 a potom je vydelit 4 pro 8bit PWM a odeslat je pryc. Stejne tak u Gausse. Ale ty funkce nepocitaji, to co z toho leze je "to same" jako bez tech filtru, stejny prubeh.

    Jestli mas MAtlab muzu ti poslat jak to ma fungovat, funkce jsou prepsany z toho matlabu a jak jsem zminil, mam je dobre, udajne funguji. PRoblem jestli v tom volani tech funkci? Definici, jestli ten buffer to nepobira, ale napsan je dobre....

    Jo jeste jak jsi psal kde mi to pise chybu, o to jde, zadna chyba tam neni, jako takova, zkompiluje se mi to a naprogramuje bez hlasenych chyb, jenom to nedela co ma, nepocita ty filtry, ostatni vsechno funguje. Diky moc!!!

  4. #4
    Ospravedlňovať sa nemusíš, stačí ak ten tvoj 1. príspevok upravíš a dáš ten kód do tagu code.

    Inak v tom tvojom texte sa človek ťažko vyzná a o to ide. Stále tam píšeš o tom čo netreba riešiť a funguje, a ja teda vlastne neviem v čom ti poradiť. Som len chcel aby si pár vetami, alebo možno v odrážkach napísal kde je chyba. Čo očakávaš a čo to robí. Presne. Napr.:
    • Zavolá sa funkcia XXX
    • Predám jej číslo (8 bit)
    • Má mi vrátiť 29
    • Ale vráti 36

    Už som programoval nejaký MCU a je to celkom podobné, ale takto ti neporadím. Jedine veci čo som si tak všimol je, že delíš tými štyrmi pričom si písal, že preto aby si dostal 8bit hodnotu. Prečo rovno z tej funkcie nevrátiš unsigned char? Ten je 8bitový a nemusíš nič deliť.

    To, že ti to skompiluje neznamená, že tam nie je chyba. Práve chyby, ktoré neodhalí prekladač sú skutočné chyby.
    Všetci chcú vaše dobro. Nedajte si ho vziať!!

  5. #5
    Ok dal som to do code. Tiez sa oci krizia ked to sledujem. Ja som nic take nerobil takze tazko ti poradim. Ak by sa to dalo tak sem postni aj #include "uart2.h". A kludne mi posli aj Matlab files. Dohodneme sa cez PM.
    Všetko o hrách a novinkách s herného sveta nájdete na http://the-guild.cz/.

  6. #6
    Takze, ja se snazim a myslim ze rikam celkem jasne co se tam deje a co chci aby to delalo. ADC1 pobira 0-5V a prevadi na 0-1023, nemuzu rict jaka tam jde hodnota z toho rozsahu a jakou presne chci aby lezla ven, je tam ruzny prubeh hodnot, ktery filtruju. Vse v programu je jen nastaveni mikroprocesoru a pwmek atd. Klicove jsou ty dve funkce, jsou jasne oddelene, a hlavni program, kde je vlastne pouze volani techto funkci a odesilani na PWM1. Kdyz volam bez avg a bez gauss, v poradku. KDyz volam avg a gauss, vysledek je stejny jako bez nich. Co se tyce tech dvou funkci je to prepsani z matlabu (byl jsem ujisten ze tak jak jsou samostatne napsane pry funguji), kod matlabu preposilam zde (nevim proc mi nechce pripojovat soubory na techto strankach...)

    Code:
    close all;
    clear;
    clc;
    
    N=50; % délka signálu
    t=1:1:N;
    x=zeros(1,N);    % několik vstupních hodnot pro filtraci
    x(5) = 10;
    x(7) = 15;      
    x(9:12) = 17;
    x(14) = 22;
    x(16) = 15;
    x(17) = 10;
    x(18) = 5;
    x(30) = 20
    yg=zeros(1,N);
    ya=zeros(1,N);
    
    %% Klouzavý průměr 8
    for i=8:N
        ya(i) = sum(x(i-7:i))/8;
    end
    
    %% Gaussův filtr
    
    L = 11;     % délka filtru
    % ----------------
    gx = -(L-1)/2 : (L-1)/2; % interval okolních hodnot signálu, které bude filtrovat
    mi = 0;     % střední hodnota
    sig2 = 3;    % rozptyl
    G = 1/(sqrt(2*pi*sig2)) * exp( -(gx-mi).^2 /(2*sig2) ); % normální rozdělení
    % ----------------
    % výpočet filtru
    for i=L:N
        yg(i) = sum( x(i-L+1:i) .* G );  % násobení signálových hodnot v intervalu s koeficienty Gaussova rozdeleni
    end
    
    %% Plots
    %plot(t, x, 'b', t, yg, 'r', t, ya, 'g');
    stem(t, x, 'b');
    hold on;
    stem(t, ya, 'g');
    stem(t, yg, 'r');
    hold off;
    xlabel('vzorek'); ylabel('amplituda'); title('odezva signálu');
    legend('x', 'y prumer 8', 'y gauss');
    Last edited by Hanisss; 14.06.2011 at 17:23.

  7. #7
    Takže, tam Matlabe vidím pre vypočítanie avg cyklus for. Dajme tomu, že v C ti namiesto toho slúži cyklus while(1); problém bude ale asi to, že funkcia sum v matlabe počíta vektor, čo by mal byť v C ďalší cyklus a ten nikde nevidím. Prípadne si nadefinuj funkciu sum aj v C. Priznám sa, že moc múdry z toho nie som, ale hádam trochu pomôže.
    Všetci chcú vaše dobro. Nedajte si ho vziať!!

  8. #8
    Funbkce jsou napsane spravne. Sum tam neni jako funkce ale jako promenna a zacina s hodnotou nula.

    Code:
    sum -= *pLast; //odecte posledni hodnotu z pointeru  
    sum += newVal; //pricte novou hodnotu
    do sum se neustale pricitajhi a odecitaji hodnoty z pointeru, takze si neustale drzi soucet v zavislosti na delce pointeru. a potom se to touto delkou deli...

    Kdyby nahodou byl v tomto problem, urcite by se to chovalo jinak nez gauss, jenze se oba chovaji stejne a bohuzel i stejne jako bez filtru takze nevim kde ma byt chyba...

    ty funkce uz automaticky jsou vlastne psany aby neustale pocitaly a neustale pridavaly hodnoty do pointery a mazaly ty posledni. ten while s tim samotnym pocitanim nema moc spolecneho, ten jen zprostredkuje neustale pocitani. je jedno jestli while(1) nebo for(; nebo jak se pisou ty nekonecne smycky....
    Last edited by Hanisss; 14.06.2011 at 18:40.

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts