Sprintf omvandling blir inte som jag tänkt mig

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
newbadboy
Inlägg: 2426
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av newbadboy »

Lyckades få till det men ärligt talat utan att ha jättekoll på vad jag hittat på eg.


Kod: Markera allt

#include "SSD1306driver_lite.h"  // include SSD1306 OLED display driver source code

#define BTN LATC.F5
#define OUT LATC.F4
#define EN4 LATC.F7
#define EN3 LATB.F4
#define EN2 LATC.F1
#define EN1 LATA.F2

#define SSD1306_SOFT_I2C
#define SSD1306_128_64

char PrintOut[5];
float Temp, TempOut, Vbat, Adc1, Adc2, Adc3, Adc4;


// Software I2C connections
sbit Soft_I2C_Scl           at RB7_bit;
sbit Soft_I2C_Sda           at RB5_bit;
sbit Soft_I2C_Scl_Direction at TRISB7_bit;
sbit Soft_I2C_Sda_Direction at TRISB5_bit;
// End Software I2C connections


void NTC_Lookup(){
            if(Temp<365)
               TempOut=10;
            if((365<=Temp)&&(Temp<414))
                    TempOut=15;
            if((414<=Temp)&&(Temp<465))
                    TempOut=20;
            if((465<=Temp)&&(Temp<511))
                    TempOut=25;
            if((511<=Temp)&&(Temp<559))
                    TempOut=30;
            if((559<=Temp)&&(Temp<604))
                    TempOut=35;
            if((604<=Temp)&&(Temp<646))
                    TempOut=40;
            if((646<=Temp)&&(Temp<686))
                    TempOut=45;
            if((686<=Temp)&&(Temp<722))
                    TempOut=50;
            if((722<=Temp)&&(Temp<755))
                    TempOut=55;
            if((755<=Temp)&&(Temp<785))
                    TempOut=60;
            if((785<=Temp)&&(Temp<812))
                    TempOut=65;
            if((812<=Temp)&&(Temp<836))
                    TempOut=70;
            if((836<=Temp)&&(Temp<858))
                    TempOut=75;
            if((858<=Temp)&&(Temp<875))
                    TempOut=80;
            if((875<=Temp)&&(Temp<893))
                    TempOut=85;
            if((893<=Temp)&&(Temp<908))
                    TempOut=90;
            if((908<=Temp)&&(Temp<922))
                    TempOut=95;
            if((922<=Temp)&&(Temp<934))
                    TempOut=100;
            if((934<=Temp)&&(Temp<944))
                    TempOut=105;
            if((944<=Temp)&&(Temp<953))
                    TempOut=110;
            if((953<=Temp)&&(Temp<961))
                    TempOut=115;
            if((961<=Temp)&&(Temp<968))
                    TempOut=120;
            if((968<=Temp)&&(Temp<974))
                    TempOut=125;
}


void Adc_Read_All(){
           Temp=ADC_Read(4);    //ANA4
           Delay_ms(10);
           NTC_Lookup();

           Vbat=ADC_Read(5);    //ANA5
           Delay_ms(10);
           Vbat=(Vbat*88)/10000;

           Adc1=ADC_Read(16);   //CH1
           if(Adc1<20)          //filter
              Adc1=0;
           Delay_ms(10);
           Adc1=(Adc1*60)/10000;
           
           Adc2=ADC_Read(18);   //CH2
           if(Adc2<20)
              Adc2=0;
           Delay_ms(10);
           Adc2=(Adc2*49)/10000;
           
           Adc3=ADC_Read(14);   //CH3
           if(Adc3<20)
              Adc3=0;
           Delay_ms(10);
           Adc3=(Adc3*39)/10000;
           
           Adc4=ADC_Read(22);   //CH4
           if(Adc4<20)
              Adc4=0;
           Delay_ms(10);
           Adc4=(Adc4*56)/10000;
}
       
