binär till float

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

binär till float

Inlägg av Lullen »

Jag håller på att läsa av en tempsensor,DS18B20, problemet är bara att den ger ut temperaturen i två olika byte. Jag kan läsa av sensorn men när jag ska göra om det till en float så kommer problemen!

Kod: Markera allt

float readTempature()                   //läser av temp från tempsensorn och gör om resultatet till float
 {
    float temp;
    int mask;
    float add;
    unsigned btemp;
    unsigned short j;

    //..
    //kod för att ta emot MSB och LSB
    //..
    j = Ow_Read(&PORTA,6);                            // Get temperature LSB
    btemp = Ow_Read(&PORTA,6);                      // Get temperature MSB


    mask = 00001000;                                      //mask för att bestämma vilken bit som skall läsas
    add = 64.0;                                                 //hur mycket som ska adderas om biten = 1
    temp = 0;                                                  //nollställ tempen

    while (mask > 0)                                        //konvertera MSB
    {
       if(btemp & mask == 1)                           //den kontrollerade biten är hög
       {
          temp += add;                                      //addera talet till temp
       }

       mask >> 1;                                          //bestäm nästa bit som ska kontrolleras
       add/2;                                                //minska talet som ska adderas
    }
    

    //...
    //samma sak fast med LSB
    //...
    
    return temp;
 }
När jag kompilerar detta så får jag felmeddelandet "duplicated labels JMPSETFOV32" vilket jag inte förstår mig på. Fick det förut när jag felstavat en variabel i en uträkning, men så är inte fallet nu i alla fall.
Senast redigerad av Lullen 8 maj 2008, 21:05:53, redigerad totalt 1 gång.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Men varför?

Float är en dålig lösning på "allt", det vore mycket bättre att ha fast upplösning så att temperaturen räknas i t.ex 1/10°C, 123 vill alltså ge 12,3°C.

Och sedan är det ett annat problem: DS18S20 har ±0,5°C i noggrannhet över temperaturområdet, detta gör att upplösning bättre är 0,5°C är meningslöst.
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

Inlägg av Lullen »

Okej det med float kan jag lätt ändra men problemet kvartstår fortfarande då den ändå ska klara float. Sen behöver jag inte direkt 0.0625 upplösning men avrundar man till 0.5 så kommer temperaturen att visa fel med ännu mer än 0.5, om vi har att temperaturen är 20.62 så kan jag tempen vara allt mellan 20.12-21.12 men har jag 0.5 så kommer jag hamna på 20.00, 20.50 eller 21.00. Så det blir ändå nogrannare eller tänker jag fel?
Men men det spelar egentligen ingen roll då det inte påverkar koden o varför den inte fungerar
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Nu kommer jag inte ihåg hur de två bytes:en från DS1820 är uppbyggda, så jag vet inte vad som ska göras. Men jag tror jag har hittat lite allmänna C-fel.


> unsigned btemp;

unsigned vadå? Du måste ange en datatyp också.


> int mask

Varför int? uint8_t borde vara mer lämpligt.


> mask = 00001000;

Menar du inte mask = 0b00001000 ?


> mask >> 1;
> add/2;

Dessa gör ingenting. Du vill nog ha "mask >>= 1" och "add /= 2" (eller "add >>= 1")


Som sagt vet jag inte om din metod för att omvandla till float är korrekt. Har du kollat i appnotes från Maxim? Jag vet att det finns en hel del C-kod där som kan hjälpa.
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

Inlägg av Lullen »

I ett exempel från mikroC så använder dom bara unsigned så jag antog att det skulle vara rätt, sedan har jag faktiskt ingen aning om vad det är heller.

Jo mask = 0b0001000 ska det nog vara, men borde inte mikroC reagera på binära tal som den gör med decimala och hexadecimala? Letade förut efter syntaxet för binär men hittade aldrig det utan bara för hex.

Började ta bort floats och byta till int(vad är det för skillnad på uint8_t?) och genast när jag ändrat temp och add till int så fungerar det! Gillar verkligen inte mikroC, ger så skumma felmeddelande.

