Sida 1 av 1
Vill göra en varvräknare av PIC...
Postat: 27 november 2007, 17:43:39
av dadde
Som vanligt har jag många ideer men den här gången har jag tagit mig lite vatten över huvudet;
Jag kan nämligen nästan ingenting om PIC:ar
Dock är jag lite kunnig innom språket C++ vilket jag antar är likt C?
Jag kan iaf lite av grunderna
Jag hade iaf tänkt mig göra en varvärknade med en PIC16F628, en hallgivare och typ 10 lysdioder.
En magnet kommer placeras på grejen jag ska mäta varvtalet och hallgivaren kommer då sitta och ge en puls/varv.
Varvtalen som jag vill mäta är ca 1500-2500 varv/minut vilket inte borde vara några problem.
En antalet varv överträffar 1500 rpm så skall den första lysdioden tändas och sedan en lysdiod/1000varv upp till 2500.
Problemet är att jag inte har en aning om hur man skall skriva programmet;
måste man definera in/utgångarna på något sätt?
Hur får jag en räknare att trigga när hallgivaren ger en puls?
Hur får jag PIC:en räkningen att resetta sig efter en viss tid för att sedan ränka ut hur många varv det blir / minut?
Hur får jag PIC:en att tända lysdioder på utgångarna?
Finns det någon smidig guide för nybörjare?
Har letat som en galing men har inte hittat något vettigt :/
Postat: 27 november 2007, 18:01:20
av RasmusB
Finns massor om du googlar runt lite.
Däremot skulle jag rekommendera att du börjar programmera i assembler i början, det blir lättare att förstå vad som händer då.
Vill också rekommendera en djupdykning i databladet till processorn, där finns det allra mesta du behöver veta
Lycka till!
Postat: 27 november 2007, 18:08:05
av EEPROMdanne
EDIT: Hittade en länk...Var det något sånt här du menade?
http://www.jetronic.se/Led_varvraknare.htm
Postat: 27 november 2007, 19:16:08
av Icecap
Att lösa problemet är inte så svårt men först steg först: GLÖM C++!!!
Jag kör själv C++, ANSI C, assembler osv. och till detta är det assembler som gäller.
På en PIC finns det en CCP-enhet, den kan fånga "händelser" (pulser) i tid vid att en räknare kör på med inställd frekvens och Capture-enheten sparar "tiden" i ett register när det kommer en (valfri) flank på en ingång.
Då vet du tiden mellan 2 pulser:
Tid_mellan_pulser = Tiden_Nu - Tiden_Då;
Sedan kopierar man ner såhär:
Tiden_Då = Tiden_Nu;
då kommer den att vara klar till nästa puls.
Sedan kan du köra en helt vanlig:
if(Tid_mellan_pulser < X1) Tänd_LED1;
else Släck LED1;
if(Tid_mellan_pulser < X2) Tänd_LED2;
else Släck LED2;
osv. osv.
X1 och X2 (och X...) är konstanter du räknar ut baserat på räknefrekvensen osv. Timern ger interrupt vid overflow, den kan du använda till att utöka räknarens antal bits vid behov.
Postat: 27 november 2007, 20:07:59
av xobx
Snor tråden lite,
kan CCP-enhet användas på vilken IO pin som helst eller finns det en speciell för just detta?
Postat: 27 november 2007, 20:16:41
av eriikh
Det är (oftast) en speciell, titta i databladet.
Postat: 27 november 2007, 20:37:19
av bengt-re
Det är en eller två pinnar på 16F serien iaf, kanske har blivit mer spritt på nyare PICár, men på gamla goa 16F876A så är det RC1 och RC2 som är kopplade till CCP, men som sagt - läs databladet på den pic du tänkte använda.
Postat: 29 november 2007, 06:29:45
av dadde
Tack för hjälpen grabbar!
Har pluggat på databladet och börjat förstå hur jag skall gå tillväga...
Har börjat lite lätt att skapa ett program,
Får se var jag hamnar

