Enkel hastighetsmätare (programmeringsproblem)

Elektronikrelaterade (på komponentnivå) frågor och funderingar.
joakimholmberg
Inlägg: 18
Blev medlem: 27 januari 2009, 14:45:59

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av joakimholmberg »

Okej.
Men då skall jag alltså försöka skriva ut till LCD:n utan att använda den färdiga funktionen " LongToStr()"? För det är väl den som förstör allt antar jag?
För att lösa detta tänkte jag att det kanske går att använda en pekare för att göra en egen omvandling från long till char. Men problemet kanske kvarstår. Eller du kanske har någon bättre idé för att lösa detta?
Jag är väldigt tacksam för att du har tagit dig tid till att svara och förklara alla mina frågor. :)
Jag har lärt mig oerhört mycket på dina inlägg :tumupp:


Kod: Markera allt

#define false 0
#define true  1

typedef unsigned char byte;
typedef unsigned int  word;
typedef unsigned long dword;
unsigned long hastighet=0;
char svar[12];
typedef union
  {
  word Word;
  byte Byte[2];
  } T_W_AND_B;

typedef union
  {
  dword DW;
  word  WO[2];
  byte  BY[4];
  } T_ALL_ACCESS;

T_ALL_ACCESS Pulse_Now;
T_ALL_ACCESS Pulse_Previous;
byte Overflow;dword Difference;

struct
  {
  byte Running : 1;
  byte Update  : 1;
  byte Timeout : 1;
  } Flag;

void interrupt(void)
  {
  if(PIR1.TMR1IF)
    { 
    PIR1.TMR1IF = false; 
    Overflow++;
      if(Overflow > 20) Flag.Timeout = true;
    }
  if(PIR1.CCP1IF)
    { // Pulse came on Capture
    if(!Flag.Update)
      {
      Pulse_Now.BY[0] = CCPR1L; 
      Pulse_Now.BY[1] = CCPR1H; 
      Pulse_Now.BY[2] = Overflow;
      Overflow = 0;
      Flag.Update = true;
      }
    PIR1.CCP1IF = false;
    }
  }

void main(void)
  {
  CCP1CON      =  0x04; 
  PIE1         =  0x05; 
  PIR1         =  0x00;
  INTCON       =  0xC0; 
  T1CON        =  0x31;
  Flag.Running = false;
  Flag.Update  = false; 

ANSEL = 0;
ANSELH = 0;
PORTB = 0;
TRISC=0x20;    

Lcd_Custom_Config(&PORTB,7,6,5,4,&PORTC,2,0,3);
Lcd_Custom_Cmd(LCD_CLEAR);
Lcd_Custom_Cmd(LCD_CURSOR_OFF);
delay_ms(1000);
        
  while(true)
    {
    if(Flag.Update)
      {
      Pulse_Now.BY[3] = 0; // If a 16 bit overflow counter is not needed
      Difference = Pulse_Now.DW - Pulse_Previous.DW;
      Pulse_Previous.DW = Pulse_Now.DW;
      Flag.Update = false; 

        hastighet = (0.65/Difference)*1000000;
        LongToStr(hastighet,svar);
        Lcd_Custom_Out(1, 1, "Hastighet: ");
        Lcd_Custom_Out(2,1, svar );
        }
    if(Flag.Timeout)
      {
        Lcd_Custom_Out(1, 1, "Hastighet: ");
        Lcd_Custom_Out(2,1, "0          " );
        Flag.Timeout = false;
      }
    }
  }
Mvh Joakim
Användarvisningsbild
Icecap
Inlägg: 26962
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av Icecap »

Ah... då ser man vad du gör fel direkt...

Allt är med heltalsräkning så.... hur kan du göra detta???:
hastighet = (0.65/Difference)*1000000;
I heltalsräkning finns det INGEN decimaler.

Du kan istället skriva den som:
hastighet = (WORD)650000 / (WORD)Difference);

Testa om detta ger något resultat.
joakimholmberg
Inlägg: 18
Blev medlem: 27 januari 2009, 14:45:59

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av joakimholmberg »

Hej!
Tack än en gång. Nu verkar det som att det fungerar och jag ska ta och skriva en medelvärdesalgoritm.
Det verkar alltså som det fungerar nu, värdena är stabila och positiva i rätt storlek. Men vad gör egentligen det du skrev med (WORD) innan?

Tack Mvh
Joakim
Användarvisningsbild
Icecap
Inlägg: 26962
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av Icecap »

(WORD) är en "cast" där man berättar för kompilern att det värde ska uppfattas som en WORD som är en 16-bit utan förtecken. Detta betyder också att "Difference" bara uppfattas som de understa 16 bit fastän det är en 32-bit variabel.

Att "cast"a kan vara mycket viktigt ibland och man kan egentligen aldrig cast'a för mycket.

Har man t.ex. en block med olika värden (t.ex. inställningar som sparas i/hämtas ifrån EEPROM) kan man ibland behöva "komma åt dom" som bytes (t.ex. "hämta buffer från EEPROM" eller "spara buffer i EEPROM", extremt aktuellt) och istället för att fibbla en massa kan man skriva:
Save_Buffer_2_EEPROM(StartAddress, (BYTE*)&Config, sizeof(Config));
"Config" är alltså en samling data som ska sparas/hämtas.
"StartAddress" är ett tal som anger var i EEPROM'en man ska starta.
"sizeof(Config)" blir under kompileringen ett tal som anger hur många bytes "Config" behöver.

Det knepiga är "(BYTE*)&Config" som betyder:
"&Config" är adressen till "Config" och "(BYTE*)" cast'er den till att vara en 'pekare till unsigned char', alltså blir den plötsligt inte en pekare till en variabel av typen 'Config' men istället anses adressen vara en byte-adress. Då jag har "cast"at detta betyder det för kompilern att jag faktisk är medveten om vad jag gör, detta gör C till ett mycket starkt språk... samtidig som det gör att man kan göra bort sig rejält på detta vis!
joakimholmberg
Inlägg: 18
Blev medlem: 27 januari 2009, 14:45:59

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av joakimholmberg »

Hej.
I interruptrutinen ingår följande. För att få det korrekta värdet måste man väl multiplicera overflow med timertiden det tar för ett overflow? Är informationen från ccp registren binärt eller måste man räkna om de för att kunna lägga till overflow?

Kod: Markera allt

 Pulse_Now.BY[0] = CCPR1L;
      Pulse_Now.BY[1] = CCPR1H;
      Pulse_Now.BY[2] = Overflow;   
timern räknar med 125kHz. Då tar ett overflow ca 0,5s.
Ska man då skriva såhär: overflow*tid för ett overflow(mikro sekunder)?

Mvh Joakim.
Användarvisningsbild
Icecap
Inlägg: 26962
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av Icecap »

Overflow räknas upp med 1 varje gång Timern gär från 0xFFFF -> 0x0000 och då den ligger där den gör är den AUTOMATISK placerat rätt om man använder hela talet som en 32-bit variabel. Placeringen i sig ger alltså "multiplikationen".

Och vad menar du med om informationen från CCP-registern är binär? Den information man läser är ett 16-bitars värde mellan 0x000 och 0xFFFF och ska inte räkna om på något vis.

Om pulserna "aldrig" kommer med kortare intervall än 0,5 sek behövs hela overflow och 32-bit matten inte, då kan allt klaras med 16-bit matematik men du har ju aldrig definierat om det är så eller inte.
joakimholmberg
Inlägg: 18
Blev medlem: 27 januari 2009, 14:45:59

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av joakimholmberg »

Okej. Då förstår jag varför det inte fungerade. Ibland kommer pulserna med kortare intervall än 0,5 sekunder. behöver jag då en 16-bitars variabel på overflow räknaren? Om det går snabbare än 0,5s så används väl inte overflow variabeln? Då borde det väl inte ha någon betydelse?

mvh Joakim
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Re: Enkel hastighetsmätare (programmeringsproblem)

Inlägg av v-g »

Det du gör är att när du får interupt för att timern slagit runt UTAN puls så ökar du på en eller flera variabler.
Skriv svar