Eftersom jag inte har chansen att testa koden(mina reservdelar till wispen skickas på måndag) så är det lika bra att fråga varför du inte tror att min omvandling är rätt? Bytsen från DS18B20 ser ut på detta sett:
MSB: S S S S S 2^6 2^5 2^4
LSB: 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4

Så jag kollar bara upp om 2^6 är 1 och isf adderar 64, sedan går jag till nästa bit, borde väl inte vara några problem?

Vad S:en exakt står för har jag ingen aning om, men de används när det är minusgrader vilket jag inte behöver kolla upp

Edit: Om jag nu skriver allt som int, när jag ska skriva ut det på LCDn så vill jag ju gärna ha decimaltal. Så då är frågan finns det typ någon left() funktion till PIC?
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

De µC jag har jobbat med och där jag har kollat på float ska man alltid initiera float-paketet med ett systemkall.

Och sedan börjar jag förstå lite av dina problem: du skiljer på binäre, decimala och hexadecimala värden... varför?

Att notationen skiljer sig, javisst men EN BYTE ÄR EN BYTE för en µC, inget annat!

Och sedan lite C-kompiler:
"unsigned" utan typnamn likställas med "unsigned int".
"uint8_t" är en AVR/GCC-grej, ska man ange en unsigned byte i ANSI C ska man använda "unsigned char".

Jag har jobbat med en DS18S20 för att mäta temperatur, jag höll mig till 0,5°C upplösning och det enda jag gjorde med datan efter att ha läst dom var att sätta MSB rätt om det var minusgrader.

Att värdet sedan angavs i 0,5°C (21 = 10,5°C) var en bisak, det fungerar alldeles utmärkt ändå.

Jag skulle vilja föreslå att du stegar upp temperaturen så att t.ex. 210 ska läsas 21,0°C, gör det som en integer (16 bit med förtecken), då kan du även läsa negativa temperaturer.
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Inlägg av mri »

"duplicated labels JMPSETFOV32"

mikroC har jag aldrig använt, men det där meddelandet ser ut som en internt genererad label av c-kompilatorn, som inte blev till korrekt assembler kod, vilket assemblern nu klagar på. Orsaken kan vara att du använder float, men inte har satt de rätta kompilerings-switcharna eller dyl. FOV32 i JMPSETFOV32 skulle kunna indikera att just den labeln har att göra med float...
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

Inlägg av Lullen »

Skiljer på binära, decimala och hexadecimala?

Har nu ändrat så att jag inte har float någonstanns i programmet längre. Och det allt går igenom kompileringen i alla fall, men jag har suttit o kollat länge på mikroCs exempelkod nu och förstår inte vart dom gör om det binära talet till decimal. Eller går det bara att ta 0b1001 + 9 och få ut 18? Verkar lite skumt om det gick eller är kompilatorn så smart(iof så ändras ju allt till binärt/hex)

Tar och kopierar in koden här.

Kod: Markera allt

void Display_Temperature(unsigned int temp2write) {
  const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
  char temp_whole;
  unsigned int temp_fraction;

  // check if temperature is negative
  if (temp2write & 0x8000) {
     text[0] = '-';
     temp2write = ~temp2write + 1;
     }

  // extract temp_whole
  temp_whole = temp2write >> RES_SHIFT ;

  // convert temp_whole to characters
  if (temp_whole/100)
     text[0] = temp_whole/100  + 48;

  text[1] = (temp_whole/10)%10 + 48;             // extract tens digit
  text[2] =  temp_whole%10     + 48;             // extract ones digit

  // extract temp_fraction and convert it to unsigned int
  temp_fraction  = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;

  // convert temp_fraction to characters
  text[4] =  temp_fraction/1000    + 48;         // extract thousands digit
  text[5] = (temp_fraction/100)%10 + 48;         // extract hundreds digit
  text[6] = (temp_fraction/10)%10  + 48;         // extract tens digit
  text[7] =  temp_fraction%10      + 48;         // extract ones digit

  // print temperature on LCD
  Lcd_Out(2, 5, text);
}//~
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Inlägg av mri »

