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:

Sprintf omvandling blir inte som jag tänkt mig

Inlägg av newbadboy »

Har ett program som mäter några strömman genom en shunt. ADC1-4 kallar jag dem.
Detta skrivs ut på en Oled display men här blir det inte som jag tänkt och får inte till det.

Mäter jag jag tex 1555mA så skriver den ut 1555 vilket är ok.
Mäter jag 555mA så skriver den ut 5550. Vilket blir fel att läsa.
Ni hittar detta i Display_out();

Hur gör jag ? :oops:

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)*1000;
           
           Adc2=ADC_Read(18);   //CH2
           if(Adc2<20)
              Adc2=0;
           Delay_ms(10);
           Adc2=(Adc2*49)*1000;
           
           Adc3=ADC_Read(14);   //CH3
           if(Adc3<20)
              Adc3=0;
           Delay_ms(10);
           Adc3=(Adc3*39)*1000;
           
           Adc4=ADC_Read(22);   //CH4
           if(Adc4<20)
              Adc4=0;
           Delay_ms(10);
           Adc4=(Adc4*56)*1000;
}
       
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, "%-.0f", Adc1);
           SSD1306_GotoXY(1, 24);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           

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

           sprintf(PrintOut, "%-.0f", Adc3);
           SSD1306_GotoXY(1, 40);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           
           sprintf(PrintOut, "%-.0f", 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();
     }
}
Senast redigerad av newbadboy 4 september 2019, 10:52:58, redigerad totalt 1 gång.
Shimonu
Inlägg: 294
Blev medlem: 21 oktober 2015, 22:44:33

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

Inlägg av Shimonu »

Varför gör du såhär?

Kod: Markera allt

PrintOut[4]=0;
Har du testat med att bara göra en enkel %f?
Senast redigerad av Shimonu 4 september 2019, 10:56:59, redigerad totalt 1 gång.
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 »

Utan den får jag tex om jag mäter 555mA ut på displayen 55500000.
Shimonu
Inlägg: 294
Blev medlem: 21 oktober 2015, 22:44:33

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

Inlägg av Shimonu »

Det verkar ju som funktionen som skriver ut inte hanterar null-tecken rätt.

Ah! Det är inte så att det är för stora tal som skrivs då? Flyttal kan ju vara mycket längre än 4 tecken. Förmodligen blir det något i stil med 555.0000004536 eller så som du inte gör rätt med.
Senast redigerad av Shimonu 4 september 2019, 11:02:09, redigerad totalt 1 gång.
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

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

Inlägg av snigelen »

Vilket betyder att du låter sprintf skriva utanför din buffer. Fatalt programmeringsfel.

Se till att PrintOut verkligen har plats för det sprintf tänker fylla den med. Eller använd snprintf.
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 »

Du menar denna?

SSD1306_Print(PrintOut);

såhär ser den ut i ssd1306driver_lite.h
void SSD1306_Print(char *s);


och såhär ser den ut eg

Kod: Markera allt

// print text
void SSD1306_Print(char *s) {
  uint8_t i = 0;
  while (s[i] != '\0'){
    if (s[i] == ' ' && x_pos == 0 && wrap)
      i++;
    else
      SSD1306_PutC(s[i++]);
  }
}
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 »

snigelen skrev:Vilket betyder att du låter sprintf skriva utanför din buffer. Fatalt programmeringsfel.

Se till att PrintOut verkligen har plats för det sprintf tänker fylla den med. Eller använd snprintf.

Detta är inget jag pysslat med innan så att jag gör ett fatalt fel är inget som förvånar mig.

snprintf godkänns inte av min kompilator, vad står detta för. Den har kanske annan syntax bara i kompilator
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

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

Inlägg av snigelen »

Ändra då "char PrintOut[5];" till något rimligare, t.ex char PrintOut[15]; och se om du får rimliga reslutat (utan PrintOut[4] = 0 förståss).

Med snprntf får du ange maximalt antal byte som för skrivas till buffern.
Vad är det för bibliotek som har sprintf men inte snprintf?
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 »

nixpix. får samma. 55500000

Här har du länk till libbet

https://download.mikroe.com/documents/c ... ibrary.htm
Användarvisningsbild
Icecap
Inlägg: 26106
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 jag inte minns helt fel gör sprintf(&Buffer, "%-.0f", float) inte helt som du tror.
Om du vill ha 4 siffror och ingen decimal skulle jag använda sprintf(&Buffer, "%4.0f", float);

Har för mig att '-' strax bakom '%' betyder "left justified" vilket definitivt inte är önskvärd här.
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 »

Om jag inte minns helt fel gör sprintf(&Buffer, "%-.0f", float) inte helt som du tror.
Om du vill ha 4 siffror och ingen decimal skulle jag använda sprintf(&Buffer, "%4.0f", float);

Har för mig att '-' strax bakom '%' betyder "left justified" vilket definitivt inte är önskvärd här.
det stämmer det betyder left justified




Provar som nedan

Kod: Markera allt

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

om jag inte lastar shunten skriver den ut en 0a bara, med koden ovan flyttar den 0an 4steg. När jag sen lastar med 555ma skriver den ut 5550
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

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

Inlägg av FormerMazda »

Rensas nollan från skärmen när den ska skriva 555?
Lasta shunten först, starta arduinon sen. Eller resetta den. Blir det rätt då så är det ju en envis nolla som behöver rensas först bara.
Användarvisningsbild
Icecap
Inlägg: 26106
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 »

OK, en enkel lösning:
u_int16_t Value;
Value = float;
sprintf(&Buffer, "%4u", Value);
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

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

Inlägg av arvidb »

... fast utan & före strängvariabeln!
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

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

Inlägg av arvidb »

newbadboy skrev:

Kod: Markera allt

           Adc1=ADC_Read(16);   //CH1
           if(Adc1<20)          //filter
              Adc1=0;
           Delay_ms(10);
           Adc1=(Adc1*60)*1000;
Det minsta värdet som Adc1 kan få, förutom 0, är ju 1200000. Så hur skulle den kunna skriva ut 555 eller 1555? Om ADC_Read(16) returnerar 925 så blir Adc1 55500000. Det kanske är det den försöker skriva ut?

(Helt värdelöst för övrigt om de implementerat sprintf() men inte snprintf()! Det borde vara tvärt om!)

Edit: Bättre matte. :)
Skriv svar