Jump to content
chicken

[Energia Library] Hardware Counter Library for MSP430

Recommended Posts

I will make a speed test for this with a signal generator, and scope. For many reasons, writing to energia ports are sometimes slow. I just could not fix my bricked 5529 and waiting for a new one.

 

Best,

C.A.

 

You are right of course.  I nominate you for the honorific title of "Count Chicken" ;)

 

I rewrote my signal generation sketch to run on the F5529:

// toggles a pin LOW to HIGH over and over...
// test on MSP-EXP30F5529LP
//
#include <msp430.h>
     

void setup()
{
  P1DIR |= 0x01;               // Set P1.0 to output
}

void loop()
{
  P1OUT ^= 0x01;               // Toggle P1.0 using exclusive OR
}

By getting a bit closer to the metal and getting rid of some Energia overhead it is running faster than before, even on a slower device.  On the oscilloscope I see:

 

attachicon.gifcounter2.jpg

 

811 kHz!  We are in new territory.  I doubled the count time and halved the clock (also changed to Timer A2 just to test it).  Here is the new counting sketch for the F5529:

#include "CounterLib_t.h"

Counter<CL_TimerA2> MyCounter;  // create counter that counts pulses on pin P2.2

void setup()
{
  Serial.begin(9600);
  MyCounter.start(CL_Div8,2);   // start counter, divide clock by 16
} 

void loop()
{
  MyCounter.reset();           // reset counter to zero
  delay(200);                  // wait 200 milliseconds
  Serial.print((MyCounter.read() + 5) / 200 * 16);   // read counter, calculate kHz
  Serial.println(" kHz");
  delay(1000);                 // wait one second

I get a very regular 816 kHz.  That is a new speed record and around 0.6 % error.  I'm sure it could be improved with some more tweaking of the parameters.  Alternatively, if the pulses are regular it wouldn't be difficult to put together a function with correction factors.

Share this post


Link to post
Share on other sites

Just received my el-cheapo 25 MHz signal generator from eBay (MHS-5200A, $77.56 shipped).
 
Second thing I did after unpacking (first thing being verification of voltage levels on the oscilloscope ;) ), is to test my counter library on the F5529 and G2553 Launchpads.
 
The library works all the way to 25 MHz. For the G2553, this is well beyond the datasheet spec of system clock frequency (16 MHz).
 
As discussed above, I used two measurements to compensate for overhead.

#include "CounterLib_t.h"

Counter<> MyCounter;

void setup()
{
  Serial.begin(9600);
  MyCounter.start(CL_Div4);    // divide signal frequency by 4
  // 25 MHz = 25000 counts / ms, 250K / 10 ms
  // divided by 4 => 62500 / 10 ms -> fits into 16 bit
}

void loop()
{
  unsigned int count1, count2;  // variables to hold measurements

  MyCounter.reset();            // set counter to 0
  delay(5);                     // wait 5 ms
  count1 = MyCounter.read();    // read counter and remember

  MyCounter.reset();            // reset counter to 0
  delay(10);                    // wait 10 ms
  count2 = MyCounter.read();    // read counter

  Serial.print((count2 - count1) / 5 * 4);  // difference is eq. to 5 ms w/o overhead
  Serial.println(" kHz");       // divide by ms, multiply by counter divider to get kHz

  delay(1000);
}

 
As theorized, the error is lower as a percentage - about 1-2% on my G2553, vs. 10+% with just one measurement.

 

The error (with and without compensation) is fairly constant across a range of about 150 KHz to 25 MHz, but grows at the very low end. What we're seeing at low frequencies is the counter resolution. At 80 kHz we only get about 100 counts in 5 ms with a divider of 4. Missing 1 count will translate to 1% additional error at that level.

 

There could be a bit more resolution with more careful integer math (e.g. multiply before divide, but be careful with that at the high end).

Share this post


Link to post
Share on other sites

@@bluehash

 

I think that it is a great example of clean, concise, easy to use and well documented code for people who would like to see how to write an Energia library.  All credit to @@chicken and wish I could code like that.

 

Attached is a photograph of a F5529 LaunchPad with a SHARP96 BoosterPack attached and running an example that uses two samples to compensate for overhead. The LaunchPad is displaying 804 KHz while the oscilloscope is reading 810.6 KHz, so less than a percent error.  The signal is coming from another LaunchPad out of the picture.

 

post-45284-0-33025300-1442360701_thumb.jpg

Share this post


Link to post
Share on other sites

Very cool! Regarding accuracy, one thing to keep in mind is that the delay function its self is likely clocked off of the internal DCO so its accuracy plays into your measurements. I'm curious if in your test you were to use a better clock reference such as a crystal, does the measurement accuracy improve?

 

 

Sent from my iPhone using Tapatalk

Share this post


Link to post
Share on other sites

@@bluehash

 

 

That is more than what I was expecting. Silly me would have just shown a terminal image. You went a few steps further!

 

Ha ha yeah that little display has been sitting on my shelf with nothing to do for a while so one of the first thoughts I had when I saw Chicken's post was I should make a little frequency counter with it.  Your request caused me to actually do it though.  It's amazing how quickly you can throw something like that together with Energia and a BoosterPack.

Share this post


Link to post
Share on other sites

When thinking about what Energia project to bring to Makerfaire, it occurred to me, that the counter library can count slower things than just wave forms in the MHz. You could say, the penny dropped.

post-9974-0-98986800-1442801822_thumb.jpg

My Penny Counting Machine is built from a geared DC motor (unknown donor), a fork light barrier sensor from an old HP printer, a dairy cup with a bit of thick double-sided tape to make a ramp, a slide built from spare cardboard, and another dairy cup to receive the pennies. All held together by ample hot glue.

 

A G2 launchpad makes up the brains, my own SHARP Memory display BoosterPack shows the current count, and a bit of prototyping board holds some resistors and a transistor to control the motor and connect to the sensor.

post-9974-0-12035600-1442802610_thumb.jpg

 

See it in action here:

 

Attached the code for Energia. It uses the CounterLib and my SHARP Memory Display library.

PennyCounter.ino

Share this post


Link to post
Share on other sites

They loved it! It was fun looking at the kids trying to figure out how it works. When I asked them to explain it to me, I was impressed that they all pointed out the ledge to guide pennies out of the rotating cup.

 

And I think some even threw in their own penny, I returned with more than I started :)

Share this post


Link to post
Share on other sites

Wow! Just what I'm looking for... a counter library and some code for the sharp display.

 

I have a somewhat related question. I'm working on a pulse counting application, which has to run off batteries. When the uC need to pulse count, it will have to do this for up to 8 minutes at a stretch. Simply using the delay function between getting the pulse count and determining pulse frequency will drain the battery quick enough.

 

As the msp430 has a pretty fast wake up I'm looking at what options can I turn off to make the uC sleep between the 1 second periodic updates, without jeopardising the functionality of this library.

 

Thanks

Share this post


Link to post
Share on other sites

The counter keeps working in low power mode, e.g. during sleep(). The only time limit is how long your signal takes to overflow the 16bit counter.

 

Energia's sleep() function will put the micro into low power mode. Adding sleep(1000) into your main loop will greatly improve power consumption. Also see this write-up by @@Fmilburn for the effects it has on power consumption.

http://43oh.com/2015/09/how-to-measure-an-energia-applications-power-usage-with-energytrace/

Share this post


Link to post
Share on other sites

Yeah, I could add an interupt to handle counter overflows.

 

But that would significantly complicate the implementation. The library currently is dead simple inside. Adding interrupts would also increase the risk of conflicts with other libraries that use timers.

 

But the source is on GitHub and anyone is welcome to fork :)

Share this post


Link to post
Share on other sites

Hello @@chicken,

 

I am trying to use your library for a PPM decoder. (PPM as in radio control standard)

 

Basically I need to do a:

 

attachInterupt(PIN, isr_routine, CHANGE); in the setup, then:

timer.start();

 

isr_routine() {

   process_value = timer_val;

   timer.reset();

   // process the value

}

 

So I basically need to be able to start a timer on demand, and read value of it, then reset it, but programmatically, not by reading a pin?

 

Any ideas on how to modify this library to accomplish something similar?

 

 

The arduino equivalent of this code is below:

#define PPM_Pin 3
int ppm[16];

void setup() {

  Serial.begin(115200);

  pinMode(PPM_Pin, INPUT);
  attachInterrupt(PPM_Pin, read_ppm, CHANGE);

  TCCR1A = 0;  //reset timer1
  TCCR1B = 0;
  TCCR1B |= (1 << CS11);  //set timer1 to increment every 0,5 us
}

void loop()
{
}

void read_ppm() {

  static unsigned int pulse;
  static unsigned long counter;
  static byte channel;

  counter = TCNT1;
  TCNT1 = 0;

  if(counter < 1020){  //must be a pulse if less than 510us
    pulse = counter;
  }
  else if(counter > 3820){  //sync pulses over 1910us
    channel = 0;
  }
  else{  //servo values between 510us and 2420us will end up here
    ppm[channel] = (counter + pulse)/2;
    channel++;
  }
}

I have done many experiments, and mostly in CCS using the MSP430g2xx3_TA_21.c, where timer can be used in input capture mode, measuring time for both rising and falling edge, and it can be calculated from there. However, I need to read this data and then transmit it tru serial or i2c, which was beyond my abilities at the moment, so I decided to do it with energia for now.

 

Any ideas/reccomendations/help greatly appreciated.

 

Best regards,

C.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×