Re:
Postat: 2 augusti 2012, 10:23:29
av SeniorLemuren
Icecap skrev:Att lösa problemet är inte så svårt men först steg först: GLÖM C++!!!
Jag kör själv C++, ANSI C, assembler osv. och till detta är det assembler som gäller.
På en PIC finns det en CCP-enhet, den kan fånga "händelser" (pulser) i tid vid att en räknare kör på med inställd frekvens och Capture-enheten sparar "tiden" i ett register när det kommer en (valfri) flank på en ingång.
Då vet du tiden mellan 2 pulser:
Tid_mellan_pulser = Tiden_Nu - Tiden_Då;
Sedan kopierar man ner såhär:
Tiden_Då = Tiden_Nu;
då kommer den att vara klar till nästa puls.
Sedan kan du köra en helt vanlig:
if(Tid_mellan_pulser < X1) Tänd_LED1;
else Släck LED1;
if(Tid_mellan_pulser < X2) Tänd_LED2;
else Släck LED2;
osv. osv.
X1 och X2 (och X...) är konstanter du räknar ut baserat på räknefrekvensen osv. Timern ger interrupt vid overflow, den kan du använda till att utöka räknarens antal bits vid behov.
Grävde fram denna gamla tråd, Eftersom jag nu står i begrepp att bygga ett par varvräknare till mina motorer så ställer jag frågan om det verkligen måste programmeras i assembler.
Jag har inte något emot assembler, men resultatet skall presenteras på en display som även är tänkt att visa temperatur och oljetryck. Rutinen för att visa tecken på displayen har jag redan skrivit i C så det vore klart mindre arbete om man kunde använda C. Jag tänkte använda en PIC 16F887 20 Mhz för ändamålet.
Re: Vill göra en varvräknare av PIC...
Postat: 2 augusti 2012, 10:41:12
av Icecap
Såklart måste man inte det - men kommer man med C++ i PC-miljö i bakfickan kommer det att vara nära nog den enda möjlighet att lösa detta utan att gå vilse i skillnaden mellan PC-med-extremt-med-resurser och mikroprocessor.
Rent faktisk har jag löst det du behöver till så vida att jag har färdiga "mäta tid"-rutiner osv.
Kod: Markera allt
#define RPM_CONSTANT xxx // Här ska man räkna lite, värdet beror på Timer1 frekvens. Se kommentar vid T1CON.
struct
{
union
{
unsigned char Byte[2];
unsigned int Word;
} Start;
unsigned int Previous, Difference;
unsigned int RPM;
} Pulse;
void interrupt(void)
{
if(PIR1.CCP1IF)
{
if(CCP1CON.CCP1M0) // If capturing rising edges
{
Pulse.Start.Byte[0] = CCPR1L; // Transfer the value, low byte
Pulse.Start.Byte[1] = CCPR1H; // Transfer the value, high byte
}
PIR1.CCP1IF = false; // Acknowledge interrupt
Pulse.Difference = Pulse.Start.Word - Pulse.Previous; // Calculate the difference
Pulse.Previous = Pulse.Start.Word; // Save for next time
}
}
Initiera CCP:
void Initialize_CCP(void)
{
TRISA = 0xEF; // All input but PORTA.4
TRISB = 0x08; // All output but PORTB.3
CMCON = 0x07; // No comparator inputs
CCP1CON = 0x05; // Set CCP1 to capture all rising edges and use Timer 1 as timebase
PIE1 = 0x04; // Allow CCP1 interrupts
PIR1 = 0x00; // Erase any latent interrupts
INTCON = 0xC0; // Allow interrupts
T1CON = 0x31; // Måste ändras för rätt frekvens men då måste man veta maximal och minimal RPM först
}
main-Loop:
if(Pulse.Difference)
{
Pulse.RPM = RPM_CONSTANT / Pulse.Difference;
Pulse.Difference = 0; // Mark as used
}
// Nu innehåller Pulse.RPM värdet för RPM hela tiden.
// Man kan lägga in en timeout så att om motorn stoppas visas 0 RPM
Detta är saxat ur ett gammalt projekt och kan behöva fräschas upp lite men grunden är den samma:
I interrupt-rutinen:
* Fånga tiden för varje puls.
* Subtrahera tiden för den förra tiden för att få fram skillnaden.
* Spara den senaste tiden som "förra tiden".
I main-loop'en:
* Om skillnaden är icke-noll är det mätt en tid.
* Räkna då vilket RPM det motsvarar vid att ta en konstant och dela med tiden för skillnaden, nolla sedan skillnaden för att markera den som klar.
Då kan man skriva ut Pulse.RPM hela tiden om man vill.
Själva RM-uträkningen kan såklart utföras i själva interrupt-rutinen om man vill, det beror helt på processorkraft och vad som behövs.
Re: Vill göra en varvräknare av PIC...
Postat: 2 augusti 2012, 10:47:49
av sodjan
> Grävde fram denna gamla tråd,
Nu har jag inte kollat alla detaljer i tråden men jag ser att det i början
talas om en PIC16F628, vilket *idag*, "5 år senare...", är lite "dated".
Det har hänt mycket på processorsidan under den tiden. En standard
processor ur t.ex 16F1xxx serien har betydligt mer resurser än 628'an.
Vad som också har hänt är t.ex att Microchip har köpt HiTech vilket
gör urvalet av utvecklingsverktyg något annorlunda ("bredare") idag.
Re: Vill göra en varvräknare av PIC...
Postat: 2 augusti 2012, 18:47:40
av SeniorLemuren
@sodjan. Jag har PICKIT2 och den klarar tydligen inte 16F1xxx serien. Skulle det vara bättre att gå på 18F2xx? Jag har några PIC 18F2550 liggandes, den finns med i listan som supportade av PICKIT2.
Jag hade från början tänkt att använda PIC16F877 men den har ju inte högre klockfrekvens än PIC16F628 så det är väl ingen stor vinning med det.
Jag tänkte använda en display som visar RPM, oljetryck, vattentemp, laddning och det kanske blir svårt att få PIC16F877 att räcka till?
@Icecap. Ett bra exempel som jag tar till mig. Kul att få lära sig
Den möjligheten har jag inte använt tidigare.
Re: Vill göra en varvräknare av PIC...
Postat: 2 augusti 2012, 20:50:40
av sodjan
> Jag har PICKIT2 och den klarar tydligen inte 16F1xxx serien.
Nja, inte från den integrerade "drivern" i MPLAB, men den fristående PICkit2
"applikationen" gör nog det. Sen kan man ställa in den så att den "flashar"
automatiskt så fort den finns en ny HEX fil, så det blir i princip som att köra
som vanligt i MPLAB.
http://www.microchip.com/stellent/idcpl ... e=en027813
(Se andra halvan av sidan...)
> Jag tänkte använda en display som visar RPM, oljetryck, vattentemp, laddning
> och det kanske blir svårt att få PIC16F877 att räcka till?
Nu så beror det ju lite på vad du tänker använda för "display", men om det är en
vanlig HD44780 text display eller en enkel grafisk med eget minne (så att den inte
behöver "refreshas" hela tiden) så ska det inte vara något problem. De saker du
vill visas ändras ju inte flera 100 gånger per sekund.
Re: Vill göra en varvräknare av PIC...
Postat: 2 augusti 2012, 21:28:03
av SeniorLemuren
Tanken var en vanlig text LCD 20x4
Re: Vill göra en varvräknare av PIC...
Postat: 2 augusti 2012, 21:30:54
av sodjan
OK. Den kan du uppdatera säkert 50-100 ggr/sek.
Men det lär ju inte behövas för att visa det du vill visa.