void Display_Out(){
           
           SSD1306_Color = 1;
           SSD1306_TextSize(1);
          
           sprintf(PrintOut, "%.2f", Vbat);
           SSD1306_GotoXY(1, 8);
           SSD1306_Print(PrintOut);
           
           sprintf(PrintOut, "%.0f", TempOut);
           SSD1306_GotoXY(1, 16);
           SSD1306_Print(PrintOut);
           

           sprintf(&PrintOut, "%.3f", Adc1);
           SSD1306_GotoXY(1, 24);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           

           sprintf(PrintOut, "%.3f", Adc2);
           SSD1306_GotoXY(1, 32);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);


           sprintf(PrintOut, "%.3f", Adc3);
           SSD1306_GotoXY(1, 40);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           
           sprintf(PrintOut, "%.3f", Adc4);
           SSD1306_GotoXY(1, 48);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);

           SSD1306_Display();
           
           delay_ms(2000);
           SSD1306_ClearDisplay();   // clear the buffer
}


Init_main(){
       OSCCON1=0B00000001;
       OSCFRQ=0b00000110;         // set internal oscillator to 16MHz
       OSCTUNE=0b00000000;


       
       ANSELA=0b00110000;         // configure all PORTS
       ANSELB=0b01000000;
       ANSELC=0b01000101;
       TRISA=0b00110000;
       TRISB=0b01000000;
       TRISC=0b01100101;

       delay_ms(1000);     // wait a second
       Soft_I2C_Init();  // initialize I2C communication
       
       SSD1306_Begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS);
       SSD1306_Display();
       delay_ms(2000);
       SSD1306_ClearDisplay();   // clear the buffer

       ADC_Init();

       EN1=1;
       EN2=1;
       EN3=1;
       EN4=1;

}


// main function
void main(){
     Init_main();
     while(1){
          ADC_Read_All();
          Delay_ms(10);
          Display_Out();
     }
}
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av johano »

"%.3f" säger att du vill ha talet skrivet med tre decimaler.

float Adc1=12345.987654321;

kommer alltså dels skrivas som "12345.987" och samtidigt flöda över din buffer PrintOut[5]
Användarvisningsbild
newbadboy
Inlägg: 2426
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av newbadboy »

ja sen har jag även delat med 10000 istället för multiolicerat med 1000 i Adc_Read_all() funktionen.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av johano »

Den här ser också lite konstig ut, är det verkligen avsikten att skicka _adressen_ av buffertpekaren??

"sprintf(&PrintOut, "%.3f", Adc1);"

Borde väl iofs gett en kompilatorvarning kan jag tycka.
Användarvisningsbild
newbadboy
Inlägg: 2426
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av newbadboy »

Nix .Inga varningar men & behövs inte så den tar jag bort. Tackar
Användarvisningsbild
Icecap
Inlägg: 26139
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av Icecap »

Med &Buffer avses adressen på den tilltänkta minneslokation.
Om man har en buffer som är definierat på rätt sätt (typ u_int8_t Buffer[]) räcker det såklart att bara ange 'Buffer' då det i verkligheten ger adressen till Buffer.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av johano »

newbadboy skrev:Nix .Inga varningar men & behövs inte så den tar jag bort. Tackar
Det är ju inte så att "den inte behövs", typ som om '&' vore något "extra attribut"
man kan klämma dit ibland för att få lite mer fjong i koden(!)

sprintf(&PrintOut, ...) innebär _något helt annat_ än sprintf(PrintOut, ...) och om det "fungerade"
så beror det på ren tur(*) och är en bugg som kommer bita förr eller senare.

Jag hoppas att du inte skriver ett styrsystem till en respirator.

* egentligen är det otur att det fungerade - det hade varit bättre med "stor svart rök" direkt vid såna här fel.
Min kompilator varnar direkt för detta, så jag tycker det låter konstigt att du inte fått någon varning på detta.
Användarvisningsbild
Icecap
Inlägg: 26139
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av Icecap »

Om kompilern varnar eller inte beror på vilka settings man använder.
De kan ställas till att varna om allt - men å andra sidan kan det ge mindre erfarna programmörer skrämselshicka.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45272
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av TomasL »

