Kodu Kontrol Edebilir Misiniz?

Başlatan E-x8, 28 Mayıs 2017, 12:23:46

E-x8

Merhaba

Sonunda işini iyi yapan bir çinliye denk geldim ve sapa sağlam efsane bir pickit3 satın aldım. Alete IPE veya mplapx IDE' si üzerinden veya ccs c üzerinden sonunda bir şeyleri sorunsuzca gönderebiliyorum. Bir kaç kodu denemeye de başladım. PWM ile alakalı bir yer danışacağım. Basitçe örneğim pot üzerinden okunan analogu PWM ile lede gönderiyor. Çalışıyor mu diye sorarsanız evet çalışıyor ama max PWM' e ulaşamıyorum.

float bilgi = 0;
int16 bilgint = 0;
int16 analogRead(int8 ch);
void main()
{
   set_tris_b(0x00);
   set_tris_c(0x00);
   setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16,200,4);
   set_pwm1_duty(0);
   while(TRUE)
   {
      bilgi = analogRead(1);
      bilgi = bilgi * 200 / 1023;
      bilgint = (int16)bilgi;
      set_pwm1_duty(bilgint); 
   }
}


PIC16F877A, 20Mhz

Kullandığım timer2' nin setup kısmını işleme soktuğumuzda PWM'in Hertz'i 388,68Hz olarak çıkıyor.(Sanırım, birde siz bakın)
Başta da belirttiğim gibi 0-5V arası PWM'i süremiyorum sanırım 0-3V arası çalışıyor en üst noktaya ulaşamıyorum. Yardımcı olabilir misiniz?

aliveli

programın tamamı yok
adc kaç bit belli değil
set_pwm1_duty() içine 16 bit veri gönderirsen hesap değişir
şu anki pwm frekansı 1554 Hz

10 bitlik okuma istiyorsan kod

#include <16F877.h> 
#device adc=10 
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP 
#use delay(clock=4000000) 
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS) 
//================================ 
void main() 
{ 
int16 value; 
setup_ccp1(CCP_PWM); 
// Set the PWM frequency for 245 Hz (with a 4 MHz crystal) 
setup_timer_2(T2_DIV_BY_16, 254, 1); 
setup_port_a(AN0); 
setup_adc(ADC_CLOCK_DIV_8); // Divisor for 4 MHz crystal 
set_adc_channel(0); 
delay_us(20); 


while(1) 
  { 
   value = read_adc();  // 10-bit ADC result 
   set_pwm1_duty(value); 
  } 
}

E-x8

ADC main.h dosyası içinde zaten 10bit olarak tanımlı.
Sizin kullandığınız "value" değişken int16  benim metottan gönderdiğimde int16 :
int16 analogRead(int8 ch); //Kolaylık olsun diye Arduino'da alışkın olduğum gibi tanımladım

Bu arada bir yanlışlık var 20Mhz kristalde yazdığınız PWM frekansı 1554Hz değil, 1225,49Hz'tir.
Ayrıca halen çözüme ulaşmış değilim :)

Mesajımda gönderme gereği duymadığım kodları paylaşayım :
//Main.h Dosyası 
#include <16F874A.h>
#device ADC=10
#use delay(crystal=20000000)


#include <main.h>
float bilgi = 0;
int16 bilgint = 0;
int16 analogRead(int8 ch);
void main()
{
   set_tris_b(0x00);
   set_tris_c(0x00);
   output_b(0x00);
   setup_adc(adc_clock_div_32);
   setup_adc_ports(ALL_ANALOG);
   enable_interrupts(INT_AD); 
   enable_interrupts(GLOBAL); 
   setup_timer_2(T2_DIV_BY_1,170,1); //Frekansı değiştirdim şu haliyle 1827,49Hz
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(0);                             //Başlangıçta sıfıra sabitledim
   while(TRUE)
   {
      bilgi = analogRead(1);      //Oluşturduğum fonksiyondan analog bilgisini alıyorum.
      bilgi = bilgi * 170 / 1023; //Aşmaması için 170'e kadar oranlıyorum.
      bilgint = (int16)bilgi;        //Float'ın virgüllerinden kurtulmak için int16'ya dönüştürüyorum
      set_pwm1_duty(bilgint); //Artık bu hesaplanan değeri gönderiyorum
   }
}
int16 analogRead(int8 ch)
{
   set_adc_channel(ch); //İstenilen kanal ch değişkeni ile gönderiliyor
   delay_us(20);             //Bekliyoruz
   return read_adc();      //Okunan değeri temiz bir şekilde geri döndürüyoruz
}





sadogan

#3
Adc 10 bit , Pwm de 10 bit.
Pwm den 5 volt alabilmek için 1023 değerini yazmanız gerekiyor.
Adc den okudugunuz değeri 200 ile çarpıp 1023 bölünce, pwm e
yükleyebileceğiniz en büyük değer 200 olur.
aliveli nin verdigi koddaki gibi direk adc değerini pwm e yüklemeniz gerekiyor.


E-x8

@sadogan PWM görev çevrimi süresi PWM periyodu süresinden daha fazla olmaması gerekmiyor mu? Yani 200 aşmamam gerekmez mi? Ben bu bilgiye dayanarak 10biti sınırladım.

mehmet

XC8 ile olsa olmaz mı?
RA0(AN0) adc giriş,
RC2(CCP1) pwm çıkışı...


// PIC16F877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = EXTRC     // Oscillator Selection bits (RC oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = ON         // Data EEPROM Memory Code Protection bit (Data EEPROM code-protected)
#pragma config WRT = HALF       // Flash Program Memory Write Enable bits (0000h to 0FFFh write-protected; 1000h to 1FFFh may be written to by EECON control)
#pragma config CP = ON          // Flash Program Memory Code Protection bit (All program memory code-protected)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include <stdint.h>

#define _XTAL_FREQ  20000000
#define MAX_DUTY    500 - 1

/*
 */
void PWM(unsigned int duty)
{
    CCPR1L = duty >> 2; // Set MSB values
    CCP1CON = ((duty & 3) << 4) | 0x0C; // set initial duty and set PWM mode bits.
}

/*
 */
void mcuInit(void)
{
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;

    ADCON1bits.PCFG = 0b1110;

    TRISA = 0xFF;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
}

/*
 */
void pwmInit(void)
{
    /*
     * http://eng-serve.com/pic/pic_pwm.html
     * 
     * PWM Register Values
     * Oscillator Frequency Fosc = 20000000
     * Clock Frequency Fclk = 5000000
     * PWM Freq = 10000 desired...actual: 10000
     * Prescaler Value = 4
     * PR2 = 124
     * Maximum duty value = 500 
     * Requested Duty Value = 0
     * 
     * Code Provided AS IS....Use at your own risk!
     */

    // be sure to set PWM port as output
    T2CON = 0b00000101; // prescaler + turn on TMR2;
    PR2 = 0b01111100;
    
    CCPR1L = 0b00000000; // set duty MSB
    CCP1CON = 0b00001100; // duty lowest bits + PWM mode
}

/*
 */
void adcInit(void)
{
    ADCON1bits.ADCS2 = 0b1;
    ADCON0bits.ADCS = 0b11;
    ADCON0bits.CHS = 0b000;

    ADCON1bits.ADFM = 0b1;
}

/*
 */
unsigned int adcOku(void)
{
    unsigned int deger;
    
    ADCON0bits.CHS = 0b000;
    ADCON0bits.ADON = 0b1;
    __delay_us(20); //akustik zamanı
    ADCON0bits.GO_nDONE = 1;
    while (ADCON0bits.GO_nDONE == 1);
    ADCON0bits.ADON = 0b0;
    deger = (unsigned int)(ADRESH << 8) | ADRESL ;
    
    if(deger > MAX_DUTY) deger = MAX_DUTY;    //en fazla duty degeri
    
    return deger;
}

/*
 */
void main(void)
{
    mcuInit();
    adcInit();
    pwmInit();

    while(1)
    {
        PWM(adcOku());
    }
}
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

E-x8

XC8 kullanmakta da sakınca yok lakin merak ediyorum CCS yerine XC8 mi öğrenilmeli mi diye :)
Kodlarınızı da hemen deneyeceğim.

sadogan

Timer2 yapılandırmasını   setup_timer_2(T2_DIV_BY_1,255,1);  Bu şekilde değiştirip adc değerini direk yükleyip test etinizmi ?

E-x8

setup_timer_2(T2_DIV_BY_1,170,1);

Şeklinde bırakarak değeri herhangi bir oranlamaya sokmadan gönderdim ve çalıştı fakat kafam karışık nasıl oldu da 1023'ü kabul etti?

E-x8

@mehmet Kodunuzu yükledim ve gerekli bağlantıları yaptım fakat çalışmadı.

mehmet

Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr