• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Converting timer value to speed in RPM

Status
Not open for further replies.

Cantafford

Member
Hey,

I'm trying to convert the value that I read from timer5 of PIC18f2431 into an RPM value. I have implemented the program in a way so the value that the TMR5 has reached since it started counting is read when input capture 1 of the PIC generates an interrupt when a hall sensor on the BLDC motor generates a change on that pin. Then I read this value, put it into the formula that will turn it into an rpm value then clear the value of the timer5 so I can get it again on the next IC1 interrupt.

Speed in RPM = (Operating Frequency/4) / (Timer5 Count x Timer5 Prescale x Number of Pole Pairs x 6) * 60
My operating frequency is 25Mhz.

This is the code:

Code:
if(IC1IF==1)
  {
   timercount = (TMR5H<<8)+TMR5L;
   speed = ( 6250000 / (timercount*4*6) ) * 60;
   TMR5H = 0; // reset
   TMR5L = 0; // timer5 value
   putrsXLCD("Speed: ");                     //Display "Temp is" on the screen
   sprintf(buf, "%g", speed );        //Convert temperature float value to string
   putsXLCD(buf);                             //Display the temperature on the screen
   putrsXLCD(" ");                            // Display "C" for Celsius
   putrsXLCD("RPM");                            // Clear after comma
   WriteCmdXLCD(0x02);                        //Home position on LCD
When I run this piece of code, this value is displayed on the LCD: "1.11606e+" and does not change no matter what the speed of the motor is.
I'm guessing I'm reading the contents of the TMR5 register wrong. Please help me correct this. Thanks.

This is the whole code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
#include <plib/delays.h>
#include <plib/xlcd.h>

#define FREQ 6250000

int HALL;
int HALLvalue[6] = { 0b00000101, 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100 };
unsigned int dch;
unsigned int dcl;

float timercount;
float speed;
unsigned char buf[20];

// Capture Interrupt Service Routine


void init_XLCD(void);       //Initialize LCD display
void DelayFor18TCY( void ); //18 cycles delay
void DelayPORXLCD (void);   // Delay of 15ms
void DelayXLCD (void);       // Delay of 5ms

void interrupt CheckHallValue()
{
  if(IC1IF==1)
  {
   timercount = (TMR5H<<8)+TMR5L;
   speed = ( 6250000 / (timercount*4*6) ) * 60;
   TMR5H = 0; // reset
   TMR5L = 0; // timer5 value
   putrsXLCD("Speed: ");                     //Display "Temp is" on the screen
   sprintf(buf, "%g", speed );        //Convert temperature float value to string
   putsXLCD(buf);                             //Display the temperature on the screen
   putrsXLCD(" ");                            // Display "C" for Celsius
   putrsXLCD("RPM");                            // Clear after comma
   WriteCmdXLCD(0x02);                        //Home position on LCD

   dch = ADRESH >> 2; // set the
   dcl = (ADRESL<<6) | ((ADRESL>>2) & 0x00) ; // duty cycle with the pot
   IC1IF = 0;
   ADON = 0;
  }

  IC2QEIF = 0; IC3DRIF = 0;
  HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state
  if(HALL == HALLvalue[0]) { OVDCOND = 0b00100100; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[1]) { OVDCOND = 0b00000110; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[2]) { OVDCOND = 0b00010010; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[3]) { OVDCOND = 0b00011000; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[4]) { OVDCOND = 0b00001001; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[5]) { OVDCOND = 0b00100001; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
}

void ConfigureADC()
{
  ADCON0 = 0b00000000; // single shot mode, single channel mode
  VCFG1 = 0; // VDD and VSS as ref
  VCFG0 = 0;
  ADCON2 = 0b00001000; // left justified, 2TAD, conversion clock: Fosc/2
  ADCON3 = 0b11000100;  // input capture 1 starts the a/d sequence!!(check here the first two bits)
  GASEL1 = 0; // select AN0
  GASEL0 = 0;
  ANSEL0 = 0b00000001;
}

void main()
{
 //OSCCON = 0b01001111; // frequency is 1Mhz
 ConfigureADC();
 SCS1 = 0; // use primary
 SCS0 = 0; // oscillator
 TRISA = 0b11111111; // PORTA is input(CAP's + POT)
 TRISB = 0b11000000;
 GIE = 1; // enable global interrupts
 GIEH = 1;
 PEIE = 1;

 // Initialize the Input Capture Module
 CAP1CON = 0b00000000; // disable input capture 1 module
 CAP1CON = 0b00001000; // enable input capture 1 module; interrupt on every state change

 CAP2CON = 0b00000000; // disable input capture 2 module
 CAP2CON = 0b00001000; // enable input capture 2 module; interrupt on every state change

 CAP3CON = 0b00000000; // disable input capture 3 module
 CAP3CON = 0b00001000; // enable input capture 3 module; interrupt on every state change

 // Enable Capture Interrupt and configure TMR5
 IC1IE = 1; // enable IC1 interrupt
 IC1IP = 1; // IC1 interrupt on high priority
 IC1IF = 0; // clear IC1 interrupt status flag

 IC2QEIE = 1; // enable IC2 interrupt
 IC2QEIP = 1; // IC2 interrupt on high priority
 IC2QEIF = 0; // clear IC2 interrupt status flag

 IC3DRIE = 1; // enable IC3 interrupt
 IC3DRIP = 1; // IC3 interrupt on high priority
 IC3DRIF = 0; // clear IC3 interrupt status flag

 PTCON0 = 0b00000000; // 1:1 postscale, 1:1 prescale, PWM in free-running mode
 PTCON1 = 0b10000000; // pwm time base is on, the time base counts up
 PWMCON0 = 0b01001111; // pwm0-5 configured as pwm output in independent mode
 SEVOPS3 = 0; // 1:1 postscale
 SEVOPS2 = 0;
 SEVOPS1 = 0;
 SEVOPS0 = 0;
 OSYNC = 1; //Output overrides via the OVDCON register are synchronized to the PWM time base(NOT SURE HERE)

 PTPERH = 0x0F; // frequency is 1.5Khz
 PTPERL = 0xFF; // 0xFF here

 T5CON = 0b01000011; // tmr 5 prescaler = 1:1
 PR5H = 0xFF;
 PR5L = 0xFF;

 init_XLCD();                    //Call the Initialize LCD display function
 OVDCOND = 0b00100100; // start(needs a change on input capture)
 PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
 OVDCONS = 0;

 while(1)
 {
     ADON = 1;
 }

}

void init_XLCD(void)                //Initialize LCD display
{
OpenXLCD(FOUR_BIT&LINES_5X7);       //configure LCD in 4-bit Data Interface mode
                                    //and 5x7 characters, multiple line display
while(BusyXLCD());                  //Check if the LCD controller is not busy
                                    //before writing some commands
WriteCmdXLCD(0x06);                 //Move cursor right, don't shift display
WriteCmdXLCD(0x0C);                 //Turn display on without cursor
}

void DelayFor18TCY( void )         //18 cycles delay
{
Delay10TCYx(20);
}
void DelayPORXLCD (void)           //Delay of 15ms
{
Delay1KTCYx(30);
}
void DelayXLCD (void)              //Delay of 5ms
{
Delay1KTCYx(10);
}
 

Jon Wilder

Active Member
It's actually best to set up one of the timers as a pulse counter, then sample the counter at a fixed time base.

On a V8 engine, you have 4 tach pulses per rotation of the crank. At a tach frequency of 53Hz, this translates as -

53Hz / 4 pulses per rotation = 13.25 rotations per second
13.25 RPS * 60 seconds = 795 RPM

On a 6-cylinder engine, you would have 3 pulses per rotation. On a 4-cylinder, you would have 2 pulses per rotation.

If you set up a timer as a counter and feed the tach signal into its TxCKI pin, the timer will count tach pulses. Then you can use a second timer to interrupt every 1/2 second, and sample the counter timer during this interrupt. Your RPM = counter value * 120.
 

Cantafford

Member
It's actually best to set up one of the timers as a pulse counter, then sample the counter at a fixed time base.

On a V8 engine, you have 4 tach pulses per rotation of the crank. At a tach frequency of 53Hz, this translates as -

53Hz / 4 pulses per rotation = 13.25 rotations per second
13.25 RPS * 60 seconds = 795 RPM

On a 6-cylinder engine, you would have 3 pulses per rotation. On a 4-cylinder, you would have 2 pulses per rotation.

If you set up a timer as a counter and feed the tach signal into its TxCKI pin, the timer will count tach pulses. Then you can use a second timer to interrupt every 1/2 second, and sample the counter timer during this interrupt. Your RPM = counter value * 120.
Hello, thank you for your answer. I will try your ideea if I can't get it to work as I want to(by reading timer5).

What I'm trying to do is quite simple actually I just need to read the value of TMR5 and put it into a formula. That's literally all I need to do.
With this code:
Code:
if(IC1IF==1)
  {
   timercount = TMR5;
   speed = ( 6250000 / (timercount*8*6) ) * 60;
   TMR5 = 0;
     
   putrsXLCD("Speed: ");                     //Display "Temp is" on the screen
   sprintf(buf, "%g", speed );        //Convert temperature float value to string
   putsXLCD(buf);                             //Display the temperature on the screen
   putrsXLCD(" ");                            // Display "C" for Celsius
   putrsXLCD("RPM");                            // Clear after comma
   WriteCmdXLCD(0x02);                        //Home position on LCD

   dch = ADRESH >> 2; // set the
   dcl = (ADRESL<<6) | ((ADRESL>>2) & 0x00) ; // duty cycle with the pot
   IC1IF = 0;
   ADON = 0;
  }
The value of my RPM gets up to a value 710224 and then does not get modified no matter the speed of the motor. It is as if the TIMER5 value counts up to a value and then stays there even if I do TMR5 = 0. Any ideea why my timer5 value does not change to 0 when I do TMR5 = 0;?

Thanks.
 

jjw

Member
Your interrupt routine may take a lot of time ( LCD and float operations) and Timer5 might overflow during that time.
I am not sure if this ok when speedcount is float:
speedcount=TIMER5H<<8+TIMER5L
It is ok if speedcount is 16bit integer.
You could try:
speedcount=256×(float)TIMER5H+(float)TIMER5L
 

jjw

Member
Timer5 also overflows with low rpm.
You could use a higher prescaler value for the timer5 or count the overflows and put all calculations + LCD display into the main().
 

Cantafford

Member
Timer5 also overflows with low rpm.
You could use a higher prescaler value for the timer5 or count the overflows and put all calculations + LCD display into the main().
Edit: I got it to work(somehow). Apparently I had something set wrong in my T5CON(the reset of the tmr5 was not enabled).
Now it works(somehow): With my calculations the speed displayed on the LCD is ≃ the actuall speed of the motor * 8.5.

However on low speeds(from 15% pot position and below and high speeds over 80% the values on the LCD are not corelated with that formula anymore)(the timer overflows I think). :(

This is the program:

Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
#include <plib/delays.h>
#include <plib/xlcd.h>

#define FCY 6250000

int HALL;
int HALLvalue[6] = { 0b00000101, 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100 };
unsigned int dch;
unsigned int dcl;

float timercount;
float speed, actualspeed;
unsigned char buf[20];

float RPMconstant = 60 * 6250000 / 256;
int long timer5;

// Capture Interrupt Service Routine


void init_XLCD(void);       //Initialize LCD display
void DelayFor18TCY( void ); //18 cycles delay
void DelayPORXLCD (void);   // Delay of 15ms
void DelayXLCD (void);       // Delay of 5ms


void interrupt CheckHallValue()
{
  if(IC1IF==1)
  {
   timercount = TMR5;
   speed = ( 6250000 / (timercount*8*6) ) * 60;
   TMR5 = 0;
     
   putrsXLCD("Speed: ");                     //Display "Temp is" on the screen
   sprintf(buf, "%g", speed );        //Convert temperature float value to string
   putsXLCD(buf);                             //Display the temperature on the screen
   putrsXLCD(" ");                            // Display "C" for Celsius
   putrsXLCD("RPM");                            // Clear after comma
   WriteCmdXLCD(0x02);                        //Home position on LCD

   dch = ADRESH >> 2; // set the
   dcl = (ADRESL<<6) | ((ADRESL>>2) & 0x00) ; // duty cycle with the pot
   IC1IF = 0;
   ADON = 0;
  }

  IC2QEIF = 0; IC3DRIF = 0;

  HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state
  if(HALL == HALLvalue[0]) { OVDCOND = 0b00000110; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[1]) { OVDCOND = 0b00100100; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[2]) { OVDCOND = 0b00100001; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[3]) { OVDCOND = 0b00001001; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[4]) { OVDCOND = 0b00011000; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[5]) { OVDCOND = 0b00010010; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
}

void ConfigureADC()
{
  ADCON0 = 0b00000000; // single shot mode, single channel mode
  VCFG1 = 0; // VDD and VSS as ref
  VCFG0 = 0;
  ADCON2 = 0b00001000; // left justified, 2TAD, conversion clock: Fosc/2
  ADCON3 = 0b11000100;  // input capture 1 starts the a/d sequence!!(check here the first two bits)
  GASEL1 = 0; // select AN0
  GASEL0 = 0;
  ANSEL0 = 0b00000001;
}

void main()
{
 //OSCCON = 0b01001111; // frequency is 1Mhz
 ConfigureADC();
 SCS1 = 0; // use primary
 SCS0 = 0; // oscillator
 TRISA = 0b11111111; // PORTA is input(CAP's + POT)
 TRISB = 0b11000000;
 GIE = 1; // enable global interrupts
 GIEH = 1;
 PEIE = 1;

 // Initialize the Input Capture Module
 CAP1CON = 0b00000000; // disable input capture 1 module
 CAP1CON = 0b00001000; // enable input capture 1 module; interrupt on every state change

 CAP2CON = 0b00000000; // disable input capture 2 module
 CAP2CON = 0b00001000; // enable input capture 2 module; interrupt on every state change

 CAP3CON = 0b00000000; // disable input capture 3 module
 CAP3CON = 0b00001000; // enable input capture 3 module; interrupt on every state change

 // Enable Capture Interrupt and configure TMR5
 IC1IE = 1; // enable IC1 interrupt
 IC1IP = 1; // IC1 interrupt on high priority
 IC1IF = 0; // clear IC1 interrupt status flag

 IC2QEIE = 1; // enable IC2 interrupt
 IC2QEIP = 1; // IC2 interrupt on high priority
 IC2QEIF = 0; // clear IC2 interrupt status flag

 IC3DRIE = 1; // enable IC3 interrupt
 IC3DRIP = 1; // IC3 interrupt on high priority
 IC3DRIF = 0; // clear IC3 interrupt status flag

 PTCON0 = 0b00000000; // 1:1 postscale, 1:1 prescale, PWM in free-running mode
 PTCON1 = 0b10000000; // pwm time base is on, the time base counts up
 PWMCON0 = 0b01001111; // pwm0-5 configured as pwm output in independent mode
 SEVOPS3 = 0; // 1:1 postscale
 SEVOPS2 = 0;
 SEVOPS1 = 0;
 SEVOPS0 = 0;
 OSYNC = 1; //Output overrides via the OVDCON register are synchronized to the PWM time base(NOT SURE HERE)

 PTPERH = 0x0F; // frequency is 1.5Khz
 PTPERL = 0xFF; // 0xFF here

 T5CON = 0b00011001; // tmr 5 prescaler = 1:2
 PR5H = 0xFF;
 PR5L = 0xFF;

 init_XLCD();                    //Call the Initialize LCD display function
 OVDCOND = 0b00000110; // start(needs a change on input capture)
 PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF;
 OVDCONS = 0;

 while(1)
 {
     ADON = 1;
 }

}

void init_XLCD(void)                //Initialize LCD display
{
OpenXLCD(FOUR_BIT&LINES_5X7);       //configure LCD in 4-bit Data Interface mode
                                    //and 5x7 characters, multiple line display
while(BusyXLCD());                  //Check if the LCD controller is not busy
                                    //before writing some commands
WriteCmdXLCD(0x06);                 //Move cursor right, don't shift display
WriteCmdXLCD(0x0C);                 //Turn display on without cursor
}

void DelayFor18TCY( void )         //18 cycles delay
{
Delay10TCYx(20);
}
void DelayPORXLCD (void)           //Delay of 15ms
{
Delay1KTCYx(30);
}
void DelayXLCD (void)              //Delay of 5ms
{
Delay1KTCYx(10);
}
Any ideea what I should do so that the higher and lower frequencies are also displayed as 8.5 * the actuall speed? I tried with different prescale values but it won't work.
 
Last edited:

Cantafford

Member
Hello. It's for a BLDC motor as show in proteus snapshot.

Still couldn't make it to work. This code is supposed to run the motor counterclockwise. I even checked the phases with the digital oscilloscope and they are energised in reverse compared to the sequence I used for the forward sequence. Still the motor only runs CW :(. It bugs me because it's supposed to be a simple process of simply reversing some sequence and hall sensor value yet I've been stuck on this for the last month.

Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
#include <plib/delays.h>
#include <plib/xlcd.h>

#define FCY 6250000

int HALL;
//int HALLvalue[6] = { 0b00000001, 0b00000101, 0b00000100, 0b00000110, 0b00000010, 0b00000011 };
int HALLvalue[6] = { 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100, 0b00000101 };
unsigned int dch;
unsigned int dcl;

float timercount;
float speed, actualspeed;
unsigned char buf[20];

float RPMconstant = 60 * 6250000 / 256;
int long timer5;

// Capture Interrupt Service Routine


void init_XLCD(void);       //Initialize LCD display
void DelayFor18TCY( void ); //18 cycles delay
void DelayPORXLCD (void);   // Delay of 15ms
void DelayXLCD (void);       // Delay of 5ms
void CW();
void CCW();
void ConfigureADC();
void CalculateSpeed();
void SetSpeed();
void DisplaySpeed();
void ConfigureInterrupts();
void ConfigureInputCapture();
void ConfigurePCPWM();
void ConfigureTIMER5();
void Start();

void interrupt CheckHallValue()
{
  if(IC1IF==1)
  {
   CalculateSpeed();
   SetSpeed();
  }

  IC2QEIF = 0; IC3DRIF = 0;

  HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state
  CCW();

}



void main()
{
ConfigureADC();
SCS1 = 0; // use primary
SCS0 = 0; // oscillator
TRISA = 0b11111111; // PORTA is input(CAP's + POT)
TRISB = 0b11000000;
TRISCbits.RC7 = 0;
LATCbits.LATC7 = 0; // led initially off

ConfigureInterrupts();
ConfigureInputCapture();
ConfigurePCPWM();
ConfigureTIMER5();

init_XLCD();                    //Call the Initialize LCD display function

//OVDCOND = 0b00100100; // start(needs a change on input capture)
//PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
OVDCONS = 0;

while(1)
{
     Start();
     ADON = 1;
     DisplaySpeed();
}

}

void init_XLCD(void)                //Initialize LCD display
{
OpenXLCD(FOUR_BIT&LINES_5X7);       //configure LCD in 4-bit Data Interface mode
                                    //and 5x7 characters, multiple line display
while(BusyXLCD());                  //Check if the LCD controller is not busy
                                    //before writing some commands
WriteCmdXLCD(0x06);                 //Move cursor right, don't shift display
WriteCmdXLCD(0x0C);                 //Turn display on without cursor
}

void DelayFor18TCY( void )         //18 cycles delay
{
Delay10TCYx(20);
}
void DelayPORXLCD (void)           //Delay of 15ms
{
Delay1KTCYx(30);
}
void DelayXLCD (void)              //Delay of 5ms
{
Delay1KTCYx(10);
}

void CW()
{
  if(HALL == HALLvalue[0]) { OVDCOND = 0x09; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[1]) { OVDCOND = 0x18; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[2]) { OVDCOND = 0x12; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[3]) { OVDCOND = 0x06; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[4]) { OVDCOND = 0x24; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[5]) { OVDCOND = 0x21; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
}

void CCW()
{
  if(HALL == HALLvalue[0]) { OVDCOND = 0x06; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[1]) { OVDCOND = 0x12; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[2]) { OVDCOND = 0x18; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
  else if(HALL == HALLvalue[3]) { OVDCOND = 0x09; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[4]) { OVDCOND = 0x21; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
  else if(HALL == HALLvalue[5]) { OVDCOND = 0x24; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
}

void SetSpeed()
{
   while(GODONE); // wait untill conversion is over
   dch = ADRESH >> 2; // set the
   dcl = (ADRESL<<6) | ((ADRESL>>2) & 0x00) ; // duty cycle with the pot
   IC1IF = 0;
   ADON = 0;
}

void CalculateSpeed()
{
   timercount = TMR5;                               // get
   speed = ( 6250000 / (timercount*8*6) ) * 60 / 8.5;     // the
   TMR5 = 0;
   if(dch==0 && dcl==0) {speed = 0; LATCbits.LATC7 = 0; }
}

void DisplaySpeed()
{
   putrsXLCD("Speed: ");                     //Display "Temp is" on the screen
   sprintf(buf, "%g", speed );        //Convert temperature float value to string
   putsXLCD(buf);                             //Display the temperature on the screen
   putrsXLCD(" ");                            // Display "C" for Celsius
   putrsXLCD("RPM");                            // Clear after comma
   WriteCmdXLCD(0x02);                        //Home position on LCD
}

void ConfigureADC()
{
  ADCON0 = 0b00000000; // single shot mode, single channel mode
  VCFG1 = 0; // VDD and VSS as ref
  VCFG0 = 0;
  ADCON2 = 0b00001000; // left justified, 2TAD, conversion clock: Fosc/2
  ADCON3 = 0b11000100;  // input capture 1 starts the a/d sequence!!(check here the first two bits)
  GASEL1 = 0; // select AN0
  GASEL0 = 0;
  ANSEL0 = 0b00000001;
}

void ConfigureInterrupts()
{
GIE = 1; // enable global interrupts
GIEH = 1;
PEIE = 1;
}

void ConfigureInputCapture()
{
// Initialize the Input Capture Module
CAP1CON = 0b00000000; // disable input capture 1 module
CAP1CON = 0b00001000; // enable input capture 1 module; interrupt on every state change

CAP2CON = 0b00000000; // disable input capture 2 module
CAP2CON = 0b00001000; // enable input capture 2 module; interrupt on every state change

CAP3CON = 0b00000000; // disable input capture 3 module
CAP3CON = 0b00001000; // enable input capture 3 module; interrupt on every state change

// Enable Capture Interrupt and configure TMR5
IC1IE = 1; // enable IC1 interrupt
IC1IP = 1; // IC1 interrupt on high priority
IC1IF = 0; // clear IC1 interrupt status flag

IC2QEIE = 1; // enable IC2 interrupt
IC2QEIP = 1; // IC2 interrupt on high priority
IC2QEIF = 0; // clear IC2 interrupt status flag

IC3DRIE = 1; // enable IC3 interrupt
IC3DRIP = 1; // IC3 interrupt on high priority
IC3DRIF = 0; // clear IC3 interrupt status flag
}

void ConfigurePCPWM()
{
PTCON0 = 0b00000000; // 1:1 postscale, 1:1 prescale, PWM in free-running mode
PTCON1 = 0b10000000; // pwm time base is on, the time base counts up
PWMCON0 = 0b01001111; // pwm0-5 configured as pwm output in independent mode
SEVOPS3 = 0; // 1:1 postscale
SEVOPS2 = 0;
SEVOPS1 = 0;
SEVOPS0 = 0;
OSYNC = 1; //Output overrides via the OVDCON register are synchronized to the PWM time base(NOT SURE HERE)

PTPERH = 0x0F; // frequency is 1.5Khz
PTPERL = 0xFF; // 0xFF here
}

void ConfigureTIMER5()
{
T5CON = 0b00011001; // tmr 5 prescaler = 1:8
PR5H = 0xFF;
PR5L = 0xFF;
}

void Start()
{
if(PORTAbits.RA1==0)
     {
      PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
      LATCbits.LATC7 = 1; // turn on LED
     }
}
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top