sprintf är väl en av de funktioner man inte skall använda, eftersom den inte är säker.
printf() is unsafe if you do not KNOW that the size of the input is safe. For example, if you are printing strings that you know from other places are no longer than 99 chars into a 120 char array, where the formatting itself adds no more than 20 characters then you are safe.

The difficulty, of course, is to judge whether the format and input is within range or not. You may for example want to format a floating point value, and you expect it to fit in %6.6f, but for some reason the value is greater than 999999, so the resulting string is longer than the format expects [and bear in mind that negative numbers take up one extra space, so a negative, large enough, number would also produce the same type of problem].

sprintf certainly has the ability to overflow.
Man får aldrig varningar om syntaxen är korrekt, men data är fel.
mounte
Inlägg: 204
Blev medlem: 14 november 2010, 13:15:00
Ort: Sandviken

Re: Sprintf omvandling blir inte som jag tänkt mig

Inlägg av mounte »

Ska ju inte lägg näsan allt för mycket i blöt (off topic med andra ord), men tänkte bara säga att din lookup-tabell (som gör det den ska väldigt effektivt) kan rationaliseras på många sätt.
För att inte dra det för långt så kan man t.ex. dr nytta av att det är en serie som ökar genom t.ex.:

Kod: Markera allt

const int limits[] = {
0, 365, 414, 465, 511, 559, 604, 646, 686, 722, 755, 785, 
812, 836, 858, 875, 893, 908, 922, 934, 944, 953, 961, 968, 974
};
const int results[] = {
-1, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70,
75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, -1
};

int NTC_Lookup(int temp_in) {
  int i = 0;
  while(temp_in >= limits[++i]);
  return results[i];
}
I de flesta fall får du nog något sämra prestanda med denna koden men den är enklare att underhålla.
Sedan om du har fallet med en serie som kan approximeras med en funktion så kan du implementera den matematiska funktionen.

Värt att notera för prestanda-freaks är följande: binär sökning / bisection fungerar nog riktigt fint för att inte behöva traversera listan hela tiden.
Not 2. Om man vet att temperaturen inte förändras drastiskt så kan man börja med att söka från den gräns man använde senast.
newbadboy skrev:Lyckades få till det men ärligt talat utan att ha jättekoll på vad jag hittat på eg.


Kod: Markera allt

#include "SSD1306driver_lite.h"  // include SSD1306 OLED display driver source code

#define BTN LATC.F5
#define OUT LATC.F4
#define EN4 LATC.F7
#define EN3 LATB.F4
#define EN2 LATC.F1
#define EN1 LATA.F2

#define SSD1306_SOFT_I2C
#define SSD1306_128_64

char PrintOut[5];
float Temp, TempOut, Vbat, Adc1, Adc2, Adc3, Adc4;


// Software I2C connections
sbit Soft_I2C_Scl           at RB7_bit;
sbit Soft_I2C_Sda           at RB5_bit;
sbit Soft_I2C_Scl_Direction at TRISB7_bit;
sbit Soft_I2C_Sda_Direction at TRISB5_bit;
// End Software I2C connections


