Design Bureau online. Simple revolution counter - Designs of simple complexity - Circuits for beginners Simple pulse counter circuit

Often, when operating a microcontroller device, there is a need to count “anthropomorphic” time - how many fractions of a second the LED should glow, the maximum period of double-click time, etc. In general, count not only nano- and microseconds, but also tens of milliseconds, or even seconds , minutes and even hours (I'm afraid to say about days...).
At the same time, in microcontrollers it is often necessary to simultaneously deal with microseconds - pulse periods, anti-bounce waiting, etc.
There are also devices that operate continuously for many hours and even days - aviation equipment, automobile equipment, downhole devices (sometimes we are talking about continuous operation for several days). In these cases, overflow of timers and 8-bit variables is unacceptable.
I would like to combine all this into one elegant and universal solution - to have a means of measuring time with microsecond accuracy that does not overflow for several days.
Why not? I suffered for some time and came up with a solution for 8-bit AVR microcontrollers. To do this, I used an 8-bit timer-counter and a 4-byte variable. I don’t currently work with PICs and AT89, and I’m not familiar with other embedded platforms. However, if readers help, I’ll do it for them too.
Advantages – the code is highly repeatable (I’m already making the 5th device with it); ease of operation (interrupts are not used for the client part of the work); the client part of the code is conditionally platform-independent; in the interrupt - one summation operation (but, however, for a 4-byte value); there is no external device - a real time timer.
I found only one drawback - one such useful and always needed timer is busy...
The article will be of interest primarily to beginners - I didn’t discover America here.

Theory

So, I have at my disposal a device based on Atmega16A with 12MHz quartz. Let's take its timer-counter 0. This is an eight-bit timer - that's enough for us. Why? We count:
  1. we take 12 MHz from the quartz and take the division factor by 8 - we get a frequency of 1500 KHz;
  2. We take the CTC mode (reset on coincidence) and set the interrupt to coincide with 150 - we get the interrupt frequency of 10 KHz;
  3. on this very interrupt we increment the variable (an increment is obtained every 0.1 milliseconds);
  4. if it is an unsigned 32-bit value, it will overflow after approximately
    • 429496729.6 milliseconds;
    • 42949.7 seconds;
    • 7158.3 minutes;
    • 119.3 hours;
    • 4.97 days.
In other words, this solution creates a timer with an accuracy of 0.1 milliseconds for (almost) 5 days (we must, however, take into account that real quartz has an error - more on that later). And if you also analyze the value of timer 0 itself - it is incremented every 2/3 microseconds - then you can get a counter with an accuracy of 0.67 microseconds.
Enough? Behind my eyes. Using a 0.1 millisecond counter, in my projects I:
  • I count the duration of glow and pauses between LEDs;
  • I take into account timeouts when working with UART, USB;
  • I set all sorts of situations in the test equipment - complex spatio-temporal combinations;
  • I maintain specified time intervals when polling the ADC and other sensors;
  • I tell the computer the time of my (the device’s) operation and transmit information at a given time interval;
  • Taking into account the counter down to the microsecond, I carry out anti-bounce control when pressing keys, analyzing pulses in long lines.
And all this easily fits into ONE ATmega16 CONTROLLER! Moreover, this is not Assembler, but cross-platform C! And no external real-time counter!
Not bad, right?

Setting up for AVR

How to do all this in AVR?
First of all, we create an external variable, which I call “DeciMilliSecond”:
// in main.h typedef unsigned long dword; // unsigned 32-bit integer extern volatile dword dmsec; // 0.1msec // in main.c volatile dword dmsec;
As @no-smoking correctly noted, this variable must be volatile so that the compiler does not try to optimize it.
I initialize this variable in a function:
dmsec = 0;
Next, I set the operating mode of timer 0:
// . timer 0 – 0.1msec Timer0_Mode (TIMER_Mode_CTC | TIMER0_Clk_8); Timer0_Cntr(149); Timer_Int(Timer0_Cmp);
At the same time, in some MCU_init.h I declare everything that is needed:
// in mcu_init.h #include // . TIMSK #define Timer0_Cmp (1<< 1) // совпадение таймера 0 // . TCCRn #define WGM1 (1 << 3) #define CS1 (1 << 1) // . источник сигнала для таймера 0 #define TIMER0_Clk_8 CS1 // предделитель 8 // . режим работы таймера #define TIMER_Mode_CTC WGM1 // CTC (сброс при совпадении) // . настройка таймера #define Timer_Int(Mode) TIMSK = (Mode) #define Timer0_Mode(Mode) TCCR0 = (Mode) #define Timer0_Cntr(Cntr) OCR0 = (Cntr)
Well, then, when possible, I enable interruptions:
#asm("SEI")
It remains to describe the interruption. This is easier than everything before:
#include interrupt Timer0_Compare (void) ( ++dmsec; )
That's it, the timer is described, configured and running!

Setting for PIC

Here's what dear PIC fans told me:

At peaks this can be easily repeated using the Timer2 module. It has a similar interrupt function by coincidence.

PR2 = 75 - the value at which the timer will reset and generate an interrupt
T2CON.T2CKPS = 2 - prescaler 1:16
T2CON.T2OUTPS = 0 - without postscaler
T2CON.TMR2ON = on - timer is enabled

IPR1.TMR2IP = 1 --high priority interrupt
PIR1.TMR2IF = off -- reset the interrupt flag
PIE1.TMR2IE = on -- enable interrupt when TMR2 and PR2 coincide
INTCON.GIE = ​​on -- enable interrupt processing

As you can see, the prescaler here is 2 times larger, therefore PR2 is 2 times smaller.
These settings will generate interrupts with a frequency of 10 kHz at a system frequency of 48 MHz (the timer is set to Fosc/4) - the standard frequency for USB Full Speed.

Usage

The code for the client of this timer is cross-platform (except for accessing the value of timer 0 in AVR).
Here is a snippet of the USB sharing code:
#include "main.h" // here is the dmsec variable, next_USB_timeout #include "FT245R.h" // here are functions for working with the USB module #include "..\Protocol.h" // here is the microcontroller-computer exchange protocol // * * // ** Analyze USB packets // ** void AnalyzeUSB (void) ( #define RECEIVE_BYTE(B) while (!FT245R_IsToRead)\ ( if (dmsec > end_analyze) return; )\ B = FT245_ReadByte (); #define RECEIVE_WORD(W) // similar for 2 bytes #define RECEIVE_DWORD(W) // similar for 4 bytes dword end_analyze, d; NewAnalyze: if (!FT245R_IsToRead) // no packets return; end_analyze = dmsec + max_USB_timeout; for the current analysis next_USB_timeout = dmsec + MaxSilence_PC_DEV; // timeout for general exchange RECEIVE_BYTE (b) // packet header switch (b) ( case SetFullState: RECEIVE_DWORD (d); // read the word is_initialized = 1; // process ChangeIndicator () ; break; ) // switch (pack) goto NewAnalyze; #undef RECEIVE_BYTE // cancel #define #undef RECEIVE_WORD #undef RECEIVE_DWORD )
The macro functions RECEIVE_BYTE, RECEIVE_WORD, RECEIVE_DWORD implement reading procedures taking into account the timeout for a given exchange phase. As a result, if something hangs on the other side, the microcontroller will not go into hibernation. Please note - WatchDog is not needed! And all thanks to the variable/constant max_USB_timeout, which sets the timeout with an accuracy of 0.1 milliseconds.
The analysis of “silence on air” using the next_USB_timeout variable is implemented in the same way. This allows the microcontroller 1) to know that the computer has disappeared somewhere, 2) to signal this somehow (in my case, the “error” LED lights up). The MaxSilence_PC_DEV constant/variable allows you to vary the concept of “silence” within the widest range – from a fraction of a millisecond to several days.
All other points are implemented similarly.
If you need to use a microsecond counter, then a comparison function appears there:
#define GetUSec(A,B) ( #asm ("CLI"); A = dmsec; B = TCNT0; #asm ("SEI"); ) // ** // ** Time difference between events accurate to 2/3usec // ** dword Difference (dword prev_dmsec, byte prev_usec) ( dword cur_dmsec; byte cur_usec; ​​dword dif; // . note the current time GetUSec (cur_dmsec, cur_usec); // calculate the difference dif = cur_dmsec - prev_dmsec; dif<<= 8; if (cur_usec < prev_usec) dif += 255 + (dword) cur_usec - prev_usec; else dif += cur_usec - prev_usec; return dif; }
The function is passed the previous point in time - the previous value of dmsec and timer 0.
First, we use the GetUSec macro to stop interrupts so that the value of dmsec and the counter are not corrupted at the time of copying. And copy the current time.
Next, we convert the time difference to a 2/3 microsecond format, taking into account overflow.
Well, let's return this time.
And then we use this in a regular if to control anti-bounce and other measures. Just don’t forget to also pause interrupts when marking the current moment in time - or better yet, use the GetUSec macro.

results

This timer turned out to be an extremely convenient solution for me. I think it will be useful to you too. And I used it in my following projects:
  • Switchboard fencing situations. This is a hefty half-meter board with three controllers - ATmega128 as the central one and ATmega64 as two auxiliary ones (right and left sides). There is no galvanic connection between the three controllers and their components - power supply is based on ionistors, communication through optocouplers. The central controller charges groups of some ionistors and at this time powers both sides from other ionistors. Here we had to create a multi-stage algorithm for switching all this in order to minimize the interconnection. In particular, we are talking about the coordinated work of 8 relays - timers work here for 3.3 ms (guaranteed relay response time). Well, in fact, both sides control 10 relays and about half a hundred multiplexers. All this equipment works with clearly defined time characteristics (with an accuracy of 1 ms, maximum duration is 6 seconds). Well, and, in the end, banal timeout for USB, UART.
  • Depth sensor. Here I am solving another problem (a project in progress). There are two conductors (many meters long) that define the situation “shift up by 1 cm” and “shift down by 1 cm”. There are many ways to set a direction. In any case, these are certain combinations of impulses. Using this timer, I determine bounce and the duration of a stable pulse. The maximum permissible bounce time (10 microseconds is enough here), anti-bounce wait, and minimum/maximum pulse duration are set from the computer. Well, there is a debug mode - the sensor becomes a logic analyzer. This allows you to debug the operation of the line and adjust the coefficients. Well, again timeout, LEDs.
  • Analog signal sensor. A banal 8-channel ADC. Here I use a timer to maintain the necessary pauses.
Dear habra users from other platforms can tell me the initialization code for the corresponding timer, as well as the rules for accessing it - I’ll add it here. It may be necessary to select different times for other platforms. But in any case, it should be something within a few units of microseconds for the timer itself and something a multiple of 100 microseconds for the counter variable. Because, as it turns out, sometimes one millisecond is not enough.

video of device operation

The circuit is assembled on a PIC16F628A microcontroller. It can count input pulses from 0 to 9999. The pulses are sent to the RA3 port line (SA1 button active level low). With each pulse, the indicator readings change by +1. After the 999th pulse, 0 is displayed on the indicator and the point at which the second thousand begins (the one on the right in the diagram) lights up, etc. So the counting can continue until the value 9999. After this, the counting stops. Button SA3 (port line RA1) is used to reset the readings to 0.

Pulse counter circuit with memory on a microcontroller

Initially, the circuit was designed to be powered by three AA batteries. Therefore, in order to save energy, the circuit includes an indication button to monitor the status of the meter SA2 (port line RA4). If this button is not needed, its contacts can be short-circuited. Pull-up resistors ranging from 1k to 10k can be used in the circuit. The INTRC I/O and PWRTE configuration bits are set. When the power is turned off, the counter readings are saved in the controller memory. When the indicator is off, the circuit remains operational when the power is reduced to 3.5 volts. Practice has shown that the battery charge is enough for almost a week of continuous operation of the circuit.


Meter printed circuit board


Photo of the counter

Schematic, MK firmware and printed circuit board in S-layuout format archive (15kb).

From the administrator. Resistors R1-R3 can be selected with a value of up to 10K.

-20 dB wrote:
Why not approach the matter with little bloodshed? If there is something like the above-mentioned IZhTS5-4/8, with separate segment outputs?

In the stash of unused K176IE4 from Soviet times, there was a lot left (a counter/divider by 10 with a seven-segment decoder and a transfer output, used to form units of minutes and hours in an electronic watch, an incomplete analogue - CD4026 - what is the incompleteness, haven’t looked... yet) in classic switching on for LCD control. 4 pcs - 2 per channel, + 2 pcs. 176(561)LE5 or LA7 - one for single pulse shapers (contact bounce suppressors), the second - for forming a meander to “illuminate” the LCD indicator?

Of course, the solution on MP is more beautiful, but on garbage it’s cheaper, and can only be solved on the knee... With MP programming, for example, I have a hard time (unless someone hands me a ready-made dump) - it’s easier for me with hardware.


Well, I'm willing to bet here. Let's do the math. For starters, the cost:
1. PIC12LF629 (SOIC-8) - 40 rub. (~$1.15)
2. Display from Motorola S200/S205/T190/T191 - about 90 rubles (~$2.57) In addition, the resolution is 98x64 - draw and write what you want.
3. Bulk (SMD shortcuts, buttons, SMD capacitors, etc.) at a glance - about 50 rubles. (~$1.42)

Total: ~180rub (~$5)

The case, the battery (I would choose the Lo-Pol battery from the same C200 motor scooter - compact, capacious, inexpensive (relatively)) - we don’t count it, since both are needed in both options.

Now your option:

1. LCI5-4/8 - about 50 rubles (~1.42 $)
2. K176IE4 (CD4026) - 15 rubles (~0.42$)x4=60 rubles (~1.68$)
3. K176LA7 - 5 rubles (~0.14$)x4=20 rubles (~0.56$)
4. Bulk (SMD shortcuts, buttons, SMD capacitors, etc.) at a glance - about 50 rubles. (~$1.42)

Total: ~180rub (~$5)

What's the benefit?

Now let’s estimate the performance characteristics and functionality:

The version with MK will have consumption maximum 20mA, while in your version, I think 1.5...2 times more. In addition, in your version - the complexity (relative) of a printed circuit board on 7 cases + multi-legged ILC5-4/8 (probably double-sided), the inability to upgrade the device (add or change functionality) without getting into the circuit (only at the software level), the lack of possibility organize memory for measurements (counting), power supply of at least 5V (with less you will not swing the LCI), weight and dimensions. There are many more arguments that can be given. Now the option with MK. I already wrote about the current consumption - 20mA max. + the possibility of a sleep mode (consumption - 1...5 mA (mainly LCD)), the complexity of the board for one 8-leg microcircuit and a 5-pin connector for a Motorola LCD is ridiculous even to say. Flexibility (you can do something like this programmatically, without changing the circuit or board - it will make your hair stand on end), the information content of the 98x64 graphic display cannot be compared with the 4.5 digits of a 7-segment LCI. power supply - 3...3.5V (you can even use a CR2032 tablet, but Li-Pol from a mabyl is still better). The ability to organize multi-cell memory for the measurement results (counts) of the device - again, only at the software level without interfering with the circuit and board. And finally - the dimensions and weight cannot be compared with your option. The argument “I don’t know how to program” will not be accepted - whoever wants to will find a way out. Until yesterday, I did not know how to work with the display from the Motorola S205 mobile phone. Now I can. A day has passed. Because I NEED it. In the end, you are right - you can ask someone.)) That's something like this. And it’s not a matter of beauty, but the fact that discrete logic is hopelessly outdated both morally and technically as the main element of circuit design. What required dozens of cases with wild total consumption, complexity of PP and huge dimensions can now be assembled with a 28-40 foot MK easily and naturally - believe me. Nowadays there is even much more information on MK than on discrete logic - and this is quite understandable.

Everyone knows why a microcalculator exists, but it turns out that in addition to mathematical calculations, it is capable of much more. Please note that if you press the “1” button, then “+” and then press “=”, then with each press of the “=” button the number on the display will increase by one. Why not a digital counter?

If two wires are soldered to the “=” button, they can be used as a counter input, for example, a turns counter for a winding machine. And after all, the counter can also be reversible; to do this, you must first dial a number on the display, for example, the number of turns of the coil, and then press the “-” button and the “1” button. Now, each time you press “=” the number will decrease by one.

However, a sensor is needed. The simplest option is a reed switch (Fig. 1). We connect the reed switch with wires parallel to the “=” button, the reed switch itself stands on the stationary part of the winding machine, and we fix the magnet on the movable one, so that during one revolution of the coil the magnet passes near the reed switch once, causing it to close.

That's all. You need to wind the coil, do “1+” and then with each turn, that is, with each turn the display readings will increase by one. You need to unwind the coil - enter the number of turns of the coil on the microcalculator display, and make “-1”, then with each revolution of unwinding the coil, the display readings will decrease by one.

Fig.1. Connection diagram of the reed switch to the calculator.

And, suppose you need to measure a large distance, for example, the length of a road, the size of a plot of land, the length of a route. We take a regular bicycle. That's right - we attach a non-metallic bracket with a reed switch to the fork, and we attach the magnet to one of the spokes of the bicycle wheel. Then, we measure the circumference of the wheel, and express it in meters, for example, the circumference of the wheel is 1.45 meters, so we dial “1.45+”, after which with each revolution of the wheel the display readings will increase by 1.45 meters, and as a result, the display will show the distance traveled by the bike in meters.

If you have a faulty Chinese quartz alarm clock (usually their mechanism is not very durable, but the electronic board is very reliable), you can take a board from it and, according to the circuit shown in Figure 2, make a stopwatch out of it and a calculator.

Power is supplied to the alarm clock board through a parametric stabilizer on the HL1 LED (the LED must have a direct voltage of 1.4-1.7V, for example, red AL307) and resistor R2.

The pulses are generated from the control pulses of the stepper motor of the clock mechanism (the coils must be disconnected, the board is used independently). These pulses travel through diodes VD1 and VD2 to the base of transistor VT1. The alarm board supply voltage is only 1.6V, while the pulse levels at the outputs for the stepper motor are even lower.

For the circuit to work properly, diodes with a low level of forward voltage, such as VAT85, or germanium are required.

These pulses arrive at the transistor switch at VT1 and VT2. The collector circuit VT2 includes the winding of a low-power relay K1, the contacts of which are connected in parallel to the “=” button of the microcalculator. When there is +5V power, the contacts of relay K1 will close at a frequency of 1 Hz.

To start the stopwatch, you must first perform the “1+” action, then turn on the power to the pulse shaper circuit using switch S1. Now, with every second, the display readings will increase by one.

To stop counting, simply turn off the power to the pulse shaper using switch S1.

In order to have a count for reduction, you must first enter the initial number of seconds on the microcalculator display, and then do the “-1” action and turn on the power to the pulse shaper with switch S1. Now, with every second, the display readings will decrease by one, and from them it will be possible to judge how much time is left until a certain event.

Fig.2. Scheme for turning a Chinese hanger into a stopwatch.

Fig.3. Scheme of an IR beam intersection counter using a calculator.

If you use an infrared photo sensor that works at the intersection of the beam, you can adapt the microcalculator to count some objects, for example, boxes moving along a conveyor belt, or by installing the sensor in the aisle, count people entering the room.

A schematic diagram of an IR reflection sensor for working with a microcalculator is shown in Figure 3.

The IR signal generator is made on an A1 chip of type “555” (integrated timer). It is a pulse generator with a frequency of 38 kHz, at the output of which an infrared LED is switched on. The generation frequency depends on the C1-R1 circuit; when setting up by selecting resistor R1, you need to set the frequency at the output of the microcircuit (pin 3) to close to 38 kHz. The HL1 LED is placed on one side of the passage, putting an opaque tube on it, which must be precisely aimed at the photodetector.

The photodetector is made on the HF1 chip - this is a standard integrated photodetector of the TSOP4838 type for remote control systems for TVs and other home appliances. When a beam from HL1 hits this photodetector, its output is zero. In the absence of a beam - one.

Thus, there is nothing between HL1 and HF1 - the contacts of relay K1 are open, and at the moment of the passage of any object, the relay contacts are closed. If you perform the “1+” action on the microcalculator, then with each passage of an object between HL1 and HF1, the microcalculator display readings will increase by one, and from them you can judge how many boxes were shipped or how many people entered.

Kryukov M.B. RK-2016-01.

The counter on the microcontroller is quite simple to repeat and is assembled on the popular PIC16F628A microcontroller with an indication output on 4 seven-segment LED indicators. The counter has two control inputs: “+1” and “-1”, as well as a “Reset” button. The control of the new counter circuit is implemented in such a way that no matter how long or short the input button is pressed, counting will continue only when it is released and pressed again. The maximum number of received pulses and, accordingly, ALS readings is 9999. When controlled at the “-1” input, the counting is carried out in reverse order to the value 0000. The counter readings are saved in the controller’s memory even when the power is turned off, which will save the data in the event of random interruptions in the supply voltage.

Schematic diagram of a reverse counter on the PIC16F628A microcontroller:

Resetting the counter readings and at the same time the memory state to 0 is carried out by the “Reset” button. It should be remembered that when you first turn on the reverse counter on the microcontroller, unpredictable information may appear on the ALS indicator. But the first time you press any of the buttons, the information is normalized. Where and how this circuit can be used depends on the specific needs, for example, installed in a store or office to count people or as an indicator for a winding machine. In general, I think that this counter on a microcontroller will be useful to someone.

If someone does not have the required ALS indicator at hand, but has some other one (or even 4 separate identical indicators), I am ready to help redraw the signet and redo the firmware. In the archive on the forum there is a circuit diagram, board and firmware for indicators with a common anode and a common cathode. The printed circuit board is shown in the figure below:

There is also a new firmware version for the counter on the PIC16F628A microcontroller. at the same time, the circuit and board of the meter remained the same, but the purpose of the buttons changed: button 1 - pulse input (for example, from a reed switch), button 2 turns on the counting for subtracting input pulses, while the leftmost point on the indicator lights up, button 3 - adding pulses - The rightmost point lights up. Button 4 - reset. In this version, the counter circuit on a microcontroller can be easily applied to a winding machine. Just before winding or unwinding turns, you must first press the “+” or “-” button. The meter is powered from a stabilized source with a voltage of 5V and a current of 50mA. If necessary, it can be powered by batteries. The case depends on your tastes and capabilities. Scheme provided by Samopalkin

Loading...Loading...