Vindmätare. Programmering mikroC.

Planering och tankar kring eventuella framtida projekt.
Seqius
Inlägg: 11
Blev medlem: 25 april 2008, 21:02:01
Ort: Göteborg

Vindmätare. Programmering mikroC.

Inlägg av Seqius »

Hej. Är ny här på forumet och har tittat endel på andra pojekt och fått en del mycket bra ideér :)
Jag och en kompis ska nu bygga en vindmätare som projektarbete. Så efter lite efterforskningar om mikrokontroller så har jag nu köppt en pickit2 med 16F690. Har även lyckats koppla ihop den med en LCD display som ska visa resultatet från vindmätaren.
Vindmätaren ska avläsas med ett tungelement och mikrokontrollen ska då räkna varven på en viss tid. Antar att jag måste koppla in en kristall för att tiden ska fungera?

Eftersom jag inte har någon erfarenhet av assembler så hade jag tänkt skriva koden i mikroC.
Problemet är att jag inte riktigt vet hur jag ska skriva koden för inkopplingen med tungelementet. Har läst om någon interupt funktion i databladet men jag vet inte riktigt hur det fungerar. Så nu undrar jag bara om det är någon som har gjort något liknande projekt som jag kan få ta del av? Har läst lite på forumet om andra som gjort bvindmätare/hastighetsmätare o.s.v. Men jag har aldrig sett någon exempelkod på hur det är inkopplat.

Är väldigt tacksam för alla svar.
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Har även lyckats koppla ihop den med en LCD display som ska visa resultatet från vindmätaren.

Menar du bara "koppla" eller får du även ut text på den ?

> Vindmätaren ska avläsas med ett tungelement

Är det en sådan där roterande sak med "skopor" på 3 eller 4 armar ?
Spontakt låter mekaniska tungelement lite för "mekansikt". Kanske
en skiva med en optiskt avläsning skulle fungera bättre.

> Antar att jag måste koppla in en kristall för att tiden ska fungera?

Var menar du med "tiden" ?
Det hela beror på vilken precision ni behöver. Om du tar något
lite mer modern än en 690'a så har du en 1% intern oscillator (INTOSC)
som antagligen räcker gott för att mäta vindstyrkan.

> Eftersom jag inte har någon erfarenhet av assembler så hade jag tänkt skriva koden i mikroC.

Det är ingen bra orsak till att välja C. Ni kommer att få stora problem...

> Problemet är att jag inte riktigt vet hur jag ska skriva koden

Det kan till viss del bero på att ni hoppar över assembler.

Det här är ett så pass litet projekt, så det finns ingen anledning att
inte köra med assembler. Dessutom lär ni er mer samtidigt.

> Har läst om någon interupt funktion i databladet men jag vet inte riktigt hur det fungerar.

Det står i databladet !!

> Så nu undrar jag bara om det är någon som har gjort något liknande projekt som jag kan få ta del av?

Var det inte *erat* projektarbete ? Då ska ni väl inte kopiera någon annan ?

> Är väldigt tacksam för alla svar.

Inge orsak.
Men *lite* bättre får ni nog försöka...
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Inlägg av Micke_s »

Kristall lär du inte behöva för lite vindmätning.

kodandet har jag ingen kod till, men i princip

ha en timer (8bit) som tidsbas och räkna upp en variabel på 24bitar t.ex vid overflow.

för få aktuell tid så tar 24bitarna bitshift 8ggr + timer count registret.

vid varje ändring på interruptpinnen så läser du av skillnaden jfm förra gången och sparar undan nuvarande.

pseudokod

Kod: Markera allt

//timrar, interrupt osv får du läsa i databladet hur du får igång
//microC har väl exempel på timer och interrupt.
volatile unsigned int timerXhigh=0;
volatile  unsigned int lastreading;

unsigned int gettimer(){
   return timerXhigh<<8 + timerCntReg;
}

isr(timerX){
timerXhigh++
}

isr(pinchange){
   static unsigned int last;
   if(pinlow(sensepin)){ //reagerar bara när tungelementet är slutet mot jord, ha en pull-up här.
       lastreading = gettimer() - last;
       lastreading = gettimer(); //sparar undan nuvarande tid
   }
}

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

Inlägg av Icecap »

Välkommen till forumet först och främst.

Och sedan bara lite klarheter: man ska göra "samma jobb" oavsett om det är i C eller ASM, det skiljer bara "lite" i hur man skriver det.