void NTC_Lookup(){
            if(Temp<365)
               TempOut=10;
            if((365<=Temp)&&(Temp<414))
                    TempOut=15;
            if((414<=Temp)&&(Temp<465))
                    TempOut=20;
            if((465<=Temp)&&(Temp<511))
                    TempOut=25;
            if((511<=Temp)&&(Temp<559))
                    TempOut=30;
            if((559<=Temp)&&(Temp<604))
                    TempOut=35;
            if((604<=Temp)&&(Temp<646))
                    TempOut=40;
            if((646<=Temp)&&(Temp<686))
                    TempOut=45;
            if((686<=Temp)&&(Temp<722))
                    TempOut=50;
            if((722<=Temp)&&(Temp<755))
                    TempOut=55;
            if((755<=Temp)&&(Temp<785))
                    TempOut=60;
            if((785<=Temp)&&(Temp<812))
                    TempOut=65;
            if((812<=Temp)&&(Temp<836))
                    TempOut=70;
            if((836<=Temp)&&(Temp<858))
                    TempOut=75;
            if((858<=Temp)&&(Temp<875))
                    TempOut=80;
            if((875<=Temp)&&(Temp<893))
                    TempOut=85;
            if((893<=Temp)&&(Temp<908))
                    TempOut=90;
            if((908<=Temp)&&(Temp<922))
                    TempOut=95;
            if((922<=Temp)&&(Temp<934))
                    TempOut=100;
            if((934<=Temp)&&(Temp<944))
                    TempOut=105;
            if((944<=Temp)&&(Temp<953))
                    TempOut=110;
            if((953<=Temp)&&(Temp<961))
                    TempOut=115;
            if((961<=Temp)&&(Temp<968))
                    TempOut=120;
            if((968<=Temp)&&(Temp<974))
                    TempOut=125;
}


void Adc_Read_All(){
           Temp=ADC_Read(4);    //ANA4
           Delay_ms(10);
           NTC_Lookup();

           Vbat=ADC_Read(5);    //ANA5
           Delay_ms(10);
           Vbat=(Vbat*88)/10000;

           Adc1=ADC_Read(16);   //CH1
           if(Adc1<20)          //filter
              Adc1=0;
           Delay_ms(10);
           Adc1=(Adc1*60)/10000;
           
           Adc2=ADC_Read(18);   //CH2
           if(Adc2<20)
              Adc2=0;
           Delay_ms(10);
           Adc2=(Adc2*49)/10000;
           
           Adc3=ADC_Read(14);   //CH3
           if(Adc3<20)
              Adc3=0;
           Delay_ms(10);
           Adc3=(Adc3*39)/10000;
           
           Adc4=ADC_Read(22);   //CH4
           if(Adc4<20)
              Adc4=0;
           Delay_ms(10);
           Adc4=(Adc4*56)/10000;
}
       
void Display_Out(){
           
           SSD1306_Color = 1;
           SSD1306_TextSize(1);
          
           sprintf(PrintOut, "%.2f", Vbat);
           SSD1306_GotoXY(1, 8);
           SSD1306_Print(PrintOut);
           
           sprintf(PrintOut, "%.0f", TempOut);
           SSD1306_GotoXY(1, 16);
           SSD1306_Print(PrintOut);
           

           sprintf(&PrintOut, "%.3f", Adc1);
           SSD1306_GotoXY(1, 24);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           

           sprintf(PrintOut, "%.3f", Adc2);
           SSD1306_GotoXY(1, 32);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);


           sprintf(PrintOut, "%.3f", Adc3);
           SSD1306_GotoXY(1, 40);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           
           sprintf(PrintOut, "%.3f", Adc4);
           SSD1306_GotoXY(1, 48);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);

           SSD1306_Display();
           
           delay_ms(2000);
           SSD1306_ClearDisplay();   // clear the buffer
}


Init_main(){
       OSCCON1=0B00000001;
       OSCFRQ=0b00000110;         // set internal oscillator to 16MHz
       OSCTUNE=0b00000000;


       
       ANSELA=0b00110000;         // configure all PORTS
       ANSELB=0b01000000;
       ANSELC=0b01000101;
       TRISA=0b00110000;
       TRISB=0b01000000;
       TRISC=0b01100101;

       delay_ms(1000);     // wait a second
       Soft_I2C_Init();  // initialize I2C communication
       
       SSD1306_Begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS);
       SSD1306_Display();
       delay_ms(2000);
       SSD1306_ClearDisplay();   // clear the buffer

       ADC_Init();

       EN1=1;
       EN2=1;
       EN3=1;
       EN4=1;

}


// main function
void main(){
     Init_main();
     while(1){
          ADC_Read_All();
          Delay_ms(10);
          Display_Out();
     }
}
Skriv svar