informer Postat Septembrie 20, 2019 Partajează Postat Septembrie 20, 2019 Acum 5 minute, aetius a spus: cand ajung la 0 nu se opreste , si trece mai departe la 255 si scade... Current_duty este unsigned... nu poate fi mai mic decat zero... pune "<=" sau doar "=". Link spre comentariu
aetius Postat Septembrie 20, 2019 Autor Partajează Postat Septembrie 20, 2019 //in caz de overflow, nu vrei sa se reseteze la 0, ci sa stea la 255 if ((current_duty_2) > 254 ) { current_duty_2 = 255 ; PWM2_Set_Duty(current_duty_2); break; } //in caz de overflow, nu vrei sa se reseteze la 255, ci sa stea la 0 if ((current_duty_2) < 0 ) { current_duty_2 = 0 ; PWM2_Set_Duty(current_duty_2); break; } se manifesta in felul urmator: daca cresc si ajunge la 255 ramine "blocat" acolo nici nu mai creste nici nu mai scade... daca ajung la 0 trece in 255 si ramine "blocat" acolo nu mai creste sau scade , indifferent ce buton apas... @informer am incercat ce ai zis dar nu merge....mai studiez Link spre comentariu
informer Postat Septembrie 20, 2019 Partajează Postat Septembrie 20, 2019 Daca pui tot codul, ti-l corectez. Problema este comparatia cu zero dar probabil decrementezi inainte si ajungi la 255 inapoi oricum. Nu pot dezarhiva rar-ul ala, n-am windows si nu stie arhivatorul meu... fa-l eventual zip. Link spre comentariu
aetius Postat Septembrie 20, 2019 Autor Partajează Postat Septembrie 20, 2019 #define bit oldstate; //Conexiuni LCD sbit LCD_RS at RB1_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 TRISB1_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; //Declarare variabile unsigned char ch, ADCx; unsigned int Tensiune; unsigned long V; unsigned short oldstate, current_duty_1, current_duty_2; void InitMain() { ADCON0 = 0b00001101; ADCON1 = 0b00000000; CMCON = 0b00000111; // Disable comparators CVRCON = 0; PORTA = 0b00001011; TRISA = 0b00001011; // configure PORTA pins as input PORTB = 0; // set PORTB to 0 TRISB = 0; // designate PORTB pins as output PORTC = 0; // set PORTC to 0 TRISC = 0; // designate PORTC pins as output PORTD = 0b11111111; TRISD = 1; oldstate = 0; Lcd_Init(); ADC_Init(); Lcd_Cmd(_LCD_CURSOR_OFF); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"Sursa digitala"); Delay_ms(500); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"TENSIUNE:"); } void main() { InitMain(); { short current_duty_1 = 16; // initial value for current_duty_1 short current_duty_2 = 16; // initial value for current_duty_2 PWM1_Init(5000); //Initialize PWM1 PWM2_Init(5000); //Initialize PWM2 PWM1_Start(); // start PWM1 PWM2_Start(); // start PWM2 PWM1_Set_Duty(current_duty_1); // Set current duty for PWM1 PWM2_Set_Duty(current_duty_2); // Set current duty for PWM2 } while (1) // endless loop { //Achizitie ADC Tensiune = 0; for (ADCx=0; ADCx<3; ADCx++) { Tensiune += ADC_Read(0); Delay_ms(10); } //Tensiune Tensiune = Tensiune/ADCx; // Alocare valoare tensiune V = (long)Tensiune*5000; // Converteste rezultat in milivolti V = V/1023; // 0...1023 => 0...5000mV ch = V/1000; // Extrage zeci 10.0 Lcd_Chr(1,10,48+ch); // Afisare rezultat in format ASCII linia 1, coloana 1 ch = (V/100) % 10; // Extrage unitati 01.0 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII Lcd_Chr_CP('.'); // Afiseaza caracter '.' ch = (V/10) % 10; // Extrage sutimi 00.1 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII LCD_Chr_CP('V'); // Afiseaza caracter 'V' Delay_ms(10); bit oldstate; if (Button(&PORTD, 0, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 0, 1, 0)) { oldstate = 0; current_duty_1++; PWM1_Set_Duty(current_duty_1); } if (Button(&PORTD, 1, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 1, 1, 0)) { oldstate = 0; current_duty_1--; PWM1_Set_Duty(current_duty_1); } if (Button(&PORTD, 2, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 2, 1, 0)) { oldstate = 0; current_duty_2++; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 3, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 3, 1, 0)) { oldstate = 0; current_duty_2--; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 4, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 4, 1, 0)) { oldstate = 0; current_duty_2 = 97; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 5, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 5, 1, 0)) { oldstate = 0; current_duty_2 = 250; PWM2_Set_Duty(current_duty_2); } Delay_ms(10); // slow down change pace a little //in caz de overflow, nu vrei sa se reseteze la 0, ci sa stea la 255 if ((current_duty_2) > 254 ) { current_duty_2 = 255 ; PWM2_Set_Duty(current_duty_2); break; } //in caz de overflow, nu vrei sa se reseteze la 255, ci sa stea la 0 if ((current_duty_2) < 0 ) { current_duty_2 = 0 ; PWM2_Set_Duty(current_duty_2); break; } } } aici am ajuns cu el ... daca modifici ceva scrie si comentariu ca sa inteleg. multumesc. Link spre comentariu
informer Postat Septembrie 20, 2019 Partajează Postat Septembrie 20, 2019 Treaba e asa: daca tu decrementezi un unsigned byte de la 0 o sa ajungi la 255 (sau 65535 pt unsigned int). Deci, inainte sa decrementezi testezi daca esti la zero si daca esti, NU decrementezi. Daca faci testul asta la decrementare, nu mai ai nevoie de comparatia aia cu zero de la sfarsit. Am pus if-urile, n-am mai facut curatenie si nici n-am cum sa testez, ca-s in viteza... incearca. (comentariile "//only decrement if duty > 0") #define bit oldstate; //Conexiuni LCD sbit LCD_RS at RB1_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 TRISB1_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; //Declarare variabile unsigned char ch, ADCx; unsigned int Tensiune; unsigned long V; unsigned short oldstate, current_duty_1, current_duty_2; void InitMain() { ADCON0 = 0b00001101; ADCON1 = 0b00000000; CMCON = 0b00000111; // Disable comparators CVRCON = 0; PORTA = 0b00001011; TRISA = 0b00001011; // configure PORTA pins as input PORTB = 0; // set PORTB to 0 TRISB = 0; // designate PORTB pins as output PORTC = 0; // set PORTC to 0 TRISC = 0; // designate PORTC pins as output PORTD = 0b11111111; TRISD = 1; oldstate = 0; Lcd_Init(); ADC_Init(); Lcd_Cmd(_LCD_CURSOR_OFF); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"Sursa digitala"); Delay_ms(500); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"TENSIUNE:"); } void main() { InitMain(); { short current_duty_1 = 16; // initial value for current_duty_1 short current_duty_2 = 16; // initial value for current_duty_2 PWM1_Init(5000); //Initialize PWM1 PWM2_Init(5000); //Initialize PWM2 PWM1_Start(); // start PWM1 PWM2_Start(); // start PWM2 PWM1_Set_Duty(current_duty_1); // Set current duty for PWM1 PWM2_Set_Duty(current_duty_2); // Set current duty for PWM2 } while (1) // endless loop { //Achizitie ADC Tensiune = 0; for (ADCx=0; ADCx<3; ADCx++) { Tensiune += ADC_Read(0); Delay_ms(10); } //Tensiune Tensiune = Tensiune/ADCx; // Alocare valoare tensiune V = (long)Tensiune*5000; // Converteste rezultat in milivolti V = V/1023; // 0...1023 => 0...5000mV ch = V/1000; // Extrage zeci 10.0 Lcd_Chr(1,10,48+ch); // Afisare rezultat in format ASCII linia 1, coloana 1 ch = (V/100) % 10; // Extrage unitati 01.0 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII Lcd_Chr_CP('.'); // Afiseaza caracter '.' ch = (V/10) % 10; // Extrage sutimi 00.1 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII LCD_Chr_CP('V'); // Afiseaza caracter 'V' Delay_ms(10); bit oldstate; if (Button(&PORTD, 0, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 0, 1, 0)) { oldstate = 0; current_duty_1++; PWM1_Set_Duty(current_duty_1); } if (Button(&PORTD, 1, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 1, 1, 0)) { oldstate = 0; //only decrement if duty > 0 if(current_duty_1 > 0) current_duty_1--; PWM1_Set_Duty(current_duty_1); } if (Button(&PORTD, 2, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 2, 1, 0)) { oldstate = 0; current_duty_2++; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 3, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 3, 1, 0)) { oldstate = 0; //only decrement if duty > 0 if(current_duty_2 > 0) current_duty_2--; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 4, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 4, 1, 0)) { oldstate = 0; current_duty_2 = 97; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 5, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 5, 1, 0)) { oldstate = 0; current_duty_2 = 250; PWM2_Set_Duty(current_duty_2); } Delay_ms(10); // slow down change pace a little //in caz de overflow, nu vrei sa se reseteze la 0, ci sa stea la 255 if ((current_duty_2) > 254 ) { current_duty_2 = 255 ; PWM2_Set_Duty(current_duty_2); break; } //in caz de overflow, nu vrei sa se reseteze la 255, ci sa stea la 0 if ((current_duty_2) < 0 ) { current_duty_2 = 0 ; PWM2_Set_Duty(current_duty_2); break; } } } Link spre comentariu
aetius Postat Septembrie 20, 2019 Autor Partajează Postat Septembrie 20, 2019 #define bit oldstate; //Conexiuni LCD sbit LCD_RS at RB1_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 TRISB1_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; //Declarare variabile unsigned char ch, ADCx; unsigned int Tensiune; unsigned long V; unsigned short oldstate, current_duty_1, current_duty_2; void InitMain() { ADCON0 = 0b00001101; ADCON1 = 0b00000000; CMCON = 0b00000111; // Disable comparators CVRCON = 0; PORTA = 0b00001011; TRISA = 0b00001011; // configure PORTA pins as input PORTB = 0; // set PORTB to 0 TRISB = 0; // designate PORTB pins as output PORTC = 0; // set PORTC to 0 TRISC = 0; // designate PORTC pins as output PORTD = 0b11111111; TRISD = 1; oldstate = 0; Lcd_Init(); ADC_Init(); Lcd_Cmd(_LCD_CURSOR_OFF); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"Sursa digitala"); Delay_ms(500); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"TENSIUNE:"); } void main() { InitMain(); { short current_duty_1 = 16; // initial value for current_duty_1 short current_duty_2 = 16; // initial value for current_duty_2 PWM1_Init(5000); //Initialize PWM1 PWM2_Init(5000); //Initialize PWM2 PWM1_Start(); // start PWM1 PWM2_Start(); // start PWM2 PWM1_Set_Duty(current_duty_1); // Set current duty for PWM1 PWM2_Set_Duty(current_duty_2); // Set current duty for PWM2 } while (1) // endless loop { //Achizitie ADC Tensiune = 0; for (ADCx=0; ADCx<10; ADCx++) { Tensiune += ADC_Read(0); Delay_ms(10); } //Tensiune Tensiune = Tensiune/ADCx; // Alocare valoare tensiune V = (long)Tensiune*5000; // Converteste rezultat in milivolti V = V/1023; // 0...1023 => 0...5000mV ch = V/1000; // Extrage zeci 10.0 Lcd_Chr(1,10,48+ch); // Afisare rezultat in format ASCII linia 1, coloana 1 ch = (V/100) % 10; // Extrage unitati 01.0 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII Lcd_Chr_CP('.'); // Afiseaza caracter '.' ch = (V/10) % 10; // Extrage sutimi 00.1 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII LCD_Chr_CP('V'); // Afiseaza caracter 'V' Delay_ms(10); bit oldstate; if (Button(&PORTD, 0, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 0, 1, 0)) { oldstate = 0; //only increment if duty < 255 if(current_duty_1 < 255) current_duty_1++; PWM1_Set_Duty(current_duty_1); } if (Button(&PORTD, 1, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 1, 1, 0)) { oldstate = 0; //only decrement if duty > 0 if(current_duty_1 > 0) current_duty_1--; PWM1_Set_Duty(current_duty_1); } if (Button(&PORTD, 2, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 2, 1, 0)) { oldstate = 0; //only increment if duty < 255 if(current_duty_2 < 255) current_duty_2++; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 3, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 3, 1, 0)) { oldstate = 0; //only decrement if duty > 0 if(current_duty_2 > 0) current_duty_2--; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 4, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 4, 1, 0)) { oldstate = 0; current_duty_2 = 97; PWM2_Set_Duty(current_duty_2); } if (Button(&PORTD, 5, 1, 1)) { oldstate = 1; } if (oldstate && Button(&PORTD, 5, 1, 0)) { oldstate = 0; current_duty_2 = 250; PWM2_Set_Duty(current_duty_2); } Delay_ms(10); // slow down change pace a little } } am modificat si pe" increment"... si functioneaza perfect... @informer , multumesc. Link spre comentariu
informer Postat Septembrie 20, 2019 Partajează Postat Septembrie 20, 2019 Cu riscu` sa fiu putin obositor, ma repet: daca ai intentia sa realizezi practic (pt. atelierul tau) aceasta sursa cu uC, mai gandeste-te daca nu vrei sa obtii acea tensiune variabila cu un DAC. Insist nu pt. ca am eu o idee fixa ci pt. ca ai avantaje majore fata de PWM: 1. Tensiunea continua de iesire (intrarea in amplificatorul de eroare al sursei) este calculabila si nu este dependenta de valoarea/deriva unor elemente R/C. De ex. daca intr-un DAC de 12 biti cu referinta de 4.096V (1mV/bit) scrii valoarea 1000, apai sigur ai 1V la iesire (+/- eroarea DAC-ului, evident) . Referinta este un alt IC de cativa RON.... 2. Nu ai pulsatii de nici un fel pe tensiunea generata, pulsatii mai mari sau mai mici regasibile in tensiunea generata de sursa. 3. Masurarea tensiunii la iesirea sursei o vei face doar ca verificare (o sa corespunda cu cea calculata...) si elimini semireglabilii aia (personal ii urasc...). Cat despre programarea scrierii in DAC nu-ti fa asa probleme... ii banala... te ajut/ajutam! 1 Link spre comentariu
aetius Postat Septembrie 20, 2019 Autor Partajează Postat Septembrie 20, 2019 (editat) proiect actualizat... daca mai sunt idei ,va rog sa le spuneti ... daca nu trec mai departe... multumesc. Sursa cu PIC16F877A @aetius ver2.pdsprj cod.txt overflow.c @informer ...momentan voi face sursa asta s-a ma familiarizez si dupa voi trece si la cea cu DAC (o s-a citesc despre DAC si ce poate face sau daca ai ceva linkuri). multumesc. 00.HEX Editat Septembrie 20, 2019 de aetius Link spre comentariu
UDAR Postat Septembrie 20, 2019 Partajează Postat Septembrie 20, 2019 Acum 10 ore, Thunderer a spus: Pai si unde tratezi overflow-ul? Asta ai vazut-o (avea o greseala pe pagina precedenta)? Este in Basic, dar o transformi tu in C: in caz de overflow, nu vrei sa se reseteze la 0, ci sa stea la 255 if steps > 254 then steps = 255 end if in caz de overflow, nu vrei sa se reseteze la 255, ci sa stea la 0 if steps < 0 then steps = 0 end if Daca steps este declarat ca unsigned nu poate avea valori < 0 deci conditia trebuie pusa ca steps <= 0. Link spre comentariu
Liviu M Postat Septembrie 21, 2019 Partajează Postat Septembrie 21, 2019 (editat) La 20.09.2019 la 8:26, informer a spus: O observatie: in masura posibilului incercati sa nu definiti variabile pt. valori care nu se modifica in timpul rularii programului... ca nu-s propriu zis variabile si-i ineficient. "Atatat" de afirmatia asta, m-am jucat cu o bucata de cod - am modificat diverse bucati de cod (variabile/define-uri, tipuri de date, "ajutat" microcontrollerul la calcula) si am afisat consumul de resurse. "Analiza" mi s-a parut interesanta si m-am gandit s-o impart cu voi. Codul analizat (nu e complet, e doar partea analizata) #define NR_OF_MEAS 10 void main(void) { unsigned long lAdc = 0; double dVI = 0.0; long lVI = 0; char myLine[] = {LINE_VOLT, LINE_CURR}; char myMeas[] = {VOLTAGE, CURRENT}; char myUnits[][3] = {"mV\0", "mA\0"}; unsigned char myMessage[][5] = {"V = \0", "C = \0"}; char actMeas = 0; chipInit(); while(1){ lAdc= 0; for(char i=0; i<NR_OF_MEAS; i++){ lAdc += adcRead(myMeas[actMeas]); } //mean value of the 10 measures dVI = ((double)lAdc)/NR_OF_MEAS/1024*5000; //use double to limit the rounding problems. //print the meas type on the LCD lcdToPos(myLine[actMeas], 1); lcdScrieSir(myMessage[actMeas]); //print the integer part on the LCD lVI = (long)dVI; // integer part printInt(myLine[actMeas], 9, lVI); ... E scris pentru xc8 de la microchip Primul aspect analizat e folosirea de #define, variabila, scris pur si simplu valoarea de mana - "variabila" NR_OF_MEAS Varianta 1: folosit 10 pur si simplu Memory Summary: Program space used 7CDh ( 1997) of 2000h words ( 24.4%) Data space used 6Ch ( 108) of 170h bytes ( 29.3%) Varianta 2: #define NR_OF_MEAS 10 Memory Summary: Program space used 7CDh ( 1997) of 2000h words ( 24.4%) Data space used 6Ch ( 108) of 170h bytes ( 29.3%) Varianta 3: char NR_OF_MEAS = 10; Memory Summary: Program space used 7FBh ( 2043) of 2000h words ( 24.9%) Data space used 71h ( 113) of 170h bytes ( 30.7%) Varianta 4: const char NR_OF_MEAS = 10; Memory Summary: Program space used 80Ah ( 2058) of 2000h words ( 25.1%) Data space used 70h ( 112) of 170h bytes ( 30.4%) Varianta 1 (scris direct 10) si varianta 2 (#define) sunt echivalente si ocupa cel mai putin loc. Variantele 3 si 4 (diverse tipuri de variabile) ocupa mai mult spatiu, impartit diferit intre spatiul de date si cel de programe. Cu alte cuvinte, informer are dreptate, #define e mai eficient. Au si #define-urile "slabiciunile" lor, da' nu-s semnificative/relevante in cazul de fata. Si pentru ca tot eram la analize, am vrut sa scot in evidenta si importanta alegerii tipului corect de date pentru variabile. Pentru exemplu am folosit variabila lVI, folosita la afisare: long lVI = 0; ... //print the integer part on the LCD lVI = (long)dVI; // integer part printInt(myLine[actMeas], 9, lVI); si resursele consumate pentru ea definita ca long(32 de biti) sau int (16 biti): Cazul 1: long (32 biti) cod: long lVI = 0; //mean value of the 10 measures dVI = ((double)lAdc)/NR_OF_MEAS/1024*5000 = ; //use double to limit the rounding problems. //print the integer part on the LCD lVI = (long)dVI; // integer part printInt(myLine[actMeas], 9, lVI); Memory Summary: Program space used 7CDh ( 1997) of 2000h words ( 24.4%) Data space used 6Ch ( 108) of 170h bytes ( 29.3%) Cazul 2: int (16 biti) cod: int lVI = 0; //mean value of the 10 measures dVI = ((double)lAdc)/NR_OF_MEAS/1024*5000 = ; //use double to limit the rounding problems. //print the integer part on the LCD lVI = (int)dVI; // integer part printInt(myLine[actMeas], 9, lVI); Memory Summary: Program space used 7C0h ( 1984) of 2000h words ( 24.2%) Data space used 6Ah ( 106) of 170h bytes ( 28.8%) Ultimul aspect analizat - calculele din cod. In cazul de fata, impartirea 5000/1024 (sau 1023, e mai putin important numarul exact) facut de uController sau facuta de mana cu calculatorul de buzunar si folosita valoarea (rotunjita) in cod: Ajutat compilatorul - calculat "de mana" 5000/1024 cod (cazul 2 de mai sus): //mean value of the 10 measures dVI = (lAdc * 4.883)/NR_OF_MEAS; ///1024*5000 = ; //use double to limit the rounding problems. // dVI = ((double)lAdc)/NR_OF_MEAS/1024*5000; //use double to limit the rounding problems. //print the meas type on the LCD lcdToPos(myLine[actMeas], 1); lcdScrieSir(myMessage[actMeas]); //print the integer part on the LCD lVI = (int)dVI; // integer part printInt(myLine[actMeas], 9, lVI); Memory Summary: Program space used 7A7h ( 1959) of 2000h words ( 23.9%) Data space used 67h ( 103) of 170h bytes ( 28.0%) De concluzii nu ma mai apuc si sper ca nu v-am plictisit prea tare. LE Si pentru ca tot am facut teoria chibritului despre tipul variabilelor, bineinteles ca optim ar fi fost unsigned int iAdc = 0; in loc de unsigned long lAdc = 0; Editat Septembrie 21, 2019 de Liviu M Link spre comentariu
Liviu M Postat Septembrie 21, 2019 Partajează Postat Septembrie 21, 2019 Salut, La 20.09.2019 la 11:08, aetius a spus: proiect actualizat... Poti, te rog, sa explici ce-ai vrut sa faci cu codul citat mai jos? #define bit oldstate; ... unsigned short oldstate, current_duty_1, current_duty_2; ... bit oldstate; ... Link spre comentariu
aetius Postat Septembrie 21, 2019 Autor Partajează Postat Septembrie 21, 2019 ca s-a nu ma dau mare ...recunosc ca nu stiu. sunt in programator de "weekend" au fost luate din exemple de cod de pe internet #define bit oldstate; --s-a transformat in#define bit oldstate = 0; ... unsigned short oldstate, current_duty_1, current_duty_2; -- nu stiu ... bit oldstate; --la curatenie s-a sters... ... Link spre comentariu
Liviu M Postat Septembrie 21, 2019 Partajează Postat Septembrie 21, 2019 (editat) Am formulat intrebarea gresit, recunosc. Trebuia sa intreb "ce vrei sa faca codul..." Acum sa-ti zic si de ce am intrebat. #define bit oldstate; --s-a transformat in#define bit oldstate = 0; #define x y nu face decat sa dea numele x lui y si e directiva preprocesor. Inainte de compilarea propriuzisa, preprocesorul verifica codul si unde gaseste x scrie y. Cu alte cuvinte, in cazul tau, oriunde ai scris "bit", preprocesorul va scrie "oldstate = 0". LA SFARSITUL LUI #define NU SE PUNE NICIODATA ";" (am scris intentionat cu litere mari, ca e important). Daca ai un cod de genul: #define multiplicator 10; ... int i = 3; int j = 5; ... j = multiplicator * i; dupa ce trece preprocesurul codul tau va arata cam: ... int i = 3; int j = 5; ... j = 10; * i; Precum vezi, nu e deloc ce te asteptai tu. PS Informatia de mai sus se regaseste in orice carte de C. Poate ca, inainte sa veniti cu probleme pe forum, n-ar fi rau sa mai deschideti cate o carte de programare in limbajul dorit. La o cautare rapida cu gogu am gasit o carte online care explica ce e cu directivele preprocesor. Din pacate e salvata ca poza si nu pot cita, dar poti consulta linistit capitolul 8. Editat Septembrie 21, 2019 de Liviu M Link spre comentariu
aetius Postat Septembrie 21, 2019 Autor Partajează Postat Septembrie 21, 2019 multumesc de explicatie... Link spre comentariu
gsabac Postat Septembrie 21, 2019 Partajează Postat Septembrie 21, 2019 La 20.09.2019 la 12:02, informer a spus: Cu riscu` sa fiu putin obositor, ma repet: daca ai intentia sa realizezi practic (pt. atelierul tau) aceasta sursa cu uC, mai gandeste-te daca nu vrei sa obtii acea tensiune variabila cu un DAC. Insist nu pt. ca am eu o idee fixa ci pt. ca ai avantaje majore fata de PWM: 1. Tensiunea continua de iesire (intrarea in amplificatorul de eroare al sursei) este calculabila si nu este dependenta de valoarea/deriva unor elemente R/C. De ex. daca intr-un DAC de 12 biti cu referinta de 4.096V (1mV/bit) scrii valoarea 1000, apai sigur ai 1V la iesire (+/- eroarea DAC-ului, evident) . Referinta este un alt IC de cativa RON.... 2. Nu ai pulsatii de nici un fel pe tensiunea generata, pulsatii mai mari sau mai mici regasibile in tensiunea generata de sursa. 3. Masurarea tensiunii la iesirea sursei o vei face doar ca verificare (o sa corespunda cu cea calculata...) si elimini semireglabilii aia (personal ii urasc...). Cat despre programarea scrierii in DAC nu-ti fa asa probleme... ii banala... te ajut/ajutam! Nu doresc sa va abat de la proiectul topicului, dar sursa cu PWM este utila atunci cand se doreste realizarea unui convertor sinus pur de putere, direct de la retea, cu MOSFET si transformator. Pentru o sursa de precizie, stabilitate si zgomot extrem de mic este cel mai bine de proiectat sau construit o sursa variabila de tensiune, de ex. cu PIC16F877 sau PIC16F877A, MCP4921 si etalon MCP1541. Tensiunea reglabila din claviatura, buton step rotitor si reglaj step din butoane, etc. O schema 0-50V cu pas de circa 12mV este in poza. Click pentru marire. Daca doriti o asemenea varianta va propun fisierele mikroC si Proteus. Reglajul este super rapid si precis, dar nu tineti seama de puterile disipate la curent mare, doar reglaj si stabilizare. Codul este extrem de simplu si reglajul contine si limitarile de tensiuni la 0V si 50V. // Name : Power Source MCP4921 12 bit DAC interfacing with PIC16F877 microcontroller via SPI Connectivity // DAC module connections sbit Chip_Select at RC0_bit; sbit Chip_Select_Direction at TRISC0_bit; #define TensiuneMax 4.080 unsigned int container ; unsigned int MSB; unsigned int LSB; float Tensiune; unsigned int numar_Bit; void convert_DAC(unsigned int value) { /*Step Size = 2^n, Therefore 12bit 2^12 = 4096 For 5V reference, the step will be 5/4095 = 0.0012210012210012V or 1mV (approx)*/ /*Step: 1, stored the 12 bit data into the container Suppose the data is 4095, in binary 1111 1111 1111*/ container = value; /*Step: 2 Creating Dummy 8 bit. So, by dividing 256, upper 4 bits are captured in LSB LSB = 0000 1111*/ LSB = container/256; /*Step: 3 Sending the configuration with punching the 4 bit data. LSB = 0011 0000 OR 0000 1111. Result is 0011 1111 */ LSB = (0x30) | LSB; /*Step:4 Container still has the 21bit value. Extracting the lower 8 bits. 1111 1111 AND 1111 1111 1111. Result is 1111 1111 which is MSB*/ MSB = 0xFF & container; } void main() { TRISD = 1; PORTD = 0b11111111; Tensiune=0.000; // Tensiune presetata la zero la pornire while(1) { SPI1_Init(); //SPI Chip_Select_Direction = 0; // Set CS# pin as Output if (!RD0_bit) // if button on RD0 pressed { //Sound_Play(2000,650); //trebuie pus buzerul play in Proteus Delay_ms(30); if (Tensiune <= TensiuneMax) Tensiune = Tensiune + 0.01; //increment 0.01V } if (!RD1_bit) // button on RD1 pressed { Delay_ms(30); if (Tensiune > 0.01) Tensiune = Tensiune - 0.01; // decrement 0.01V } numar_Bit=Tensiune/0.001; //converteste Volti in numarul de trepte de 1mV // numar_Bit=4095; convert_DAC(numar_Bit); Chip_Select = 0; SPI1_Write(LSB); SPI1_Write(MSB); Chip_Select = 1; } } Cu intarzierile de 30mS reglajul este rapid, dar sare pasi, iar cu o 500mS face pasi normali la click. @gsabac Sursa_PIC16F877_MCP4921.mcppi Sursa_PIC16F877_MCP4921.pdsprj Link spre comentariu
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum