Jump to content
43oh

MSP430 LaunchPad Tachometer.


Recommended Posts

HI all,

 

Here is a working prototype of my LaunchPad Spindle Tachometer for my CNC Mill.

The firmware is ever evolving, I am still learning about the MSP430 amidst of my busy work schedule (day job)

 

 

Will post more details if anyone wants to know more.

 

I would like to understand better and learn from this community, hopeful we can have some fun generating some healthy discussion on this.

 

What it the best and most efficent way to measure RPM?

 

Currently I have the trigger pin on P2.4, and use TimerA1 to count interval, the interval is then multiplied to get RPM. I have also implemented a running average buffer to even out the results, works well but still jitter a bit.

 

Attached is the schematic and some code snippets.

 

int main(int argc, char *argv[]){
CSL_init(); // Activate Grace-generated configuration
P2OUT |= BIT5; //turn IR Led on
while (1){
if(Timer_Capture_Available){
RPS_10x = 327680 / Timer_Capture_Value;
RPS_Buffer[9] = RPS_Buffer[8];
RPS_Buffer[8] = RPS_Buffer[7];
RPS_Buffer[7] = RPS_Buffer[6];
RPS_Buffer[6] = RPS_Buffer[5];
RPS_Buffer[5] = RPS_Buffer[4];
RPS_Buffer[4] = RPS_Buffer[3];
RPS_Buffer[3] = RPS_Buffer[2];
RPS_Buffer[2] = RPS_Buffer[1];
RPS_Buffer[1] = RPS_Buffer[0];
RPS_Buffer[0] = RPS_10x;
RPM = ((RPS_Buffer[0] + RPS_Buffer[1] + RPS_Buffer[2] + RPS_Buffer[3] + RPS_Buffer[4] + RPS_Buffer[5] + RPS_Buffer[6] + RPS_Buffer[7] + RPS_Buffer[8] + RPS_Buffer[9])/10) * 6;
 DisLED(RPM); //Display results
 Timer_Capture_Available = 0;
}
else if (!Timer_Capture_Value){
DisLED(0); // Reset Display to zero.
}

}
}//main

// Functions
void TachTimer_ISR(void){
// Read timer counter value captured
if (!Timer_Capture_Flag){
 Timer_Capture_Value1 = TA1CCR2;
 Timer_Capture_Flag=1;
}
else
{
 Timer_Capture_Value = TA1CCR2 - Timer_Capture_Value1; // get the difference in time value
 Timer_Capture_Flag=0;
 TA1CTL |= TACLR;
 Timer_Capture_Available = 1;
}

} // TachTimerISR
void Timer_OF(void){
Timer_Capture_Value = 0; // reset time if timer overflow.. 2sec..
}

 

post-1099-0-92017300-1353522666_thumb.png

 

Regards,

Terence

Link to post
Share on other sites

Looking good!

I have two suggestions:

Your video shows only even values, which suggests you display values twice that of your minimum sensitivity.

 

Your main() function loops until a flag set in the interrupt is true. Instead, you could let the main() loop sleep (using __low_power_mode_0() for example, verify whether you need SMCLK clock, if not, you could probably get away with using __low_power_mode_3() as well)

