Jump to content
ELFORUM - Forumul electronistilor

Generare PWM cu PIC16F84A in mikroC - cateva probleme


Guest deian_05

Recommended Posts

Guest deian_05

Doresc sa controlez un motor cu semnal PWM pe care il generez de la un PIC16F84A. Am realizat programul urmator in mikroC. Datele le transmit de la PC prin interfata RS232 dintr-un program realizat in LabView. Nu stiu foarte bine programare si as dori niste pareri/sfaturi legate de corectitudinea programului. Compilarea este cu succes doar daca sterg ultima parte (ultimul while "while (data1 == 0x61)....."). Daca las si ultima bucla while imi da o eroare "There is not enough ROM space", deci as avea nevoie de o solutie de restrangere a programului.

As mai avea o nelamurire: care este frecventa cu care imi transmite impulsurile? Trebuie sa o specific undeva in program?

 

 

 

unsigned char data1 = 0;

unsigned x, y;

unsigned short mat[4]; // matricea in care sunt stocate datele primite de la PC

unsigned short i=0;

 

void main() {

 

unsigned short *rec;

TRISA = 0x0A; // initializare porturi

TRISB = 0x00;

 

Soft_Uart_Init(PORTA, 1, 2, 9600, 0); //initializarea comunicatiei

 

do {

mat = Soft_Uart_Read(rec); // Citesc datele preluate de la PC prin RS232 in forma "o123" o=sens de rotire orar al motorului; 123=factor de umplere (de la 0 la 255)

i++;

} while (!*rec);

 

while (1){

 

PORTB=0x00;

 

data1=mat[0]; // data1 este "o" pt sens orar sau "a" pt sens antiorar

x = mat[1]*100 + mat[2]*10 + mat[3]; //concatenez celelalte elemente ( in cazul nostru 1 cu 2 cu 3 pentru a obtine 123)

 

while (data1 == 0x6F){ // adica "o" - sens orar

 

PORTB.F2=1; // se aprinde un LED albastru pt sens orar

 

for (i=0; i

PORTB.F7=1; // RB7 = pin de iesire pt pwm

delay_us(1);

}

 

y=255-x; // restul timpului cat sta pe "0" logic

for (i=0; i

PORTB.F7=0;

delay_us(1);

}

}

 

while (data1 == 0x61){ // directie antiorar

 

PORTB.F3=1; // se aprinde un aprinde led rosu pt sens antiorar

 

for (i=0; i

PORTB.F5=1 ;

delay_us(1);

}

y=255-x;

for (i=0; i

PORTB.F5=0 ;

delay_us(1);

 

}}}}

Link to comment
Share on other sites

do {

mat = Soft_Uart_Read(rec); // Citesc datele preluate de la PC prin RS232 in forma "o123" o=sens de rotire orar al motorului; 123=factor de umplere (de la 0 la 255)

i++;

} while (!*rec);

 

N-am idei, numai nedumeriri. De ce trimiti 3 octeti si faci 2 inmultiri si 2 adunari daca tot ce vrei e un numar intre 0 si 255?

Pentru asa iti ajunge un unsigned char.

A, si in pentru a posta codul mai citibil, foloseste cu incredere tag-urile Code. Iti va iesi cam asa

