Arduino pulse counter. ATmega

Arduino pulse counter. ATmega

24.06.2023

Implemented the signal PWM 25 kHz. I don't have an oscilloscope, but I want to check the result. We make a pulse counter, check the work.

Task

On the base ATmega 328P implement a pulse counter to check PWM 25 kHz, the measurement accuracy to the pulse is not needed, but the order needs to be known.

Solution

The logic of the solution is simple, we track the impulses by which we increment the global variable for a second. The accumulated value will be the frequency of the incoming signal.

To read the pulses, we will use external interrupts, they are described on the pages 87-96 documentation from the manufacturer. IN Atmega 328P there are two inputs with which we can monitor external interrupts INT0(PD2) And INT1(PD3), to solve the problem, we use INT0.

Setting up external interrupts

The first step is to configure the port D as an input, and to avoid interference, I will connect a pull-up resistor.

To determine which events will trigger the interrupt handler, you need to configure the register ERICA. bits ISC00 And ISC01 responsible for INT0, A ISC10 And ISC11 behind INT1. The setting of monitored events is identical, with the difference in bits:

00 - Low signal level;
01 — Any logical signal change;
10 — Falling edge of the signal;
11 — Rising edge of the signal.

The register is used to directly enable interrupt inputs. EIMSK, bits INT0 And INT1 are responsible for the outputs of the same name. We write the code according to the above

Void int0_initial(void) ( DDRD = 0x00; // Port D as input PORTD = (1<< 2); // Включение подтягивающего регистра EICRA = (1 << ISC00) | (1 << ISC01); // Восходящий фронт сигнала EIMSK = (1 << INT0); // Включение входа прерывания sei(); // Разрешаем прерывания }

Handling external interrupts

Interrupts set up, now we need to process them. There is an interrupt handler for this. ISR(), which needs to specify the type of interrupt, in my case INT0_vect. In the function, we will increment the variable Tic_Count:

ISR(INT0_vect) ( Tic_Count ++; )

Result Output

To facilitate the output of the result, so as not to screw the display, I used an unclean ATmega 328P, A Arduino UNO And Arduino NANO, on board of which the same MK.

As I wrote above, the accuracy of measurements is not so important, therefore I will not set up timers, but simply in the main loop once a second I will display the accumulated value of the variable Tic_Count and reset it. For the duration of these actions, I stop processing interrupts.

Below is the complete code for solving the problem with comments:

#define F_CPU 1600000UL #include #include volatile unsigned int Tic_Count = 0; // External interrupt handler INT0 ISR(INT0_vect) ( Tic_Count ++; ) void setup() ( int0_initial(); Serial.begin(9600); ) void loop() ( cli(); // Disable interrupts Serial.println(Tic_Count); Tic_Count = 0; sei(); // Enable interrupts delay(1000); ) void int0_initial(void) ( DDRD = 0x00; // Port D as input PORTD = (1<< 2); // Включение подтягивающего регистра EICRA = (1 << ISC00) | (1 << ISC01); // Восходящий фронт сигнала EIMSK = (1 << INT0); // Включение входа прерывания sei(); // Разрешаем прерывания }

Now it remains to connect the PWM signal to the PD2 pin, and open the serial port monitor. You can also generate and check the signal on one MK.

The displayed readings are approximately equal to the previously calculated frequency, small differences are expected due to the implementation. For an accurate measurement, it is probably more correct to count the time between pulses and calculate the frequency from this.

This article contains all the data about the Arduino-based electricity meter, including diagrams, firmware, comments on the revision of the current firmware version and design.

This is what it looks like in the end.

Initially, I broke all the information into a big pile of little articles - which made it very inconvenient to search for it and repeat this device at all. This article corrects this situation.

Part 1. Idea, design and thinking out loud.

Some time ago I installed a dual zone electricity meter to take advantage of the better night rate (50% from 2300 to 0800). It turned out that we consume 45% of electricity at night. But the answer is how consumption occurs in the context of places of consumption. Of course this device does not.

Therefore, there was a need for a more detailed presentation of consumption data. Initially, it was decided to make a device showing the following data:

  1. Current load power
  2. Consumption since the beginning of the day
  3. Consumption since the beginning of the month
  4. Percentage of night consumption in %

Also, the device must transmit, to a configurable Internet address, consumption data for the last 24 hours, in the form of 24 readings. Transmission interval — set in minutes 1…120.

Parameters set in the menu:

  1. Hour in RTC
  2. Minute in RTC
  3. Day at RTC
  4. Month in RTC
  5. Year at RTC
  6. Counting interval 1…120
  7. network address indicating positional characters: “a-z0-9_-/: “. The character being edited must be highlighted so that it is clear what is being edited.

The initial version of the device will be made based on the following set of modules:

  1. (clarification regarding the connection of the indicator to the mega 2560)

The device is of interest to clarify how much the workshop, media devices, kitchen utensils consume. As a result, you need to get data in the form of graphs, on the Internet or on a local network server ()

The initial connection diagram of the measurement node.

I borrowed the scheme for measuring power and voltage. The average power is considered, and not only, many other parameters, such as frequency, power factor. First you need to assemble such a small stand for measurement.

I take a breadboard, look for a suitable transformer to measure the voltage (I take it from the ATX duty room), and go ahead.

UPD. Measuring unit

Part 2.1 Notes on the amazing features of the ENC28J60

Amazing thing. Today I started digging a module for working with the ezernet, for the "counter" project. Who would have doubted, it was fun, and everything worked out in the end.

By connection. We look where to find the SPI interface with Arduino "Mega", well, or yours. We connect. We hang the CS output (chip selection) anywhere we want, it is then set separately in the library initialization. I "hung" it on the 42nd pin, you may have some other one. The remaining MOSI / MISO / SS / OV / 3.3V are connected to the corresponding Arduino pins.

It turned out that in order to reduce memory usage, the developer of the "wonderful" EtherCard library decided and sent some strings for a GET request to the program's memory. That is, imagine a freelance programmer suddenly decided to make himself a counter. To make everything smart, he decided to edit the URL line where the data is sent there. And even did this today:

And so, he connects the library, and thinks that now he will easily make a request to an external server. An no. After all, he set the server as a string. A string, unfortunately, is not program memory. Harvard architecture. Everything is divided.

Nothing, I quickly climbed into the library, found the place where the request was filled out, distorted it, took away all the “extra” in my opinion, of course. In the end, everything works great.

I am attaching a library and an example of working with a server that works for strings. and not only for non-changeable values ​​in the program. Along with an example -

In the course of the project, it remains only to solve the problem with the measuring part, everything else has already been solved. The most difficult thing in the program was editing the URL string.

The connection feature is only DHCP, I'm not going to do static ip and selection tasks, everything works quite correctly, and there is no need to add functionality that I don't need.

Part 3. Initial Debugging of the Counter Software

Today I tinkered a little with debugging the counter software. The fact is that I did not mistakenly install a step-down resistor, too much voltage penetrated the CT sensor and, as a result, too much noise penetrated the input. Corrected, soldered 150 ohms parallel to the ST sensor, in general, about 100 ohms came out.

I had to slightly correct the coefficients in the program. I adjusted ... according to the Chinese counter. Then on a voltmeter. Got it as close as possible.

As a result, measuring the EH consumption for boiling the kettle showed the same thing as on the Chinese wattmeter. It's already good, but I'll have to check on the main counter, somehow.

The letter h after kW did not fit on the display, but it should be understood that it is there. The number shows the consumption since the beginning of the current hour. At the end of the hour, it is sent to the server and reset to zero. Then, probably I will make it reset once a day.

Counter software, in its current form -

Part 4. Making the first part of the body

I made a case today, the material is the same as last time - 11 mm caprolon. Fastening is true on M4 imbus screws, last time there were M3 everywhere. It's too weak for the body.

For scale, put the mouse "air" inside.

It remains to make the front panel, fix the modules, make milling for USB and 12V power. In the case of this device, probably 0.7A will be enough, that is, something small-sized can be used.

Part 5 Making the front panel

Part 9. Updated software, based on the results of the operation of the device

During the operation for about one month, I came to the conclusion that it is necessary to add the transfer of the current consumed power, first of the month. In addition, I moved the collecting web server inside my subnet, and stopped transmitting data outside. Because some didn't make it. Thus, the reliability of data collection has increased. Well, actually, here is the latest firmware - .

Upd 2015-09-23. Today I wrote an interface for viewing monitoring data. At the same time, I optimized the firmware, found errors in it. I raised the internal DNS server, on "" this is a matter of minutes.

Just showed the last 48 hours (I lost the statistics, so there is less on the chart) in the form of a smoothed chart. Splash is the beginning of the washing machine, according to U - the price in hryvnia for the current hour, taking into account the nightly rate, of course. By X — date/time.

Now we can take a look at what's going on. A small nuance - I placed everything on the home network, for greater stability.

I already wrote earlier that I tried one standard software to show the consumption of electricians (moncms). I don't understand the paradigm and approach. There, every three seconds it sends data to the server, and shows something. I did it differently - the device accumulates data for 1 hour, then sends it for the last 24 hours. The web server is not running, it's a low power NAS.

UPD. It turned out that this is not the Internet I have, this device sometimes does not transmit data. It is not clear what is connected with, and it is difficult to catch, so I went the other way - by calculating intermediate readings based on the current consumption. For a day somewhere 1-2 times there is a failure. This scheme allows you to refuse to store hourly data in its industry, which also does not work quite correctly for some reason.

UPD. Completed some software for the site showing data. Now there is a voltage by the hour, hourly and daily expenses.

I'm thinking about hosting the software on github. Maybe. so it will be.

No, this article is not about another way to deceive this ill-fated device. Here's how to use Arduino and LabView to turn your electricity meter into a power monitor or even an ammeter!


The very first electricity meter was induction. The principle of its operation is ridiculously simple - in fact, it is an electric motor, the rotor of which is an aluminum disk that rotates the dial. The more current it draws, the faster the disk spins. The device is purely analog.

However, today induction meters are losing ground, giving way to their cheaper electronic counterparts. And just one of these will become experimental:

The principle of operation has not changed much - in this case, the disk is replaced by electronics that generate pulses in accordance with the amount of electricity consumed. As a rule, in most devices, these pulses are shown by an LED indicator. Accordingly, the faster this light flashes, the more precious kW is burned.
In addition, on the front panel of any device there is a counter ratio A- number of pulses per 1 kWh. As can be seen from the photo, the experimental A = 12800. From this information, the following conclusions can be drawn:

With each pulse, the meter records a consumption equal to 1/12800 of 1 kWh. If you turn on the load to the meter and start simply counting the pulses, then it is easy to get the amount of electricity consumed by it (kWh) by dividing the number of pulses by the gear ratio.

Since the indicator changes the speed of its blinking, it is possible to deduce the relationship between power (kW) and the time of one meter pulse, which will allow obtaining data on power / current.
We will not load the article with calculations, but if necessary, then

here they are

Truly, the gear ratio of the meter is a great thing, since knowing it, you can express both power and current:
Let's make a proportion from our gear ratio (A=12800 imp/kW*h) and unknown gear ratio, which will be at load X and during one single pulse (light blinking):

Here X is the unknown power and t is the time of one pulse. We express the unknown power from here and here it is:

The current is calculated using the following proportion of gear ratios and known and unknown currents at load X.:


Which, in general, leads to an identical formula, but for current (current is measured in Amperes and the indices mean the load at which this current will be):

Here you can see a pitfall - you need to know the current at an ideal load of 1 kW. If good accuracy is needed, it is better to measure it yourself, and if not, then you can approximately calculate it using the formula (voltage and power are known), but it will be more rough, since the power factor is not taken into account.


Thus, everything rests on measuring the time of one impulse (blinking of the indicator). In my research, I relied on this excellent project. A certain Italian made an interface for monitoring power in the Labview environment and came up with a circuit for measuring pulses. But there was a huge flaw in his project - it was only suitable for meters with a gear ratio of 1000 imp / kWh.

The upper graph is the average power over 5 minutes, the lower graph is in real time. The interface is quite flexible and can be easily modified to suit your needs. If you have not dealt with the LabView environment yet, I recommend getting acquainted.

For everything to work, it turned out to be enough to introduce one single block into the program algorithm, in accordance with the formula above.

It looks like this


It would seem simple, but before that you still need to think of it!

So, if you still decide to implement power monitoring, then there are two options:

1. Your counter is closed and sealed to the best of your ability. This means that pulses can only be read using a photoresistor that reacts to the blinking of a light bulb. It must be attached with blue electrical tape opposite the LED indicator on the front panel of the meter.
The schema will look like this:

Scheme for non-contact pulse pickup


The program simply compares the resistance value on the photoresistor and the potentiometer. Moreover, the latter allows you to set the sensitivity of such a sensor in order to avoid false alarms and adjust to the brightness of the indicator.

2. You have access to the meter's pulse output. Many models have a pulse output that duplicates the blinking of a sweetheart. This is done in order to be able to connect the device to the automated accounting system. It is a transistor that opens when the indicator is on and closes when it is off. Connecting directly to it is not difficult - it requires only one pull-up resistor. However, before doing this, make sure that this is a pulse output, and not something else! (there is always a scheme in the passport)

Scheme for connecting to telemetry output


In my case, access is full, so I didn’t bother too much. Install LabView and start measuring! All graphs represent power (W) in real time.
The long-suffering teapot was the first to be handed out. The cap says that it has a power of 2.2 kW, but judging by the schedule, it regularly consumes only 1700 watts. Note that consumption is more or less constant over time. This means that the heating element (most likely nichrome) changes its resistance very little during the entire boiling process.

A glue gun is a completely different matter - the declared power is 20 W. It behaves in accordance with the laws of physics - when heated, the resistance of the heater increases, and the current decreases accordingly. I checked it with a multimeter and it's all there.

Old radio receiver "Spring". Here the graph went up at the beginning due to the fact that I started the measurement during the impulse, and accordingly this affected the data. The slides on the graph show how I twisted the volume knob. The louder - the more the radio eats.

Perforator with a declared power of 700 watts. I pressed the button all the way, waited a little bit and let it go, but not smoothly. The graph clearly shows the inrush current when starting the engine. That is why the light blinks when a good neighbor starts pounding on his beloved wall.

And now the most interesting. I did a little experiment with my old laptop, the result of which is shown in the picture:

The orange dot marks the time when I ran several "heavy" programs at once. As you can see, CPU load graphs and increased consumption have something in common. Recently was

For an additional task

circuit diagram

Scheme on the breadboard

note

    In this experiment, we are using an IC for the first time, in this case the 74HC595 output shift register. Microcircuits are useful in that they allow you to solve a specific problem without assembling a standard circuit each time.

    The output shift register gives us the ability to "save" the digital outputs by using only 3 instead of 8. The register cascade would allow 16, and so on. signals through the same three pins.

    Before using the microcircuit, you need to carefully study the diagram of its connection in the datasheet. In order to understand where to count the legs of the microcircuit, they have a semicircular notch on one side. If we position our 74HC595 with the notch to the left, then the bottom row will have legs 1-8, and the top row 16-9.

    In the schematic diagram of our experiment, the legs are arranged in a different order so that there is no confusion in the connections. The pin assignments according to the datasheet are signed inside the microcircuit image, the leg numbers are outside.

    Recall that on the image of the seven-segment indicator, the numbers of its legs and their correspondence to the segments are signed.

Sketch

In order to transfer a portion of the data that will be sent through the shift register further, we need to apply LOW to the latch pin (input ST cp of the microcircuit), then transfer the data, and then send HIGH to the latch pin, after which the transmitted combination of high and low signal levels will appear on the corresponding outputs of the 74HC595.

We used the shiftOut(dataPin, clockPin, bitOrder, value) function to transfer data. The function does not return anything, and as parameters it needs to be told

  • Arduino pin, which is connected to the DS input of the microcircuit (data pin),

3

Not only can you do it without an interrupt handler, you can do it with little or no software and deal with the faster pulses that are possible with software polling or interrupt counting.

Atmel AVR that most Arduinos are based on counter/timer hardware that will count the pulse at the input pin directly. All you have to do is set up the counter hardware and read the counter register. There is a slight complication for 16-bit counters on an 8-bit device, but this is easily overcome. The Arduino sets up timers for PWM operations by default, but this can be overridden as described (see the AVR user manual for details) - you need to use the timer/counter in CTC mode.

Arduninos based ARM and just about any other microcontroller will have similar hardware; some are more flexible so that pins can be used to count equipment.

On the AVR you have 8 and 16 bit counters, if you need large counts you may have to handle an overflow interrupt. If you check the counter regularly, you can handle even that without interruption, being able to poll at a much slower and possibly aperiodic rate than the input pulse rate by simply polling the overflow flag before the next overflow.

In your case, you probably need to read the number of pulses in a regular period, which is less than the time that the counter will overflow at the maximum expected pulse rate. So, for example, if you were using an 8-bit counter and the maximum heart rate was 1kHz, you would need to poll every 256/1000 seconds or less, but you can get the most accuracy by making this period as long as possible. So, for example, you could have something like the following (this is not real code, just a snippet):

For(;;) ( delayMS(250) ; frequency = 4 * readCounter() ; )

An alternative that will get a more linear response, but a non-deterministic count, will interrogate overflows and measure the time it takes to count a fixed number of pulses, and therefore define your measurement from the time for a fixed count, not to a count within a fixed time.

For(;;) ( int start = getMillisec() ; while(!counterOVF()) ( // Do nothing (or something useful but quick) ) int t = getMillisec() - start ; frequency = 256 * t/1000 ; )

0

Thank you very much for your question. If I understand correctly, your first idea is to turn off the pulses via hardware, and the second is all the time the CPU is busy. The problem is that my microcontroller is fully loaded (so a simple ISR incrementing the counter variable won't work) and can't be polled because it has to do other tasks. Also, I no longer have hardware counters. Are there other alternatives? I have heard that this is possible using the analog ports (relying on similarity to PWM). Thank you very much - manattatta Aug 28 14 2014-08-28 08:16:36

0

In both cases the hardware counter does the counting, in the second example my poll checks for the overflow flag, but that's just to demonstrate the principle, it's not a fundamental decision; it can equally be an interrupt handler - the advantage is that you get one interrupt for every 256 pulses (assuming 8 counter bits) rather than every pulse, so the interrupt overhead is much lower. - Clifford Aug 28 14 2014-08-28 11:10:07

0

You can only use an analog input if the sensor's output is a fixed PWM frequency (and you've added suitable analog filtering with a cutoff slightly below that frequency), but your question implies that it's a variable frequency, not PWM (otherwise how would pulse counting help?). -



© 2023 globusks.ru - Car repair and maintenance for beginners