Sari la conținut
ELFORUM - Forumul electronistilor

Adaugare iesire PWM


csongore

Postări Recomandate

Salutare!
Sunt un programator amator si m-am inpotmolit intr-un proiect, am un cantar si cu un PIC16F876A am facut un fel de comparator analog/digital el citeste tensiunea analogica de la cantar afiseaza si compara cu valoarea setata de doua butoane daca valoarea analogica e >= cu cel setat apare un 1 la o iesire.
 

Mai vreau sa fac o iesire PWM pe Portul C1 controlat de un potmetru pus la intrarea A1 puteti cumva sa ma ajutat cam cum ar trebuie facut?

 

 

// LCD module connectionssbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit;sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit;// End LCD module connectionschar Message1[]="MASURAT:";       // Message for line1;char Message2[]="REGLAT :";char Message3[]=" SYS";char Message4[]="by B.Csongor";unsigned int mas,val1,number = 0;unsigned long u;unsigned char ch;char *digit = "0000";void Display_init(){ digit[0] = number/1000 + 48;           // thousands digit; digit[1] = (number/100)%10 +48;        // hundreds digit; digit[2] = (number/10)%10 + 48;        // tens digit; digit[3] = number%10 +48;              // unit digit; Lcd_Out(2,9,digit);                    // display on LCD from column 2, character 7; LCD_Chr_CP('G');   }void main()                             // main;{ TRISA      = 0xFF; CMCON |= 7;                            // turn off analogue comparator and make PORTA to digital I/O; TRISC=0xE0; PORTC=0xE0; TRISC4_bit = 1;                        // make PORT RA4 as input for button; TRISC5_bit = 1;                        // make PORT RA5 as input for button; TRISC6_bit = 1;                        // make PORT RA6 as input for button; TRISC7_bit = 1;                        // make PORT RA7 as input for button; TRISC.F0 = 0;                          //declaram un port la iesire  pentru led PORTC.F0=1;                            //starea initiala a portului setata in 0 logic, ledul e stins TRISB = 0;                             // Set PORTB direction to be output; PORTB = 0;                             // Turn ON PORTB; Lcd_init();                            // LCD Initialization; Lcd_cmd(_LCD_CLEAR);                   // Clear LCD; Lcd_cmd(_LCD_CURSOR_OFF);              // Cursor mode, off; Lcd_out(1,1,Message3); Lcd_out(2,2,Message4); Delay_ms(1000); Lcd_cmd(_LCD_CLEAR); Lcd_out(1,1,Message1);                 // display message1 from column 1, character 3; Lcd_out(2,1,Message2); do{    if(Button(&PORTC,4,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;                             number = number +50;                             }    if(Button(&PORTC,5,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;                             number = number +5;                             }    if(Button(&PORTC,6,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and increment "number" with 1;                             number = number -50;                             }    if(Button(&PORTC,7,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;                             number = number -5;                             }    if (number > 9999u)                 // if it's more than 9999 go to 0;    number = 0;    display_init();                     // call display_init();          mas=ADC_read(0);                // get ADC value for U from channel 1      u=(long)mas*1000;               // covert adc reading to milivolts      u=u/1023;                            // 0..1023 -> 0-5000mV      ch=u/1000;                           // extract 10.00 U digit      if (ch==0)        {          LCD_Chr(1,9, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,9,48+ch);              // write ASCII digit at 1st row, 2nd column        }      ch=(u/100) %10;                      // extract 01.00 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      ch=(u/10) %10;                       // extract 00.10 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      ch=(u/1) %10;                       // extract 00.10 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      LCD_Chr_CP('G');            if (mas >= number)      {        PORTC.F0=0; //led on       Delay_ms(100);       }       else   PORTC.F0= 1;           } while(1);                         // infinite loop; }

 

Link spre comentariu
  • Răspunsuri 8
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Mircea

    4

  • csongore

    3

  • djvas

    1

  • Liviu M

    1

Top autori în acest subiect

Citeste help-ul MikroC: http://www.mikroe.com/mikroc/pic/libraries/

 

Ai CCP2 (RC1). Nu uita sa setezi bitii de iesire pentru RC1 (cred ca se ocupa modulul PWM de asta oricum), intrare pentru RA1. CCP1CON = b'00001111' bitii 3 si 2 trebuie sa fie 11 ca sa fie in PWM mode.


Inainte de bucla principala pui

void main() {PWM2_Init(5000); // Initialize PWM2 module at 5KHzcurrent_duty1 = 127; // initial value for current_duty = 50%PWM2_Start(); // start PWM1PWM2_Set_Duty(current_duty1); // Set current duty for PWM2

Apoi, valoarea citita de ADC o pui mereu in current_duty1, daca ADC e diferit de valoarea precedenta (o comparatie IF). Nu faci reactualizarea decat daca s-a schimbat valoarea potentiometrului.

current_duty1=ADC_read(1)

As folosi ADC_get_sample(x) caci asta nu face mereu initializarea ADC precum ADC_read(x). LE: vad ca nu ai pus in initializare ADC_Init(), deci continua sa folosesti ADC_Read(x). Nu este o aplicatie prea rapida, deci nu conteaza.

 

 

Eu lucrez in Basic, nu pot scrie toata sintaxa C. Dar ti-am dat bazele.

Editat de thunderer
Link spre comentariu

Rezolutia PWM nu e de 10 biti? Daca da, valoarea 127 pentru duty-cycle s-ar putea sa nu dea 50%.Eu nu folosesc functii de prin biblioteci, ci setez de mana toate modulele, asa ca trebuie sa setez singur si timerul (+ prescalerul corespunzator). Nu-mi dau seama cum pot fi astea setate prin functiile PWM de mai sus in conditiile in care frecventa de lucru nu e specificata nicaieri, da' probabil e vreun parametru pe undeva prin IDE-ul mikro.LE M-am uitat prin helpul mikroc si da, 127 e valoarea pentru DC 50%, iar pentru 100% e 255. In cazul asta nu cred ca poate fi folosit

current_duty1=ADC_read(1)
Ma rog, poate fi folosit, dar rezultatele vor fi "surprinzatoare". Eu as folosi
current_duty1=ADC_read(1) >> 2
adica as pastra doar cei 8 MS biti. Editat de Liviu M
Link spre comentariu

Liviu, good catch! Evident, scalarea (o impartire la 4) e necesara.Multumesc pentru corectie!In aplicatii simple folosesc functiile implementate. In rest, setez registrii corespunzatori. Am postat in trecut un mic tutorial PWM cu 16F690, cred ca a fost transferat in noul forum. Dar o fi pe pagina n-spe la PIC.LE: nu-l mai gasesc, o sa-l pun din nou.

Editat de thunderer
Link spre comentariu

Salutare nu prea am reusit sa dau de cap poate nu am declarat cum trebuie intraraile si iesirele pentru pwm.

// LCD module connectionssbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit;sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit;// End LCD module connectionschar Message1[]="MASURAT:";       // Message for line1;char Message2[]="REGLAT :";char Message3[]="SYS";char Message4[]="by B.Csongor";unsigned int mas,mas2,val1,number = 0;unsigned long u;unsigned char ch;unsigned short current_duty;char *digit = "0000";void Display_init(){ digit[0] = number/1000 + 48;           // thousands digit; digit[1] = (number/100)%10 +48;        // hundreds digit; digit[2] = (number/10)%10 + 48;        // tens digit; digit[3] = number%10 +48;              // unit digit; Lcd_Out(2,9,digit);                    // display on LCD from column 2, character 7; LCD_Chr_CP('G');   }void main()                             // main;{ TRISA      = 0xFF; CMCON |= 7;                          // turn off analogue comparator and make PORTA to digital I/O; TRISC0_bit = 0; TRISC1_bit = 0; TRISC3_bit = 1;                        // make PORT RA5 as input for button; TRISC4_bit = 1;                        // make PORT RA4 as input for button; TRISC5_bit = 1;                        // make PORT RA5 as input for button; TRISC6_bit = 1;                        // make PORT RA6 as input for button; TRISC7_bit = 1;                        // make PORT RA7 as input for button; TRISB = 0;                             // Set PORTB direction to be output; PORTB = 0;                             // Turn ON PORTB; PWM1_Init(5000); Lcd_init();                            // LCD Initialization; Lcd_cmd(_LCD_CLEAR);                   // Clear LCD; Lcd_cmd(_LCD_CURSOR_OFF);              // Cursor mode, off; Lcd_out(1,1,Message3); Lcd_out(2,2,Message4); Delay_ms(1000); Lcd_cmd(_LCD_CLEAR); Lcd_out(1,1,Message1);                 // display message1 from column 1, character 3; Lcd_out(2,1,Message2);  do{    if(Button(&PORTC,4,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;                             number = number +50;                             }    if(Button(&PORTC,5,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;                             number = number +5;                             }    if(Button(&PORTC,6,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and increment "number" with 1;                             number = number -50;                             }    if(Button(&PORTC,7,1,0)){                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;                             number = number -5;                             }    if (number > 9999u)                 // if it's more than 9999 go to 0;    number = 0;    display_init();                     // call display_init();          mas=ADC_read(0);                // get ADC value for U from channel 1      u=(long)mas*1000;               // covert adc reading to milivolts      u=u/1023;                            // 0..1023 -> 0-5000mV      ch=u/1000;                           // extract 10.00 U digit      if (ch==0)        {          LCD_Chr(1,9, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,9,48+ch);              // write ASCII digit at 1st row, 2nd column        }      ch=(u/100) %10;                      // extract 01.00 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      ch=(u/10) %10;                       // extract 00.10 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      ch=(u/1) %10;                       // extract 00.10 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      LCD_Chr_CP('G');            if (mas >= number)      {        PORTC.F0=0; //led on       Delay_ms(100);       }       else   PORTC.F0= 1;              PWM1_Start();       PWM1_Set_Duty(current_duty);       current_duty=ADC_read(1) >> 2;       Delay_ms(40);           } while(1);                         // infinite loop; }
Link spre comentariu

As verifica daca am ceva pe CCP1 (RC2) pentru ca PWM-ul asta l-ai activat, nu CCP2 (RC1). Apoi n-ai declarat care-s intrari analogice. ANSEL si ANSELx ar trebui sa fie registrii.Vezi cum am indicat eu initializarea (ce pui in afara buclei While si ce pui in bucla). Nu ai respectat. Nu ca ar fi catastrofic, dar faci operatii non-necesare si poate cu bucluc. Scriu de pe telefon si nu pot edita mai mult.

Editat de thunderer
Link spre comentariu
  • 2 săptămâni mai târziu...

Cum a zis si "thunder" tu ai activat CCP1(RC2) .

Am modificat codul pentru CCP2 RC1.

PWM1_Start()  este suficient sa o initializezi la inceput , nu trebuie pusa in bucla infinita

Codul de mai jos l-am testat in proteus si functioneaza

 

// LCD module connectionssbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit;sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit;// End LCD module connectionschar Message1[]="MASURAT:"; // Message for line1;char Message2[]="REGLAT :";char Message3[]="SYS";char Message4[]="by B.Csongor";unsigned int mas,mas2,val1,number = 0;unsigned long u;unsigned char ch;unsigned short current_duty;char *digit = "0000";void Display_init(){ digit[0] = number/1000 + 48; // thousands digit; digit[1] = (number/100)%10 +48;   // hundreds digit; digit[2] = (number/10)%10 + 48;   // tens digit; digit[3] = number%10 +48;   // unit digit; Lcd_Out(2,9,digit);   // display on LCD from column 2, character 7; LCD_Chr_CP('G'); }void main() // main;{ TRISA   = 0xFF; CMCON |= 7;   // turn off analogue comparator and make PORTA to digital I/O; TRISC0_bit = 0; TRISC1_bit = 0; TRISC3_bit = 1;   // make PORT RA5 as input for button; TRISC4_bit = 1;   // make PORT RA4 as input for button; TRISC5_bit = 1;   // make PORT RA5 as input for button; TRISC6_bit = 1;   // make PORT RA6 as input for button; TRISC7_bit = 1;   // make PORT RA7 as input for button; TRISB = 0; // Set PORTB direction to be output; PORTB = 0; // Turn ON PORTB; PWM2_Init(5000); PWM2_Start(); Lcd_init();   // LCD Initialization; Lcd_cmd(_LCD_CLEAR); // Clear LCD; Lcd_cmd(_LCD_CURSOR_OFF);   // Cursor mode, off; Lcd_out(1,1,Message3); Lcd_out(2,2,Message4); Delay_ms(1000); Lcd_cmd(_LCD_CLEAR); Lcd_out(1,1,Message1); // display message1 from column 1, character 3; Lcd_out(2,1,Message2); do{   if(Button(&PORTC,4,1,0)){ Delay_ms(200);   // If button is pressed, delay 0,2s and decrement "number" with 1; number = number +50; }   if(Button(&PORTC,5,1,0)){ Delay_ms(200);   // If button is pressed, delay 0,2s and decrement "number" with 1; number = number +5; }   if(Button(&PORTC,6,1,0)){ Delay_ms(200);   // If button is pressed, delay 0,2s and increment "number" with 1; number = number -50; }   if(Button(&PORTC,7,1,0)){ Delay_ms(200);   // If button is pressed, delay 0,2s and decrement "number" with 1; number = number -5; }   if (number > 9999u) // if it's more than 9999 go to 0;   number = 0;   display_init(); // call display_init();   mas=ADC_read(0);   // get ADC value for U from channel 1   u=(long)mas*1000; // covert adc reading to milivolts   u=u/1023;   // 0..1023 -> 0-5000mV   ch=u/1000; // extract 10.00 U digit   if (ch==0)   {   LCD_Chr(1,9, 32);   // write empty space if digit is 0   }   else   {   LCD_Chr(1,9,48+ch);   // write ASCII digit at 1st row, 2nd column   }   ch=(u/100) %10;   // extract 01.00 U digit   LCD_Chr_CP(48+ch); // write ASCII digit at cursor point   ch=(u/10) %10; // extract 00.10 U digit   LCD_Chr_CP(48+ch); // write ASCII digit at cursor point   ch=(u/1) %10; // extract 00.10 U digit   LCD_Chr_CP(48+ch); // write ASCII digit at cursor point   LCD_Chr_CP('G');   if (mas >= number)   {   PORTC.F0=0; //led on Delay_ms(100); } else PORTC.F0= 1; PWM2_Set_Duty(current_duty); current_duty=ADC_read(1) >> 2; Delay_ms(40);   } while(1); // infinite loop; }

Link spre comentariu

N-a mai zis nimic colegul csongore. Sper ca a rezolvat si se bucura de rezultat.@djvas, foloseste CODE cand postezi programe. Se vede si urmareste mai bine.

Editat de thunderer
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări