BEGINNING to Use Timers on the Arduino M0, Zero and Robotdyne SAMD M0 mini. [code example]

I have had a little time on my hands, so I've written a (fairly long) blurb on using the SAM D21 based arduino-compatible boards, specifically on their timers which have fairly good libraries to support them but very incomplete documentation. I have by no means covered anywhere near all the possibilities but have covered a few of the most popular uses.

I have also added a slightly modified RTCCounter library, the use of which is covered in the blurb.

Enjoy
Peter.

Arduino Zero, M0, SAMD21_timers.txt (13 KB)

pjsRTCCounter.zip (7.97 KB)

Nice write up and very timely for me. Thanks!

A couple of suggestions:

  1. Post your text directly in your post with the code in code tags. It will likely take more than one post But a lot more people will actually read it.

  2. .zip files are notorious for containing malware as such very few will take a chance downloading it. ( I trusted you this time) The best option is to host it on Github and add link to it here. but then you should probably do a proper fork from the original library.

Thanks, Hutkikz. I presume the pun was well intended there.

I don't know that the M0, Zero, Due etc. are very widely used and I think that anyone wanting to use the timers could find this post fairly easily and would not hesitate to download a text file.
I'm not into this forum far enough or often enough that I'd want to spend time learning the quirks of posting in the way that you suggest. Likewise, I'm not into github for the same reasons.

However I have no objection whatever if someone else wants to resubmit my efforts.

Stay COVID-free.
Peter.

@OldBikerPete

Many users of those boards tend to be used by the more experienced.
Those users may also be more savvy and not want to download the zip.

Please consider posting it as a proper tutorial and using github to host your file as it the more professional way to do it.

Bob.

Another use of the SAM-D21 timer/counters has occurred to me so I have added and example here. I will try to use the 'code' protocol mentioned above but take note that NOWHERE OBVIOUS in these beginner tutorials is any clue to special 'quirks' of this forum advocated by the so-arrogant ballscrewbob.

/*
*  Measure Period using TCC0
*  
*  A square wave varying widely in low frequency (2 - 150Hz) is applied to INPUT_PIN.
*  
*  A count measuring its period is printed repeatedly. A rolling average for output is 
*  maintained for signals with significant frequency noise - applying this code will
*  however slow any response to frequency change.
*  A similar effect may be obtained by allowing the count to run for a number of cycles
*  before saving the total and clearing the counter. The code within the #ifdef MULTI
*  block of conditional code runs the counter for 4 cycles before save and clear.
*  
*  A sufficiently high clock frequency is required for the code to operate reliably.
*  Unwanted significant digits can be discarded by right-shifting the count as in loop().
*
*  The example settings achieve a period uncertainty of less than 1% which suits my purpose
*  in recording wind speed from an anemometer.
*  
*  Written for the SAM-D21 processor used in Arduino M0, Zero and others.
*  Libraries are in:C:\Users\UserName\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.x.xx\libraries
*  A special variants.h is in:C:\Users\UserName\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.x.xx\variants\arduino_zero
*
*  I would like to thank the many people contributing to the topic "Zero TCC Capture"!
*  https://forum.arduino.cc/index.php?topic=396804.msg4046513#msg4046513
*  The information I found there regarding the configuration of the timers was very valuable for my project.
*  The code of MartinL using the DMAC for reading duty cycle at high frequencies was particularly useful.
*  
*  I copied blocks of code from his sketch to build this example. Thank you very much!
*/

#define _SAMD21_M0_MINI_  // MUST be defined FIRST to use my variant.h
/* Arduino Zero must be installed and selected in Arduino IDE */

#include <Arduino.h>

// #define MULTI

#define INPUT_PIN            D9
#define ROLLING_ARRAY_SIZE    4   // Must be a power of 2 (2,4,8,16,    .....)

uint32_t count = 0ul;
bool gotCount = false, gotUSBconn = false;

//###########################################################################################################
//read then zero TCC0
void periodCallback(void) {

#ifdef MULTI
// If a count which is NOT a power of 2 is required, then 'count' must be re-initialised if
// the test is false and the function does not do an early return.
  static uint8_t count = 0;
  if((++count & 0x03)) return;  // Returns when either of LS 2 bits of 'count' are 1
#endif // MULTI

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC;    // Trigger a read synchronization on the COUNT register
  while (TCC0->SYNCBUSY.bit.CTRLB);                  // Wait for the CTRLB register write synchronization
  while (TCC0->SYNCBUSY.bit.COUNT);                  // Wait for the COUNT register read sychronization
  count = TCC0->COUNT.reg;                           // Save the TCC0 COUNT register
  
  TCC0->COUNT.reg = 0ul;  // I can't believe that it's this easy!! A clear command would be more efficient!
  gotCount = true;
}

//############################################################################################################
void setup() {
  int i;

  SerialUSB.begin(115200);
// Clean glitches out of receive buffer
  while(SerialUSB.available()) SerialUSB.read();
  
// Wait up to 20 seconds for a keypress
  for(i = 0; i < 20 && ! SerialUSB.available(); i++) {
      delay(1000);
  }
  if(SerialUSB.available()) {  
      gotUSBconn = true;
// Make announcement
      SerialUSB.println("\n\nPeriod measurement test");
      while(SerialUSB.available()) SerialUSB.read();   // Clear out input.
  }

  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(4) |          // Divide the 48MHz clock source by divisor 4: 48MHz/4 = 12MHz
                    GCLK_GENDIV_ID(4);            // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |         // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);          // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Feed GCLK4 to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1;   // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
  
  TCC0->CTRLA.bit.ENABLE = 1;                     // Enable TCC0
  while (TCC2->SYNCBUSY.bit.ENABLE);              // Wait for synchronization

  pinMode(INPUT_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(INPUT_PIN), periodCallback, RISING); 
}

//############################################################################################################
void loop(void) {
  static double arrayTotal = 0.0;
  static float periodsArray[ROLLING_ARRAY_SIZE];
  static int readingCount = 0, arrayIndex = 0;
  static bool doneInit = false;

  float period = 0.0;
  uint16_t i = 0;

  if( ! doneInit) {
      for(i=0; i < ROLLING_ARRAY_SIZE; i++) periodsArray[i] = 0.0;
      doneInit = true;
  }
  
  if(gotCount) {
      count >>= 8;  // Unwanted (and noisy) Least significant bits discarded.
      arrayTotal -= periodsArray[arrayIndex];
      arrayTotal += periodsArray[arrayIndex] = count;
      if(readingCount >= ROLLING_ARRAY_SIZE) {
          period = arrayTotal/readingCount;    // An average of period of the input signal
          if(gotUSBconn) SerialUSB.println(period);
      } else {
          readingCount++;  // Delay output until the array has been populated.
      }
      arrayIndex++;
      arrayIndex &= (ROLLING_ARRAY_SIZE-1);
      gotCount = false; 
      count = 0ul;
  }
}

Code Tags, it's the </> button on the Menu. Please use it for long posts like this.
Thanks - from another oh-so-arrogant Moderator.

I will try to use the 'code' protocol mentioned above but take note that NOWHERE OBVIOUS in these beginner tutorials is any clue to special 'quirks' of this forum advocated by the so-arrogant ballscrewbob.

You mean like here at the top of this very forum section, highlighted in bold?

And remember, it isn't arrogance if you actually are superior.

A former (ARDUINO) moderator.

And to be quite open a lot of that guide was actually written by a regular USERS on the forum so I cannot claim credit for it all.
It occupies a prime and well deserved spot in almost every section.

All I did was compile it for usage by everyone as it is concise and certainly NOT "arrogant"

However I can honestly say that @OldBikerPete is duly awarded the title of OFFICIAL forum curmudgeon :grinning:

DARK ARTS BEGGINER CLASS
Who and what do moderators do

What constitutes infractions are not always clear and open to some interpretation or experience by individual moderators.

Our armoury consists of wits, experience, and the blood of the enemy button provided by Arduino, oh and a vast army of loyal Arduinites spread through all territories of the Arduino nation.

We quite often have to rely on "reports" from other Arduinites to do a few main things.

(1) To guide us to a post "they" think breaks forum rules.

(2) To be able to use a decision based on past experiences of similar instances to assess if the reporter is correct or not.

(3) In the case of LINKS we sometimes put ourselves in the line of fire by visiting those links directly to assess them external to Arduino. We live for the smell of danger and a random or occasionally risky link.

(4) And lastly make a final decision on what action to take.

We are often Judge, Jury, and executioner and do those duties every time we visit the forum.
We do those duties to the very best of our abilities and with each day face new challenges.

Sure there will, on rare occasions be a mistake but by far they are super rare probable less than 0.1%.
Occasionally we will use the moderator section to query our own decisions amongst ourselves (apart from when it bugs out).

I understand if you may not have the forum experience some of us have which in some cases at least dates back to pre-internet BBS days.

If we say its legit then it will be up to you guys to show us where we made a mistake and for us to learn from that and not the other way around !

Then there are all the other NON LOGGED moderator interactions where we may simply post something so users know a moderator has an eye on a certain post.

Oh and lets just cover SPAM itself for a moment.
Did you know a lot of it never even gets reported ? Well that would be because the spammers are not really the brightest bulb in the room.
They often spam a post that a moderator has been involved in. That means we go look at it and hey presto big red button and zero reports.

Then there are those where your Spidey sensors tingle before a report even if you were not involved in a post, often spotted as a “NECRO” post or a name that cries out spam.
Yep there are no reports for them either.

Then there are the PM reports from people you deal with on a regular basis “Hey can you take a look at this post it looks odd”. You guessed it no reports for those either.

Or where we may simply do a minor edit on a person's post without further action.
Or where we decide that no further action on a report is needed and simply close it.

There are also times we need to open multiple tabs of a single users posts from their profile to check things (more so for cross posting or relevant behaviour issues)

Other occasions may require a post to first be SPLIT from its parent topic, and then MOVED to a new section before being MERGED with a similar post by the same user.

And don’t forget the forum needs that to be done in a specific manner or it will cast the random back to main forum page spell on you. Leaving you with no idea WTH just happened.

Then there is the thought that crosses a moderators mind (Don’t ask its odd in there My witchy therapist says) What if the user also did multiple infractions or whatever at the same time ?
So off you go and check more of their posts that were not yet reported and as if by some telepathetic spell or your crystal ball you see laid out before you yet more things to do.
Yes you probably guessed they get dealt with and there are zero reports involved.

And while we are on dark arts lets talk about an IP address. They are exceptionally useful to moderators. Sort of like POKEMON you catch one you gotta catch em all. Often worth a look to see how many other names may be called up in that IP.

Chances are that if there is more than one user name there may be another spam account that may have been missed in the past.

Some occasions require delicate PM's to offenders to avoid official sanctions.
Yes we can tread on eggshells and even do the Flamenco on them if we need (omelettes anyone ?)

Then we have our own needs or areas we like to take a little more interest in.
Moderation is not simply point and click, we are part psychologist, part peacekeeper, part guru, part relationship counsellor, part clown, part customer relations, part detective, part masochistic (only explanation for it), and many other things.

There is so much more to the title and duties than most people are aware of and I have only touched on the major points here.
Every post or action including all your own are often subject to your own extra scrutiny.

Are we done yet ?
Oh hell NO !

We do much more than just moderate we also act as a dating agency hooking up members with other members where interests may cross paths or another member may have the experience to answer an OP’s Q. with a larger degree of skill.
This may go as far as generating sales leads for both members and Arduino alike.

We hold a fine line between customer support and the thousands of users per day passing through the forum.

Oh and did I mention we do it all for fun and free usually being in the forum often more than 5 hrs a day often 7 days a week ? ( yea masochistic is the only word for it.)
Where do we release all the feelings built up after a session ?
Well we often have other things we do to take us back to a peaceful realm but on occasion we let loose in the “BAR SPORT” section a little.

Some aspects of moderator duties are an acquired art / skill and some think its witchcraft and that all moderators should be banished to some nether region.
We have a secret location :wink:

As a gentle reminder to you all that moderators are also humans too even if we have to hold ourselves above many things.
Visit the forum and all its sections.

See and learn what type of people are in there.
Can you assess a person’s character, level of English, technical level from a few posts and respond back at a level that suits them ?

Oh and did I mention the FORUM SOFTWARE is cursed and has a mind of its own and often tries to thwart anyone and everyone from noobs to senior posters and even moderators with quite random spells and incantations. (AUTH0)
The most famous of these is to whisk you off to the main page where there may be yet another report…Hmmm which do you take first or do you decide to multiple tab and risk everything ?

Who do we help or who helps us ?
The vast forum of both experienced and even inexperienced users make for a vibrant community and they provide a backbone for community in terms of technical help and experience that would otherwise overwhelm any other form of help desk.

Without the community we are nothing and without us there would be the chaos of spam, abusive behaviour, trolls and all the other down sides you see on social media and many gamified sites.

A fine balance is achieved to provide a smooth flowing community who help each other to expand and perpetuate the Arduino ecosphere beyond the forum to a wider audience. Neglect those people and you neglect Arduino itself.

Next week we will discuss potions and lotions to counter headaches, cankers, ailments, broken bones, warts or whatever else may ail you.
Remember snake oil needs dragons blood and fairies spit to be effective otherwise it’s just a extreme laxative so don’t drink and fart !

Thanks for taking the time to read all this as you helping us to do what we need to do is crucial to helping you !

TheMemberFormerlyKnownAsAWOL:
You mean like here at the top of this very forum section, highlighted in bold?

A former (ARDUINO) moderator.

I invite you to start at Arduino->Community ->Forum with an open mind (If you can manage that) and find WITHOUT FURTHER FOSSICKING anything which describes digital protocols in a heading something like 'How to use this forum'

Peter.

Digital protocols?
The reference was to 'code' protocols, and 'quirks' of the forum.

Do try to keep up.

TheMemberFormerlyKnownAsAWOL:
Digital protocols?
The reference was to 'code' protocols, and 'quirks' of the forum.

Do try to keep up.

You have offered nothing that points to 'code' protocols and 'quirks' of the forum that does not require significant archaeology by the newcomer.
Peter

TheMemberFormerlyKnownAsAWOL:
You mean like here at the top of this very forum section, highlighted in bold?

And remember, it isn't arrogance if you actually are superior.

A former (ARDUINO) moderator.

It pleases me to see that you retain a sense of humor.
Peter.

ballscrewbob:
And to be quite open a lot of that guide was actually written by a regular USERS on the forum so I cannot claim credit for it all.
It occupies a prime and well deserved spot in almost every section.

All I did was compile it for usage by everyone as it is concise and certainly NOT "arrogant"

However I can honestly say that @OldBikerPete is duly awarded the title of OFFICIAL forum curmudgeon :grinning:

A title I humbly accept as only my due.
Peter.