Sedan till din fråga:
Tanka hem databladet för den valda PIC först (eller använd CD'n som följde med, jag har också samma kit.

Man kan göra mätningen på många sätt men jag har aldrig gillat att mäta antal pulser över en viss tid när det rör sig om långsamma förlopp, mättiden blir så helsikes lång om man ska ha någon form av precision.

Kolla i databladet under "CCP" eller "Capture/Compare/PWM" enheten, med den kan du mäta tiden mellan 2 pulser ganska exakt, vill du ha det helt rätt kopplar du till ett kristall med tillhörande lastkondensatorer.

Rätt utförd kan mjukvaran sortera bort för korta tider som kan uppstå med kontaktstuds i sensorn, då släpper du avstörningskondensatorer osv.

Om du kopplar tungelementet mellan GND och en portpinne (gärna CCP1) och kopplar ett motstånd (4,7-10K kanske) mellan VDD och samma pinne blir det bra, då kommer den att växla när mätaren roterar.

Hela idéen är då att man får en "tidstämpel" från CCP-enheten om den ställs i "Capture-mode".

Om man sedan tänker såhär:
#define MAX_OVERFLOWS 10 // Bara ett tal, räkna fram rätt senare

"Pulstid" = "Tid nu" - "Förra tidstämpel";
och om "Pulstid" är för kort (kontaktstuds) hoppar man bara vidare men är tiden "lång nog" går man vidare, annars hoppar man förbi:
"Förra tidstämpel" = "Tid nu"; // Klar till nästa puls
if(Overflows < MAX_OVERFLOWS) Hastighet = Konstant / "Pulstid";
Overflows = 0; // Nolla overflow-räknaren, se nedan

Ovanstående utförs av interruptrutinen som hör till CCP-enheten.

Till detta kan det vara vettigt att hålla koll på om timern som är grunden i CCP-tidstämplinger har Overflow, om man räknar hur många overflow utan puls kan man nolla värdet på det vis.
Då CCP använder Timer1 till att tidstämpla kan man lägga till att den ska avkänna Timer1 overflow och låta den utlösa en interrupt.

i den ISR (Interrupt Service Routine) låter man helt enkelt en räknare räknas upp:
if(Overflows < MAX_OVERFLOWS) Overflows++;
else Hastighet = 0;

På det vis har du time-out om det inte kommer pulser inom lagom tid (= 0 i vindhastighet) och när första pulsen kommer efter en time-out ger den fortfarande noll men sedan räknar den rätt.

Om du sedan vill räkna ett snitt osv. kan du göra det.
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Tidigare råkade jag skriva :

> Om du tar något
> lite mer modern än en 690'a så har du en 1% intern oscillator (INTOSC)

Även 690'ian har en 1% INTOSC, så då borde ni inte behöva någon
kristall till den. Blir lite enklare att bygga och lite driftsäkrare...

För övrigt så har ni redan fått stora delar av erat projektjobb gjort här
ser jag. Inte riktigt så som jag anser att skoljobb ska göras...
Seqius
Inlägg: 11
Blev medlem: 25 april 2008, 21:02:01
Ort: Göteborg

Inlägg av Seqius »

Är väldigt tacksam för alla svar och förslag på förbättringar. Jag ska överväga att göra programmeringen i assembler istället.

Era svar var väldigt mycket till hjälp. Tack så mycket! :)
Nu återstår det att fortsätta läsa, prova, läsa.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Inlägg av jesse »

Håller med det sista som Sodjan sade.

Bäst i det här läget är kanske att diskutera vilka grundförutsättningar man jobbar med samt några formler / idéer som studenterna sedan själva får omsätta i kod. Det har diskuterats varvtalsmätning i flera trådar innan på det här forumet med ganska detaljerade funderinger kring hur man kan / bör göra.
Seqius
Inlägg: 11
Blev medlem: 25 april 2008, 21:02:01
Ort: Göteborg

Inlägg av Seqius »

Hej. Nu har vi kommit en bit med vårt arbete. Det var en mycket bra ide' med CCP enheten så det tackar vi för :)

Men har nu kommit till ett problem. CCP enheten använder bara RC5 om jag har fattat databladet rätt. Och jag använder RC5 till LCD displayen. Men då tänkte jag att det måste ju gå att bara ta en annan port istället så att inte displayen behöver RC5?
Vi programmerar i mikroC och enligt den manualen tycker jag att man borde kunna göra så här?

void main(){
ANSEL = 0;
ANSELH = 0;
PORTC = 0;
PORTB = 0;
Lcd_Config(&PORTC,7,6,4,3,2,&PORTB,5);
Lcd_Cmd(LCD_CLEAR);
Lcd_Cmd(LCD_CURSOR_OFF);
delay_ms(500);
Lcd_Out(1,1,"Test");
}

Borde det inte gå att göra så? För det går väl att använda olika portar för att skicka data till displayen?

Tacksam för alla svar och kommentarer.
Användarvisningsbild
Icecap
Inlägg: 26637
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Nu gör ni precis det som ogillas: ni använder rutiner som INTE är C-standard, ni har alltså inte ett skvatt kontroll på VAD de gör.

Jag använder MikroC också, jag har dock ALDRIG använd några av dessa rutiner med att ställa serieport, kommunicera, styra LCD osv. då jag inte har dokumenterat exakt vad de gör.

Detta betyder i mitt fall att jag varken kan eller vill svara på frågan, dels för att jag inte ids läsa igenom dokumentationen och dels för att jag anser att det är dålig stil att använda färdiga rutiner som ni ju tydligen inte vet vad gör.
Seqius
Inlägg: 11
Blev medlem: 25 april 2008, 21:02:01
Ort: Göteborg

Inlägg av Seqius »

Okej jag förstår vad du menar. jag skulle gärna strunta i att använda de färdiga funktionerna om jag visste hur man gör annars?? Vet du någon bra sida eller något där det står exempel på hur man kan göra för att skriva ut något till displayen från olika portar? Det står väl inte i databladet för pic 16f690?
Användarvisningsbild
Icecap
Inlägg: 26637
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Kolla t.ex. på sodjans hemsida
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> där det står exempel på hur man kan göra för att skriva ut något till
> displayen från olika portar? Det står väl inte i databladet för pic 16f690?

Ja och nej.

Databladet för (t.ex) en PIC beskriver hur man hanterar en *PIC*.

Databladet för en LCD display beskriver hur man hanterar just en *LCD display*.

Sedan får man kombinera det hela till en fungerande helhet.
Och resultatet kan bli ungefär som den sida som Icecap syftade på:
http://www.jescab.se/HD44780.html
I det fallet skrivet i assembler, men principen är densamma oavsett "språk".

När det gäller frågor kring hur olika färdiga funktioner i MikroC fungerar
(som t.ex Lcd_Config) så borde manualen till MikroC beskriva det.

I just det fall som du postade så ser det ut som om du har försökt
köra LCD_Config med samma parametrar som LCD_Custom_Config.
Varför du gör det är oklart och det vet du bara själv. Kanske har du
bara missförstått manualen (ganska OK), eller så är det bara slarv,
vilket bara är, tja, slarvigt...
Seqius
Inlägg: 11
Blev medlem: 25 april 2008, 21:02:01
Ort: Göteborg

Inlägg av Seqius »

Tack för ditt svar. http://www.jescab.se/HD44780.html den sidan gjorde det mycket lättare att förstå :)
Seqius
Inlägg: 11
Blev medlem: 25 april 2008, 21:02:01
Ort: Göteborg

Inlägg av Seqius »

Nu går det lite bättre men allt verkar inte fungera som jag vill tyvärr.
Men databladet har fler lösningar än man först kunde tro.
Bara att det är svårt att fårstå utan några förkunskaper innan.
Men här är i alla fall min kod för hur jag har förstått.
Den är inte helt klar dock. Hoppas jag inte är helt ute och cyklar :lol:



#define LCD_E RC3 //Räcker det att skriva såhär eller är det
#define LCD_RS RC2 // något som saknas?
#define LCD_D4 RC4
#define LCD_D5 RB5
#define LCD_D6 RC6
#define LCD_D7 RC7

void main(void)

{
unsigned int T, t1, t2,hastighet;

initserial();


ANSEL = 0;
ANSELH = 0;
PORTC = 0; /*Frågan är om det blir fel när man sätter RC5 som utport */
PORTB = 0; /*senare?*/
Lcd_Cmd(LCD_CLEAR);
Lcd_Cmd(LCD_CURSOR_OFF);
delay_ms(500);

TRISC.5 = 1; /* CCP1-pin (RC5) är utport */

T1CON = 0b00.00.0.0.0.1 ;

CCP1CON = 0b00.00.0101 ; /*Sätter ccp1 i capture mode*/

while(1)

{

CCP1IF = 0 ; /* Flaggan till noll */

while (CCP1IF != 0 ) /* Vänta på capture */
{
t1 = CCPR1H*256;/* Här lite oklart om man kan göra så här för */
t1 += CCPR1L; /* att få ihop de två registrena till ett 16 bitars tal*/
}

CCP1IF = 0 ; /* Flaggan till noll */

while (CCP1IF != 0 ) /* vänta på nästa capture */
{
t2 = CCPR1H*256;
t2 += CCPR1L;
}

/* Uträkningar */

T = t2 - t1; /* Peroioden för ett varv */
// hastighet="konstant"/T (har inte räknat ut vad det ska vara ännu);

Lcd_Out(1,1," Tid: ",T);
// Lcd_Out(1,2," Hastighet: ",hastighet);
delay( 500 ); //kortare delay. 500 för att se att det fungerar

}

}
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Jag ser inget LCD "config" anrop alls ?
Det kanske inte behövs...
Skriv svar