So at the point you'd "poll" for the flag, instead enter low power mode, at the place where you'd normally st the flag, now clear it (as you're currently doing in the main loop) and call the __leave_low_power_on_exit() intrinsic (or something similar if using CCS/GCC).

Now instead of looping and looping until the flag is set, your processor sleeps until the interrupt occurs, at which moment the processor will wake, handle the interrupt and (if needed) keep the processor from going to sleep again, thus executing the main loop for you.

 

[edit]

I was mistaking on the stuff about even values: you use ((something)/10)*6, however, this is integer calculation. This means you're actually throwing data away by /10, then you multiply this integer value by 6. Instead, you could do ((something)*6)/10 which would discard less information.

You do need to verify that your value will actually fit in the type of your variable.

So if RPM_buffer[] is unsigned short, the value must not exceed 1092 (as you add 10 of them and multiply by 6 in the end).

Also, as the values in RPM_buffer are 327680 / value, you could move the times 6 here. so (6*327680)/value. This would decrease your quantization error even more.

Link to post
Share on other sites

Hi Roadrunner,

 

Thank you for the advise , I guess I was lazy, haha.

Everything was done in a hurry, as I was struggling with learning the MSP430 and trying to figure out the algorithm.

 

I will look in to the code and fix it as I go.

 

RPS_Buffer is declared as unsigned int array - so should be 32 bit long.

I figured I have quantisation error as I keep getting jitters in the display, even when I feed a steady pulse to the pin with another LP. I need to figure a better algorithm, in processing the time, either by counting pulses or something.

 

I wanted to do low power mode but have not figure or try it.

 

Once again thanks for your time and advise.

 

Looking good!

I have two suggestions:

Your video shows only even values, which suggests you display values twice that of your minimum sensitivity.

 

Your main() function loops until a flag set in the interrupt is true. Instead, you could let the main() loop sleep (using __low_power_mode_0() for example, verify whether you need SMCLK clock, if not, you could probably get away with using __low_power_mode_3() as well)

So at the point you'd "poll" for the flag, instead enter low power mode, at the place where you'd normally st the flag, now clear it (as you're currently doing in the main loop) and call the __leave_low_power_on_exit() intrinsic (or something similar if using CCS/GCC).

Now instead of looping and looping until the flag is set, your processor sleeps until the interrupt occurs, at which moment the processor will wake, handle the interrupt and (if needed) keep the processor from going to sleep again, thus executing the main loop for you.

 

[edit]

I was mistaking on the stuff about even values: you use ((something)/10)*6, however, this is integer calculation. This means you're actually throwing data away by /10, then you multiply this integer value by 6. Instead, you could do ((something)*6)/10 which would discard less information.

You do need to verify that your value will actually fit in the type of your variable.

So if RPM_buffer[] is unsigned short, the value must not exceed 1092 (as you add 10 of them and multiply by 6 in the end).

Also, as the values in RPM_buffer are 327680 / value, you could move the times 6 here. so (6*327680)/value. This would decrease your quantization error even more.

Link to post
Share on other sites

yes, you are right. thanks, it is 16 bit.

 

Checking thru, it works, as I am now using (6*327680)/value, short for RPM = (count per sec / capture value) *60 as recommended by roadrunner. Value stored in the unsigned int array should be < 65535.

 

@roadrunner, your formula brings the accuracy close to 1 or 2 RPM when measuring the motor spindle with a Laser tachometer. (don't know how accurate it is but not e-bay china type.)

 

This bring new problem to the table, the last digit in constantly jumping even with 10x averaging. I think I got to check the sampling code or gate sampling time somehow.

 

 

unsigned int is 16-bits I believe, unsigned long is 32-bits

Link to post
Share on other sites

Hey there. I am not very good at programing and I was searching for a tachometer with the msp430 launchpad. Can you please repost the circuit diagram and the code so i can build it? I need it to measure the rpm on a asyncronous motor for a project at school. My best regards, Julian.

P.S. What msp chip are you using because mine doesn't have 20pins so no 2.0-2.5 "gates".

Link to post
Share on other sites

Hey there. I am not very good at programing and I was searching for a tachometer with the mps430 launchpad. Can you please repost the circuit diagram and the code so i can build it? I need it to measure the rpm on a asyncronous motor for a project at school. My best regards, Julian.

 

Hi Julian,

 

Schematics and codes posted on the first post. I will post the final codes later.

 

The tachometer part of the code is very simple, it uses a reflective opto switch, Timers are used to capture the during of 1 pulse to another, the clock value is then divided to get an RPM value. The rest of the code is use to display the numbers.

 

Depending on how and what sensor you use you might need to adjust the circuit and codes. Let me know if I can be of help.

 

I am giving away the bare PCB board if you need it.

http://forum.43oh.com/topic/2910-7-seg-led-booster-pack-raw-version/

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...