"Eller går det bara att ta 0b1001 + 9 och få ut 18?"

0b1001 är en heltalskonstant (int eller möjligen char) med värdet 9. (för övrigt är binära konstanter som 0b1001 inte standard C men verkar stödas av diverse microcontroller kompilatorer)
9 är en heltalskonstant (int) med värdet 9.
0b1001+9 räknas ut vid kompilering och är också en heltalskonstant (int) med värdet 18.

18.0 däremot är en flyttalskonstant (float), eller egentligen är det double konstant och 18.0f float konstant, men jag vet ju inte hur pass mikroC följer C standarden.
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

Inlägg av Lullen »

Okej, nu vart det lite snurrigt uppe i mitt huvud. Klart jag förstår att 1001 är samma sak som 9 men det känns tokigt att man bara kan ändra så enkelt.

Så om vi säger att vi har denna raden(från exemplet):
// extract temp_whole
temp_whole = temp2write >> RES_SHIFT ;

då kan jag under bara ta
minTemp = temp_whole;

och sedan använda minTemp hur jag vill tex:
if(minTemp == 20)
gör nått

fast nu kommer inte detta fungera för att dom sista fyra bitarna är decimaler, men annars tänker jag rätt?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> men borde inte mikroC reagera på binära tal som den gör med decimala och hexadecimala?

Det gör den säkert, men 00001000 är *INTE* ett binärt tal !!
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

Inlägg av Lullen »

Det var inte så jag menade med reagerade utan, skriver man "23" så blir texten grön, "0x21" så blir den ljusblå men inte nått sånt med "0b1010"
Vad menar du med att det *INTE* är ett binärt tal? Anledningen till att jag har det talet är för att komma åt just den 4e biten och kolla om det är en etta eller inte. Var så jag fick förklarat för mig i skolan i alla fall att man skulle göra.

Men nu tror jag att jag förstår mig på mikroC exemplet så kan jag lika gärna använda det, det var anledningen till att jag inte använde deras exempel. Känns fel att att fuska genom Copy & Paste då jag aldrig kommer kunna felsöka den koden.

Men om vi tar ett exempel till så att jag är med 100% i koden:
32<<= 2 blir 3200 som om det skulle vara ett binärt tal?
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Inlägg av mri »

"Det var inte så jag menade med reagerade utan, skriver man "23" så blir texten grön, "0x21" så blir den ljusblå men inte nått sånt med "0b1010""

Textens färg är ju bara editorns "syntax highliting" och tydligen vet inte just din editor att 0b1010 är en konstant i din kompilator. Vilket inte är så konstigt eftersom detta sätt att skriva en konstant inte är standard. I standard C kan man skriva decimalt (2341), oktalt (02341) och hexadecimalt (0x4FA21), men inte binärt.

00001000 är alltså en oktalt tal, en konstant.

"32<<= 2" är inte giltig C kod. 32 << 2 är giltig kod och betyder vänsterskifta heltalet 32 med två steg, resultatet blir heltalet 128.

Jag rekommenderar att du skaffar en nybörjarbok på C, du verkar lite förvirrad på flera grundläggande punkter.
Lullen
Inlägg: 140
Blev medlem: 16 oktober 2006, 17:37:32

Inlägg av Lullen »

Jo jag är nybörjare på PIC men i dom C böcker(dator) jag läst har jag aldrig stött på "<<" eller att omvandla mellan olika talsystem. Används mest i µC kan jag tänka mig och en C-bok för µC skulle jag gärna ha men har varit på biblan o har inte hittat något, alla är assembler. Skulle någon ha en sådan över som vill säljas så är jag en möjlig köpare!

Edit: Kom att tänka på en sak ang nogrannheten på tempsensorn, är det ett fast fel den har för en viss temperatur tex vid 20 grader visar den alltid 20.3?
danei
EF Sponsor
Inlägg: 27464
Blev medlem: 2 juni 2003, 14:21:34
Ort: Östergötland
Kontakt:

Inlägg av danei »

Det står nog i databladet. Om du fixar så att man slipper skrolla i sidled så kanske fler orkar läsa tråden.
Skriv svar