Sari la conținut
ELFORUM - Forumul electronistilor

sursa cu pic


aetius

Postări Recomandate

           //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
#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

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
#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

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! :)

 

 

Link spre comentariu

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 de aetius
Link spre comentariu
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
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 de Liviu M
Link spre comentariu

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

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 de Liviu M
Link spre comentariu
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.

  277446797_sursareglabilacuPICsiDAC.thumb.png.eb0c5a0745e41571bee36fb0da0d9ac2.png

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

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