HOME - - - - - - - - Table of contents, my Arduino "How To" articles
Other material for programmers     

Using the counter in the Atmega chip

for low overhead pulse counting.

Filename: aht4timer1-counter.htm

Sorry... I "shouldn't" be doing this at this time... the "day job" beckons. But I couldn't resist just a little investigation.

I have long wanted to make use of the counter inside the Atmega328... and have now accomplished that, and will show you how.

My program isn't clever. It doesn't use a fraction of the Atmega's bells and whistles. But it DOES (in limited testing) seem to work! I hope it will be of use to you, at least as a starting point.

Before I go further, let me mention a reason for wanting a counter! If you are using electronics to supervise something, sometimes it is hard to achieve a sufficiently high polling rate to "see" some transient events. My pulse train trick, which needs a counter, is a neat solution to the problem.

The program to use the internal counter does its thing without using interrupts.

If my research is correct, with a "mere" Atmega328... all I see myself needing for a long time... you have only one counter available to you for what I'm doing here. Yes, there are other timers and counters. But you can't use them, for a variety of reasons.

PLEASE NOTE: If you are using the Servo library you can't use what's in my demo... there will be a clash of resources.

What do I mean by "use counter"?

Let's say I want to monitor windspeed... You might as well, because that's my first reason for wanting this, although there are MANY applications for it. (The gales in southern England of 28 March, 2016 got me to finally deal with this long-standing want.)

One approach to measuring windspeed starts with a "thingie" that spins around, briefly closing a switch once per revolution. You can make your own, but whatever you do, buy the "cups" from someone who has set up a machine to spit nice plastic full three-cup assemblies out by the score. I saw a nice "adequate for play" anemometer... complete with switch... for sale March 16 at... http://www.maplin.co.uk/p/maplin-replacement-anemometer-for-n25fr-n76nf?cmpid=ppc&gclid=COaDzabR5ssCFQPgGwod-EUG6g
...for abut $6. Sadly for many readers, that IS in the UK. I wouldn't expect it to be a high grade, long-term consistent, scientific instrument. But there are people who sell such... See http://sheepdogsoftware.co.uk/sc3sww.htm
... the one I have from Inspeed is working fine after 5 years in southern CT... home of winter ice and snow.

ANYWAY... once you have an anemometer, switch type, you then need to count the switch closures.

There are "crude" and "obvious" ways to do this... if you want to dedicate an Arduino to the task.

But, what if there were some form of electronics you could wire the switch to, that would keep track of how many times it has closed, and have that total available to the Arduino for the asking. With the Arduino free to go off, do other things.

There is! (A form of electronics to do that.)

It is called an Atmega328... the chip at the heart of the Arduino Uno, Mini, Pro Mini, ModernDevice RBBs, etc, etc. And other microprocessors running Arduino code have similar facilities, although my code may need a little tweaking for them.

So. How do you utilize the necessary stuff inside the Atmega? We're nearly there.

You'll need to connect up two switches to your Arduino.

One will "stand in" for the anemometer. It should short pin D5 (i.e. the one that pinMode(5,INPUT) would affect. (You don't need to issue a pinMode command for it, by the way.) The switch should pull the line low (connect it to "ground") when pressed. And the pin should also be connected to your Arduino's Vcc (5v or 3v3) THROUGH a 10k resistor.

The second switch should be connected to D6. Each time you press it, the program will go off to the "necessary stuff" (the "counter" in the narrow sense used by electronic engineers) inside the Atmega, and then display what it has found there on the serial monitor.

NOTE: Because of something called "switch bounce" you will probably find that the count sometimes rises by more than one count each time you press the button, even though you would hope for a rise of just one in perfect world. It will depend on a lot of things. In my case, I was getting one sometimes, and as much as ten another. I wouldn't be surprised with some switches, or (especially) if you are connecting and disconnecting a wire in lieu of a switch to see jumps of 100 counts or more. This down to the switch, not the counter. The switch, if you could watch the electrical events "under microscope" actually goes through a number of openings and closings in what seems like you to "closing" it. (And the same thing happens as you "open" it.) Switch bounce can be overcome.

One other little matter.... Overflow

The counter cannot handle numbers greater than 64,000-and-a-bit. (Exactly 2 to the power of 16, minus 1.

Some counters, when they reach their "top" number just get the sulks, and refuse to do anything. They don't go higher. They don't, as some do, go back to zero and start again.

Happily, the Atmega's counter DOES go back to zero, and resume counting upward.

//FirstUseOfCounter

//vers 29 Mar 16
//started 29 Mar 16... just before Mel,Gio,Jim,Maria,James visit.

//Endebted to...
//Nick Gammon, who wrote something much more clever at..
//     http://www.gammon.com.au/forum/?id=11504
//Beware: Some of his examples are for Atmega 2560

//Apologies for the rough edges in this. Done in haste... but
//  it HAS been quite carefully tested... just not so carefully
//  written up...
//    http://sheepdogguides.com/arduino/aht4timer1-counter.htm
//  ... nor that "polished", at the time of original publication.

//============================================
//All this program does is...

//  Demonstrates using the COUNTER inside an Atmega328
//microprocessor to keep track of edges... not sure if it
//is the rising edges, or falling, in a stream of pulses
//EFFICIENTLY, with virtually no software or performance
//overhead.

//Note: Uses timer1. This normally means that your Arduino
//  will operate "normally", not notice. But! You can't
//  use what's here AND the Servo library at the same time...
//  They will clash.

//To use this: You need nothing more than the "normal"
//  Arduino IDE.

//The program does not use interrupts.

//A "little detail"... I can confirm that the counter "rolls over", back
//     to zero when the count gets too high and the register "overflows"...
//     ... which happens at the usual number near 64,000. (It is a 16-bit
//     register, you will have realized from that.)

//==========================================
//For Arduino Pro Mini, with...

//Three LEDs... not really "needed". On (see "defines")

//At least one momentary switch to pull line to gnd.
//Connected to Digital 5 (no other will do)
//NOT set up with a name in the #defines, because 99%
//  of the point of this approach is that it is all
//  hardware, to collect the counts.
//The wiring of the momentary should be such that the
//  line is pulled high through a suitable resistor... 10k will do..
//  unless pulled to low, through little resistance when the switch
//  is closed. Expect some "extra" counts due to switch bounce.

//A second switch is connected to an input, as defined with
//  #define swReportCount, to trigger a "report how many pulses
//  have been counted. This switch should just connect the input
//  to ground. (No pull-up needed, as it was configured with a
//  setMode(swReportCount,INPUT_PULLUP);)

#define swReportCount 6

#define ledA 7
#define ledB 8
#define ledC 9

void setup() {
  // put your setup code here, to run once:
  pinMode(ledA,OUTPUT);
  pinMode(ledB,OUTPUT);
  pinMode(ledC,OUTPUT);
  pinMode(swReportCount,INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println();
  delay(200);
  Serial.println("Welcome to FirstUseOfCounter... simple demo for counter");
  Serial.println("   available in Atmega based Arduinos.");
  delay(300);

  //CORE OF ONE PART OF COUNTER STUFF... note: The Arduino IDE already
  //  knows about TCCR1A, TCCR1B, CS10, CS11, CS12...
  //This sets the control registers for both halves of Timer1.
  //One of the bits (in the computer sense, as well as general sense!)
  /// probably determines whether counter records rising edges, or falling.
  noInterrupts();  // ... briefly, to set things up.
  TCCR1A=0;
  TCCR1B=bit (CS10) | bit (CS11) | bit (CS12);
  interrupts();  //Resume normal operation

  //Note: The counter is unlikely to be at "zero" when the
  //  user first checks its contents. It WILL be at nearly
  //  the same place every time, and could probably be made
  //  to hold zero the first time the user looks at it, before
  //  and pulses have arrived on the input.
  //(It counts a few "stray" other things, before settling
  //  down in the role organized by the software.)

  //End one of the core bits.

}//End setup()

void loop() {

//CORE TO COUNTER use....
unsigned int timer1CounterValue;
timer1CounterValue = TCNT1;  // see datasheet, page 117 (accessing 16-bit registers)
//End "core"... rest is just to "show" it works!

 if (digitalRead(swReportCount)==LOW)
   {digitalWrite(ledA,HIGH);
    Serial.println (timer1CounterValue);
    delay(150);}
  else
   {digitalWrite(ledA,LOW);
   delay(100);};
}// end loop()


The laugh is on me!

Ha! The laugh's on me! I wrote the above in March 16... having wanted to explore that particular possibility for some time. In May 16, I was doing some work on my pages and came across a link to Peter Anderson's work, from back in ** 2007 **.

It was at http://www.phanderson.com/arduino/count_transitions.html. (Peter, alas, died in 2012. He was a great pioneer in on-line tutorials, especially for things MicroChip and Dallas 1-Wire.)

// COUNT_TRANSITIONS - Arduino
//
// Illustrates how to count positive transistions in input T1.  Digital Pin 5
//
// This uses the Timer1 module which is 16-bits and thus counts up 65535 may be accommodated.
//
// Note that I initially attempted to do this using input T0 (Digital Pin 4).  However, it
// appears that the delay function uses Timer0.
//
// copyright, Peter H Anderson, Baltimore, MD, Nov, '07

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#include <avr\io.h>

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    unsigned int count_transitions(int ms);
    int count;

    while(1)
    {
        count = count_transitions(10000);
        Serial.println(count);
    }
}

unsigned int count_transitions(int ms)
{
     // configure Counter 1
     cbi(TCCR1A, WGM11);
     cbi(TCCR1A, WGM10);

     cbi(TCCR1B, WGM12);  // WGM12::WGM10 000 - Normal mode

     sbi(TCCR1B, CS12);   // CS12::CS10 111 - External clock, count on rising edge.
     sbi(TCCR1B, CS11);
     sbi(TCCR1B, CS10);

     TCNT1 = 0x0000;      // note that TCNT1 is 16-bits
     delay(ms);
     // not sure if should turn off the counter
     return(TCNT1);
}




   Search this site or the web        powered by FreeFind
 
  Site search Web search
Site Map    What's New    Search

The search engine is not intelligent. It merely seeks the words you specify. It will not do anything sensible with "What does the 'could not compile' error mean?" It will just return references to pages with "what", "does", "could", "not".... etc.
In addition to the tutorials for which this page serves as Table of Contents, I have other sites with material you might find useful.....

Sequenced set of tutorials on Arduino programming and electronics interfacing.
Tutorials about the free database supplied with Libre Office/ Open Office.
      
Some pages for programmers.
Using the parallel port of a Windows computer.


If you visit Ionos's site from here, it helps me. They host my website, and I wouldn't put this link up for them if I wasn't happy with their service. (Formerly "1and1.com")




Ad from page's editor: Yes.. I do enjoy compiling these things for you... hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!

Click here to visit editor's Sheepdog Software (tm) freeware, shareware pages.. Material on this page © TK Boyd March, 2016


And if you liked that, or want different things, here are some more pages from the editor of these tutorials....

Click here to visit the homepage of my biggest site.

Click here to visit the homepage of Sheepdogsoftware.co.uk. Apologies if the "?FrmAht" I added to that link causes your browser problems. Please let me know, if so?

Click here to visit editor's pages about using computers in Sensing and Control, e.g. weather logging.



To email this page's editor, Tom Boyd.... Editor's email address. Suggestions welcomed! Please cite "SheGui/arduino/aht4timer1-counter.htm".

Valid HTML 4.01 Transitional Page has been tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes.

AND passes... Valid CSS!


Why does this page cause a script to run? Because of the Google panels, and the code for the search button. Why do I mention the script? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....