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:
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:
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);
}