do {    mat[i] = Soft_Uart_Read(rec);     // Citesc datele preluate de la PC prin RS232 in forma "o123"                                                  // o=sens de rotire orar al   motorului; 123=factor de umplere (de la 0 la 255)    i++;} while (!*rec);
LE A propos, cat de lung e un short in mikroC? Ca daca e mai lung de 8 biti, poti folosi unsigned char pentru mat.
Link to comment
Share on other sites

Guest deian_05

N-am idei, numai nedumeriri. De ce trimiti 3 octeti si faci 2 inmultiri si 2 adunari daca tot ce vrei e un numar intre 0 si 255?Pentru asa iti ajunge un unsigned char.

Nu trimit 3 octeti. Trimit 4 octeti "o123". Folosesc un vector mat[4] in care introduc cei 4 octeti:mat[0]="o" (sensul de rotire orar)mat[1]=1mat[2]=2mat[3]=3Folosesc 2 inmultiri si 2 adunari pentru a reconstitui numarul: mat[1]*100+mat[2]*10+mat[3] = 1*100 + 2*10 + 3 = 123Daca folosesc o variabila in care sa retin toti 4 octeti cum ii mai separ? Adica sa separ "o" de "123"?In mikroC unsigned short are 8 biti (0...255). La fel si unsigned char.Cat despre tag-urile Code nu stiam de ele....is nou pe aici :jytuiyu
Link to comment
Share on other sites

Cu 1 octet in loc de 3 ma refeream la partea 123. In final vor fi 2 octeti: o/a pentru directie si un octet pentru factorul de umplere - 0..255.In rest, totul va fi ca inainte, numai ca scapi de 2 octeti si de operatiile de reconstruire.

Link to comment
Share on other sites

Guest deian_05

Cu 1 octet in loc de 3 ma refeream la partea 123.

Asa da...m-am gandit la asta dar nu stiu sa implementez. Imi poti da un exemplu? Eu de la PC transmit "o123" "o003" (in Labview am un slide care ia valori intre 000 si 255 si un buton pt sens de rotire). PIC-ul imi receptioneaza pe rand caracterele nu? Adica "o", pe urma "1" ..."2"...etc. primul transmis primul receptionat. Cum fac sa-mi retina caracterul "o" in variabila "data1" si restul in variabila "x"?Si te-as mai ruga sa te uiti la secventa urmatoare si sa-mi zici daca "se intampla" asa cum am gandit eu referitor la generarea pwm
for (i=0; i<x; i++) { PORTB.F7=1; // //timpul cat sta pe "1" logic (RB7 = pin de iesire pt pwm)delay_us(1);
in "x" am zis ca retin 123 (de exemplu). In urma buclei "for" la iesire voi avea "1" logic timp de 123 us (avand un delay de 1 us pt fiecare ciclu)
y=255-x;for (i=0; i<y; i++) { //timpul cat sta pe 0PORTB.F7=0;delay_us(1);
y= 255-123=132, adica 132 us timpul cat sta pe "0 logic"Deci in final voi avea un impuls cu perioada 255 us (123 cat sta pe "1" si 132 cat sta pe "0") adica o frecventa de 1/255 = 3.9 KHz. As putea sa pun delay de 2us si sa merg pana la 250 pt a avea o frecv de 2 KHz. La acestea nu se adauga si viteza de executie a instructiunii? (care este de 1 us la PIC-ul meu)Mersi pt ajutor...am un proiect care trebuie sa-l finalizez pana saptamana viitoare si nu ma prea descurc cu programarea.
Link to comment
Share on other sites

Pai eu as fi zis sa trimiti din labview direct ox, unde o e directia si x e factorul de umplere si la receptie sa receptionezi doar 2 bytes in loc de 4.

Datele le receptionezi tot intr-un vector, numai ca va fi mat[2] in loc de mat[4].

Iar la "construirea" pwm-ului as face zic eu mai simplu

PORTB.F7=1; // //timpul cat sta pe "1" logic (RB7 = pin de iesire pt pwm)delay_us(x);PORTB.F7=0; // //timpul cat sta pe "0" logic (RB7 = pin de iesire pt pwm)delay_us(255-x);
unde x e ce ai receptionat anterior (eventual -1, ca sa corectezi instructiunea in sine). Eventual poti salva 255-x intr-o variabila, ca sa nu pierzi de fiecare data cate o instructiune, da' mai poti corecta si pe parcurs.

Ca sa vezi daca timpii sunt buni, poti simula programul in mplab (asta daca mikroc poate functiona cu mplab, ca n-am idee).

Link to comment
Share on other sites

Guest deian_05

Pai eu as fi zis sa trimiti din labview direct ox.

Da e buna ideea...asta mi-a scapat. Mersi mult si pentru cealalata observatie. Imi va simplifica mult programul. Si asa nu aveam destul loc in ROM-ul PIC-ului.Nu am inteles partea cu "eventual -1, ca sa corectezi instructiunea in sine". De ce sa pierd instructiuni?Cat despre timpi crezi ca este buna perioada de ordinul microsecundelor? Cu acest semnal comand grila unui MOS de putere (60V 55A). Am vazut pe alte forumuri ca unii se intrebau daca le ajunge o frecventa de 500 KHz, pe cand la mine frecventa ar de 2-3 KHz
Link to comment
Share on other sites

Pai o instructiune dureaza 1us, microsecunda care se adauga la perioada ta. Ca sa anulezi efectul ei, micsorezi delayul corespunzator cu 1us => -1. Despre frecventa aleasa... cred depinde de aplicatie, de ce vine dupa mosi si la ce frecvente functioneaza dispozitivele comandate. Oricum, de aici mai departe ma cam depaseste problema (experienta mea in zona asta tinde spre 0).

Link to comment
Share on other sites

Guest deian_05

PORTB.F7=1; // //timpul cat sta pe "1" logic (RB7 = pin de iesire pt pwm)delay_us(x);PORTB.F7=0; // //timpul cat sta pe "0" logic (RB7 = pin de iesire pt pwm)delay_us(255-x);
Am incercat asa dar nu merge. Nu se pot pune in delay decat numere intregi. Nu merge cu "x". Deci sunt nevoit sa raman la buclele for.Nu inteleg de ce ocupa atata ROM Soft_Uart. Daca pun bucla aceasta:
Soft_Uart_Init(PORTA, 1, 2, 9600, 0);  //Initializing the communicationdodata_ = Soft_Uart_Read(rec); // Receive data while (!*rec);
La statistici imi arata 99% ocupat din ROM :cry: Fara ea programul ocupa doar 7%. Deci imi ocupa 92%. Nu mai pot face aproape nimic altcevaTu in ce programezi?? Sa fie mikroC de vina? E mai ok MPLAB? Sau sa caut un alt microcontroller cu memorie mai mare
Link to comment
Share on other sites

Cine e x la tine? La mine era pe post de exemplu. Corect ar fi trebuit sa scriu mat[1], da' m-am grabit.Cat despre spatiu nu stiu ce sa zic. Trebuie sa te uiti in functii si sa vezi cine mananca asa multa. Pe de alta parte, functiile care vin cu compilatoarele sunt mai generale, asa. S-ar putea ca daca ti le scrii singur sa le poti optimiza.Eu pana acum mi-am scris singur toate functiile de care am avut nevoie, incercand sa le optimizez. Ce-i drept, aplicatiile mele n-au fost prea complicate iar controllerele au fost ceva mai generoase.Referitor la controller, din cate stiu eu 16f84 n-are port rs232 implemetat in hard, asa ca tot protocolul e emulat in soft si, cred, de-aia ocupa atata memorie. Incearca sa gasesti un controller cu rs232 hard (sau recompileaza pentru 16f627/16f628, ca cred ca sunt compatibile cu 84 si au rs232 hard).

Link to comment
Share on other sites

Guest deian_05

Cine e x la tine? La mine era pe post de exemplu.

Am scris in felul urmator sa vad daca functioneaza si imi da eroare la compilare "Integer const expected":
x=12;PORTB.F7=1; // //timpul cat sta pe "1" logic (RB7 = pin de iesire pt pwm)delay_us(x);
Am simulat programul in Proteus si am vizualizat pe osciloscop virtual semnalul si merge (bineinteles cu date prestabilite pentru factorul de umplere...am dat valori pe rand). Ramane de rezolvat problema cu transmisia RS232. Am sa incerc cu un PIC16F877 care are si PWM incorporat. Multumesc mult pentru ajutor deocamdata si poate am sa te mai deranjez cu vreo intrebare doua zilele viitoare :P
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines