Creating an Arduino Controlled Charger

Arduino PWM controller solar charging
How to make a very small, simple and cheap PWM solar charging controller with Arduino Pro Mini for 12V off-grid setups. The PCB size is the same as Pro size mini-boards so they can be clamped together. PCB plans for a universal prototype board.

Connecting and using this Arduino solar charge controller is very simple - there are 2 input wires from the panel solar panels(+ and -) and 2 outputs lead to a lead-acid battery. The solar panel base and batteries are connected together. Any load must be connected directly to the battery terminals and the charge controller will automatically handle the rest.

Arduino regularly measures the lead and acid battery voltage according to a certain value, switches to the MOSFET to charge the battery from the solar panel and switches the MOSFET to turn off when the battery is fully charged. When the load draws power from the battery, the controller detects the voltage drop and immediately begins to charge the battery again. During the night, when the solar panel stops producing, the controller waits until the panel starts outputting again.


The positive wire to the solar panel requires a protective Schottky diode installed directly on the cable (wrapped in heat shrink tubing). This is not included in the main PCB as this makes it easier to replace it and cool down at the same time. You can easily make the board a little longer to fit a different type of diode.

Circuit and Function Description:

The function is based on an N-channel MOSFET transistor IRF3205 in the high side of the circuit. This requires a gate voltage higher than 12V to turn on the MOSFET correctly. To eliminate the need for an external MOSFET driver, it is driven by a charge pump created with diodes, 2 capacitors and two Arduino PWM output pins (3 and 11). Pin A1 measures battery voltage and pin 9 controls the MOSFET ON/OFF cycle. The Arduino Pro Mini integrated LED connected to pin 13 is used to show the current cycle of the PWM signal.

The voltage regulator and all the capacitors around (C6, C5 and C4) could be eliminated since there is a regulator included in the Arduino Pro Mini. However, because I was using a cheap clone board, I don't want to rely on its ability to support more high voltage than 12V for longer periods of time. The LP2950 is very cheap and efficient up to 30 volts, so it's worth having on board anyway.


Parts List: Low Power Voltage Regulator LP2950ACZ-5.0 Transistors 2N3904 2N3906 x 2 N-channel MOSFET IRF3205 Resistors 82K (1%) 20K (1%) 220K x3 (0.4W is enough) 4K7 (0.4W is enough) Diodes 1N4148 x 5 P6KE33CA 90SQ035 (or any similar 35V minimum 9A Schottky diode) Capacitors 47N/50V x2 ceramic 220P/100V ceramic 1M/50V (1000nF) ceramic 4M7/10V tantalum 1M/35V tantalum x 2

The circuit and code for this charge controller is by Julian Ilett, he is the mastermind behind this smart thing. All this is just refined documentation and suitable PCB design to perfectly match the Arduino Pro Mini board. He shares a video of a more efficient Arduino MPPT charge regulator, but its construction is much more complex and the project is not yet complete. If you can improve the code or design in any way, please share your improvements in the comments.

Several years ago, I set myself the task of developing a set of inexpensive devices that would allow blind people to better adapt to the world around us. To date, I, together with a team of like-minded people, have managed to implement several projects.

In this article I want to talk about the ultrasonic attachment on the cane and the ultrasonic key fob - full-fledged devices that are assembled from inexpensive, available modules.

An ultrasonic attachment for a cane and an ultrasonic keychain are devices for blind people, which warn of obstacles above the level at which they can be detected with a regular cane. Such obstacles can be high-riding cars, barriers, high fences. The ultrasonic attachment is attached to a regular cane, and the ultrasonic keychain is hung around the neck or carried in the hand like a flashlight.

The operation of the devices is based on the reflection of ultrasonic waves from obstacles. By measuring the time difference between the moment the pulse is generated and the moment the reflected echo signal is received, the distance to the obstacle can be determined.

To develop devices, it is necessary to select a sensor for measuring distance, a control board and a signaling device, select batteries, a method for charging them, and suitable housings.

Ultrasonic sensor

To measure the distance to an obstacle, two devices were tested:
  • Arduino Compatible Ultrasonic Module HC-SR04
  • Car parking sensors HO 3800
Both devices work on a similar principle. The differences lie in the directional pattern of the sensors, the maximum obstacle detection range and design.
Comparison of sensor parameters:

During the tests, it turned out that the HC-SR04 modules have a slightly worse ability to detect obstacles and operate in difficult climatic conditions (cold).

Both sensors, despite their differences, can be used in an ultrasonic cane attachment as a means of measuring the distance to an obstacle, so the main parameter for us when choosing a sensor was the price. We settled on the cheaper HC-SR04 sensor.

Control board

The Arduino platform was chosen as the control board. In our case, the most applicable boards are miniature versions: Arduino Mini, Arduino Nano or Arduino Pro Mini. IN general case any other controller that provides similar capabilities can be used.

Batteries

To provide power to the device, it is advisable to use lithium-ion (Li-ion) or nickel-metal hydride (Ni-Mh) battery cells.

When operating in normal climatic conditions, it makes sense to use Li-ion batteries, which have the following advantages compared to Ni-Mh:

At low temperatures, it is preferable to use Ni-Mh batteries.

The voltage at the output of one Ni-Mh battery (1.0 -1.4 V) is not enough to operate the device. To obtain a voltage of 5 V (necessary for the operation of both Arduino and the parking sensor), in addition to batteries, we will use a boost DC-DC converter.

To operate the DC-DC converters we have selected, it is necessary to provide an input voltage of 0.9-6.0 V. To obtain the required output voltage, one could use one Ni-Mh element with a voltage of 1.2 volts. However, as the input voltage decreases, the load capacity of the converter also decreases, so for stable operation It is advisable to supply the device with at least 2 V to the input of the converter (two Ni-Mh elements of 1.2 V each or one Li-ion element with a voltage of 3.7 V). Note that there are DC-DC converters for which an input voltage of 1.2 V is not enough.

Charging batteries

For Li-ion batteries There are many ready-made inexpensive modules with end-of-charge indication.

In the case of Ni-Mh batteries, everything is more complicated. We have not found any ready-made embedded solutions on the market at the moment. To charge Ni-Mh batteries, you can use specialized external chargers or create your own charging circuit.

One way to charge a Ni-Mh cell is serial connection with a battery of two linear stabilizers LM317 (or similar): the first - in current limiting mode, the second - in voltage limiting mode.

The input voltage of such a circuit is 7.0-7.5 V. In the absence of cooling of the stabilizers, it is not recommended to exceed this voltage. The voltage on each Ni-Mh battery during charging should be about 1.45 V (voltage of a fully charged Ni-Mh cell). To avoid overheating and failure of microcircuits, the battery charging current should not exceed 100 mA and can be increased to 200 mA when using appropriate radiators.

The advantage of this charging scheme is that there is no need to control the charging state: when the required voltage on the element is reached, the current will automatically drop to a safe minimum.

Alarm

Depending on the choice of warning channel (auditory or tactile), select actuator– buzzer or vibration motor. In addition, you can combine both notification methods, giving the user the ability to switch between them.

During testing of prototypes, we found out that it is most convenient to transmit information about the proximity of an obstacle through vibration, because in this case, the audio channel, which is very important for a blind person, is not occupied. That's why all of our designed and assembled products use vibration to warn of obstacles. The intensity of vibration is proportional to the distance to the obstacle.

Frame

We were unable to find a convenient housing for the ultrasonic cane attachment among the mass-produced housings. To test the device, we used a 3D printed ABS plastic case. To print the case on a 3D printer, we developed the following 3D model:

Test result of prototypes

During the development process, more than 12 product options were collected. Each new product eliminated the shortcomings of the previous ones: during the development process, we reduced the dimensions and weight of the product, selected ultrasonic sensor, satisfying us both in price and in technical specifications, abandoned the use of an audio channel and optimized the device operation algorithm. Together with the blind (Bortnikov P.V., Shalintsev V.A.), tests of all assembled products were carried out. As a result, we obtained the final sample.

Below is a schematic electrical diagram of the developed device:

When disassembled, the ultrasonic neck keychain looks like this:

All components used in the assembly, except for the 3D printed housing for the cane attachment, were purchased through AliExpress:

  1. Ultrasonic sensor HC-SR04.
  2. Adruino Pro Mini control board.
  3. Rechargeable battery 3.7 V 300 mAh.
  4. Voltage converter 0.9V ~ 5V to 5V 600 mA.
  5. Charging module AC/DC 220V to 5 V 1 A.
  6. Charger LA-520W.
  7. Alarm: vibration motor for mobile phone 4x10mm DC 3V.
  8. Button PB-22E60.
  9. Housing Gainta G1906 (for key fob).
  10. Transistor: bss138/bcr108 or optocoupler CPC1230N.
The appearance and prices (including delivery from China) of the components used to assemble the ultrasonic head on the cane are shown in the figure:

Of the components used during assembly, the largest contribution to the cost of the device is made by the 3D-printed housing.

The appearance and prices (including delivery from China) of the components used to assemble the ultrasonic key fob are shown in the figure:

In the future, you can develop a mount for the Gainta G1906 body and use a device with such a body as an attachment for a cane.

One of the ways to reduce the cost of devices is to save on labor costs and the cost of delivering device components to Russia by deploying production directly in China.

The devices we have developed have the following characteristics:

After conducting preliminary tests of the devices, we were forced to limit the obstacle detection range to 1.5 meters in order to avoid unnecessary triggering when using the devices in a crowded environment. With a continuous change in the vibration level, it is more difficult to determine the approach of an obstacle, so based on the results of preliminary tests, we settled on three levels vibrations.
Appearance of the ultrasonic attachment on the cane:

Appearance of the neck keychain:

A 3D model of the ultrasonic cane attachment and the firmware source code for Adruino are available for download at

Good old "Rectifier"
B14 charger"!
You were always like a savior:
Helped us out, dear one!

In the heat and winter cold
Revived the battery;
Even if I have a cold
You are like a robot Terminator!

Didn't break, didn't give up
Even in the most difficult hour;
When necessary, I tensed up,
Charging everything for us.

Forty years have already flown by
Since the good Brezhnev times,
When your body is like a body
It was sealed at the factory.

And you've been serving well ever since.
You are for the benefit of all machines,
Different from the Union
Because the truth is indestructible.

But it's time to change
Throw off the heavy burden of time,
So that you can rise up,
So that Hawking becomes smart.

If anyone asks in falsetto
“How can I do this?” -
Don't worry, I'm talking about it
In this article I will tell you.

A moment of addiction.

Greetings, dear readers! After an almost four-month break, I am back in business and, as a report on the work done, I consider it necessary to write this article. I thought for a long time about where to start, well, not to post for the fourth time about zero visibility, etc. - this quote has already worked for me regularly over the last three articles, so that’s enough for it - let it go to a well-deserved rest! Well, in the meantime, I’ll use a new experimental trick, let’s call it a “minute of drug addiction” - such a fun and relaxed moment of “hello”, smoothly leading to the main idea of ​​​​the article. 🙄

So, as already announced in the “minute”, today I will tell you about how I turned an old charger from the early seventies into a new, modern one, controlled by a microcontroller. This thought came to me because my friend invited me over for a beer while my battery was charging. I would have been happy to go, but bad luck - the charger had to be constantly monitored! Run to it once every half hour, or even more often, to check the voltage on the battery, and if it exceeds the maximum, reduce the power with the appropriate switch on the front panel. Agree, it’s inconvenient: you are constantly chained to a charging battery and cannot move anywhere, and if you suddenly miss the right moment, the battery will not thank you. On the other hand, he won’t say it anyway: he’s a monument who doesn’t know how to speak))))

Jokes aside, I’ve long wanted to do something serious on Arduino, which I met back in November, picking up a treasured package from the Chinese from Aliexpress with a microcontroller, shield and other goodies in the mail. And here it is, a great opportunity - take it and do it! So I took it and started doing it directly!

Charger circuit

First, I’ll give you a very clickable diagram of the finished device:

List of main components

  • 8 capacitors: 2 of 22 pF, 1 of 100 pF, a couple of pieces of 100 mF, and for power supply - one large one of 6.3 volts and two large ones of 16, for example, and 1500 mF, respectively (all can be 16 volts or more, doesn't matter).
  • Programmable microcontroller Atmega328 with 16 MHz quartz and preferably a shield for it (scroll through a few pages to the first shield, this will be the cheapest option) to make flashing convenient.
  • For the same reason - clamping sockets for the above-mentioned microcircuit. Although you can get by with regular ones as an economical option. Well, or solder the wires to the MK and flash them with another Arduino or flasher - as you prefer.
  • 9 KT315 and 1 KT815 transistors (or analogues) - unsoldered from any old Soviet equipment.
  • 8 white diffuse LEDs and 1 green.
  • 9 relays with 12 volt coils: one for 220 V, four for 12 V 16 A and four smaller ones for 12 V 12 A. The last 8 need to be as small as possible.
  • 40 resistors: 15 560 ohm, 12 kilo ohm, 8 ohm, 2 10k and one each of 3k3, 4k7 and 30k.
  • A couple of diodes for 12 volts: one for half an ampere, the second at least for an ampere, a reserve will not hurt. It is soldered from anywhere, for example from dead power supplies.
  • Some kind of light bulb, maybe an LED with a resistor, burning from 220 volts. Actually, a neon girl would look cool there!
  • A sixteen-segment screen from an old system unit to display the current voltage on it. Well, or three seven-segment ones. Or even hammer in a bolt to display the current voltage: this, after all, automatic device, it controls the voltage itself, you don’t need to know it, in extreme cases you can measure it with a tester. Instead of a screen, you can just put a couple of LEDs so that the arduino will blink with them, they say, I’m not frozen, I’m working, everything is under control! (No, I have never seen a frozen Arduino, but nevertheless, you need to be prepared for anything.) 🙄
  • 3 shift registers 74HC595
  • Well, something like halves of a circuit board like this (I bought 10 pieces on eBay for a glass of compote):

I would like to note that almost all the components used in this project do not have exact ratings and can be replaced with similar or similar ones either with minimal adaptation of the circuit and firmware, or without any changes at all. I tried to use those parts that were literally lying around at my fingertips: for example, I recently soldered the vast majority of the resistors and transistors used here from an antediluvian Vilma tape recorder, the remains of which, after unsoldering, were safely sent to a landfill. So the amount spent on the purchase of parts for this device does not exceed $15, and most of the budget was spent on relays.

Original charger version

Unfortunately, I did not have a photo of this charger in original condition, so all I can offer you is at this stage- photo with the cover already removed, the mechanical part of the power switch unscrewed (on the left) and the handle of this switch (on the right). Its electrical part sticks out from the top of the device. Also removed from its original hole is the voltage switch (6 or 12 volts):

After carrying out the above manipulations, I also unsoldered the power wire from the fuse and the primary winding of the transformer, although it still lies in the right top corner next frame. But don’t get too used to him - I found him excellent replacement, so you won't see him again.

Operating principle of the original device

The charger itself is built on a simple principle - 220 volts are supplied to the primary winding of the transformer, and accordingly, alternating voltage also appears on the secondary winding. Power can be controlled due to the fact that secondary winding there are several conclusions (9 in total). This means that between the first and each of the subsequent eight pins everything is obtained. large quantity turns, and the more turns, as you know, the higher the voltage (that is, current or power - as you wish). These 8 pins go to the same switch with which you select the current battery charging power.

It turns out that between the first terminal of the secondary winding and the output from the switch we have the alternating voltage selected by this switch. But they still cannot charge the battery, because to do this it needs to be turned into a permanent one, that is, straightened. Hence the name of this device- rectifier.

For straightening AC voltage This charger uses such a simple and reliable thing as a diode bridge, consisting of four powerful D242 diodes mounted on individual radiators and fixed to a dielectric substrate. So from the switch the current flows first to the input of the diode bridge, and then from its output through the ammeter to the battery.

Selecting a method for switching secondary windings

Most main problem This project was the choice of the method of switching the above-mentioned secondary winding terminals. There were many options, but I immediately decided to try the most crazy and unreliable of them, but the simplest in terms of labor costs - connecting a servo drive instead manual switching switch positions:

I attached the servomotor to the switch, quickly wrote the firmware and tried to turn it, but, as it turned out, there wasn’t enough power and sometimes it got stuck in the most critical place, so this option, alas, didn’t work.

Oh yes! I almost forgot! In fact, there were not 9 but 10 terminals from the secondary winding, the first two were one for six volts, the other for twelve, both went to the toggle switch, and only then to the diode bridge:

But since I did not plan to charge the batteries at 6V, I refused this function, so I threw out the toggle switch (from the design, not in general) and insulated the wire for six volts, and ran the twelve-volt wire from the transformer directly to the diode bridge.

So how do you still commute? Here it is either transistors, or thyristors, or using relays. And I chose the last option, because relays are smaller than transistors/thyristors and, unlike them, do not heat up at all if you take them with a current reserve. That’s what I did - I bought 8 small relays with coils for 12 volts, 4 pieces for 16 amps and 4 for 12 amps. In size, they just fit into the free space inside the charger case:

Device operation algorithm

And here, having finally decided on the method of switching the outputs of the secondary winding, I consider it necessary to make some “literary additions” and talk about the algorithm for the operation of the device. Initially, to compile it, I simply analyzed my actions while charging the battery with this shaitan machine and, based on this, began to sketch out the first strokes of a new sketch, which you can pick up. I'll often quote bits and pieces of it to help you understand what's what, so if I were you, I'd open it right now and study it as I go along.

First, let's enter 3 the most important parameters:

// Maximum voltage * 10
byte maxVoltageX10 = 148;

// Voltage * 10, at which it is no longer possible to increase power
byte powerUpMaxTreshold = 142;

// Voltage * 10 at which the power will be forced to increase
byte powerUpMinTreshold = 136;

They are multiplied by 10, firstly because when calculating them it is more convenient to use integers - no rounding, etc., secondly because such numbers are actually displayed on the screen, and the comma is, as it were, virtual , so there is no need to do unnecessary calculations in the code, and it is clear that these are 14.8, 14.2 and 13.6 volts, respectively.

The first parameter tells the program the maximum permissible voltage, if exceeded, the power will be reduced by one level, and if there is nowhere to reduce it, the charger should simply turn off.

The second parameter will be used at the beginning of the charging process - after switching on, the power will increase until the voltage on the battery is less than the value it sets.

The third parameter was introduced specifically for cases when the battery connected to the car will be charged. For example, someone turned on the radio -> the voltage dropped below this value -> we increase the power. But what if the load that drops the voltage to this level is short-term (turning on the headlights or the cigarette lighter), or periodic, with a certain frequency (for example, from the impacts of a subwoofer), and will come out in such a way that as soon as the brains increase the power, it will be needed immediately reduce, then immediately increase again, etc.? The result will be a vicious circle, the relays will constantly click, wearing out, and for the battery, perhaps, this will not be very useful... Especially for this, we can make our system self-learning, as it were, by entering additional parameter:

// If less than this many milliseconds have passed between increasing power by powerUpMinTreshold and decreasing it, then powerUpMinTreshold will decrease by 1
unsigned int powerUpMinTresholdTimeout = 60000;

As you can see from the comment, thanks to this parameter, powerUpMinTreshold will decrease by one tenth of a volt each time the brains decrease power less than powerUpMinTresholdTimeout milliseconds after increasing it. That's it, the problem is solved: they click the relays once, click a second time, and by the third time they will think 10 times before clicking. Ha-ha-ha, they contacted the wrong people!

Well, we seem to have more or less figured out the basis of the algorithm, now let’s move on to the details and nuances.

I immediately planned that the entire system would be powered from the battery itself, and 220 volts would be connected through a relay controlled by the brain (that is, Arduino), thanks to which we would be able to turn off the power supply to the device in case emergency situation or when the battery has finished charging. Moreover, there will be less sparking from the relay than from inserting a plug into the socket, so this option is also more reliable. Naturally, its connection will be written below, because for now we are discussing only theoretical issues.

The switching process will occur as follows: first you will need to plug the power plug into the socket, after which, of course, nothing will happen, and then you will need to connect the battery itself, and if the voltage on it is more than eight volts, the whole system will start up and begin to charge it . But here another tricky parameter comes into play:

// Delay in milliseconds before charging starts
unsigned int powerOnDelay = 2000;

It is needed in order, for example, to reduce sparking in the relay block, with the help of which the terminals of the secondary winding of the transformer will be switched in the final device, because on the first relay of the relay block the current will be higher than on the relay supplying power to the transformer, in addition If something happens, this second relay will be much easier to replace. That is, when the battery is connected, the power will first rise to one, and then, after this delay, the power relay will turn on. These four lines of code in the power increase procedure are responsible for this:

if (powerLevel == 1) (
delay(powerOnDelay);

}

In general, this conditional operator could be specified so that it is executed only once when first turned on, but, in theory, if this happens later, when the power drops to the first level from higher ones, nothing will change, the relay will be turned on anyway , so I decided not to plant an additional garden.

By the way, there is a very interesting parameter in the code:

// Power level (initial)
byte powerLevel = 0;

He, as you may have guessed, sets First level power and was introduced at a very early stage of firmware development and is currently used there simply as the current level. The curious thing is that if we now increase it, then the condition described in previous paragraph, will never work, that is, 220 volts will never reach the primary winding of the transformer, which means the device will not charge the battery. Pichalka.

Well, okay, let's not talk about sad things. Let's say we turned on the device and charging began. Everything is fine, but do not forget that after increasing the current, the voltage on the battery does not rise instantly, and if you do not make delays before increasing, then after switching on the brains will instantly transfer the power to maximum level, but this is incorrect, which is why the following parameter is entered:

// Time after which the power can be increased by one level, in milliseconds
int powerUpTime = 5000;

That is, at least 5000 milliseconds will have to pass between two power increases, during which the voltage can already rise above the powerUpMaxTreshold and then there will be no need to increase the power.

As for reducing power, everything is generally simple: the program periodically checks whether the current voltage exceeds the maximum permissible level, and if it does, the power must be reduced:

// Power down
if (voltageX10 > maxVoltageX10) (

But if this condition is met, there must be two options for the development of events. The first is when the current power level is greater than one:

In this case, we need to set the power to a lower level and continue charging. Otherwise, when the power level was already at its lowest, we simply turn off the power and blink the screen. We smile and wave, in short, the battery is fully charged!

In general, as practice has shown, those batteries that I charged could be safely removed from charging even at the second power level, because the current already dropped below 500 mA. However, you should not neglect the auto-shut-off function - there are different types of batteries...

Also, for reducing power there is a delay parameter, similar to the powerUpTime parameter for increasing:

//Pause after power reduction, in milliseconds
int powerDownPause = 500;

True, it is implemented more simply, through the usual delay() after direct reduction. I figured that half a second is not such a long interval to use it as additional condition in the selection statement, but to each his own, so if one of you has nothing to do, first of all you could modify this piece of code according to the powerUpTime principle.

It’s amazing how I’ve already written so much and haven’t said where I actually get the current tension from. Correcting:

void loop() (
ct=millis();

It turns out that at the beginning of each iteration of the loop, which, as you know, simply repeats endlessly after the system starts, we do two things. First, we write to the ct variable current time from the moment the microcircuit starts, in milliseconds, and then we just calculate the current voltage using the analogRead() procedure, using the number of the analog monitoring input specified at the beginning of the sketch:

// Analog input for voltage monitoring
byte voltageInput = 5;

And also 2 coefficients, which I will talk about in detail later:

// Voltage calculation coefficient (divided by it)
float voltageX10Coefficient = 5.11;

// Voltage calculation offset (it is added)
int voltageX10Shift = 35;

But it would be too simple if everything were that simple. Therefore, to complicate the algorithm, 2 more variables were introduced into the code:

boolean goingUp = true, isUpAfter = false;

The first variable tells us what state the charging process is currently in. Its value is true until the power decreases for the first time. That is, goingUp = true tells us that we turned on the charger not long ago and it is still charging the battery with the maximum possible current, without ever reducing it to protect against overvoltage.

With the second, everything is finally complicated - it tells us whether the power increase occurred after goingUp became false and is set by the following simple piece of code at the end of the power increase procedure:

if (goingUp == false) (isUpAfter = true;)

Right now you’re probably thinking, why the hell is all this necessary? I'll explain right now!

The reason for adding these two variables was precisely the implementation of the ability to charge a battery standing on a car with a variable load connected to it. The first purpose of the goingUp function is to determine the parameter by which the power increase will work:

if ((powerLevel<8) && (ct >powerTime + powerUpTime) && ((goingUp == true && voltageX10< powerUpMaxTreshold) || (goingUp == false && voltageX10 < powerUpMinTreshold))) {

As you can see, in the first charging phase we increase the power if the current voltage is less than powerUpMaxTreshold, and in the second phase - if it is less than powerUpMinTreshold: these are the same parameters that I talked about at the beginning.

If conditional operator, written above, is still executed, and this same goingUp is false, then the patented system comes into play additional check voltage:

boolean stillLow = true;
if (goingUp == false) (
for (int x=0; x<= upCycles; x++){
voltageX10analogRead(voltageInput)+voltageX10Shift)/voltageX10Coefficient;
if (voltageX10 > powerUpMinTreshold) (stillLow=false; break;)
delay(1);
}
}
if (stillLow == true) (

In which a new character enters the scene:

//Number of millisecond iterations of voltage check before raising power
int upCycles = 5000;

The fact is that when there is a signal to increase power after goingUp has become false, we are most likely dealing with some kind of unstable load - the same subwoofer, as I already assumed, or some other unknown garbage. And if so, then why don’t we, instead of stupidly increasing the power, once again clicking our precious switches and risking getting the voltage on the battery higher than the maximum specified for a moment, arrange simple check: 5 thousand times (upCycles) with an interval of one millisecond, check the current voltage, and if it at least once, hear, at least once exceeds the powerUpMinTreshold - that’s it, Khan, there will be no increase, turn off the fishing rods! A simple but effective check.

isUpAfter, in turn, helps us implement the powerUpMinTreshold reduction function (I talked about it at the beginning), here's what it looks like:

if ((isUpAfter == true) && (powerTime > ct - powerUpMinTresholdTimeout)) (powerUpMinTreshold = powerUpMinTreshold - 1;)

Here powerTime is time last promotion power at the moment.

The fact is that, in addition to the condition of the powerUpMinTresholdTimeout mentioned above, we need to reduce it only when we lower the power after we first raised it after we had already started lowering it. I told you that this isUpAfter thing is complicated!

This is the algorithm, believe it or not. I will talk about its other details and subtleties in the course of the further story about the actual assembly of the device.

Preparing the relay block

So, having figured out which contacts of the relays are responsible for what and having decided on their placement relative to each other, I started gluing:

To do this, I used the “Moment - Crystal” lying nearby. I won’t say that this is some kind of super-duper glue, but its properties suit me. It’s better, of course, to use Khaigirov’s “Glue To Death”, it dries faster and generally hardens at the end, but there is 2-3 times less of it in the tube, and it costs one and a half times more than Moment, therefore, as the hero of one good one said Soviet cartoon, “And so it will do!”

As for gluing, everything is simple and written on the tube - apply to both surfaces, wait 5-10 minutes and squeeze tightly (yep, so hard that the coal pressed between the pins turns into a diamond 😆):

That's all, the relyushki are compressed. As you can see, I placed the central contacts next to each other, they will still need to be connected to each other:

I did the same with the large relays, and then glued these 2 resulting blocks together, after which I began to solder the wires to the contacts. The thick yellow wire is connected in turn to all the relays - this is the output bus, which will then go to the diode bridge, the red wires are to the first 4 terminals from the secondary winding of the transformer, and the small yellow wire that goes in turn through all the relays is constant +12 volts coils And the downsides of the coils, as you may have guessed, are the brown and white wires, which we will return to soon.

The same design, but on the other side, with new soldered wires for connecting the secondary winding leads. Moreover, with large relays there are 2 wires per output per output - this is how this relay model is made for a more uniform load distribution and, as a result, less heat generation:

Since the current consumed by the coils in such relays (~100 mA) far exceeds the maximum current that can be taken from Arduino outputs(~40 mA) or 74HC595 shift register (~25 mA), transistors must be used to turn on the relay coils. And the good old orange KT315 seems to be made for this!

These are n-p-n transistors, so in the circuit, to explain it in a simple way, the current should flow from the plus to the coil, then from it to the collector of the transistor and then from the emitter of the transistor to the minus. This transistor is opened by current from the base to the emitter, but the current needed there is very small, so we connect the bases of the transistors through 1 kOhm (1000 Ohm) resistors:

Now all that remains is to solder short wires to the resistors, not forgetting to carefully insulate everything, and you can fasten it - personally, I decided to glue the transistors to the side of the relays so that they do not get tangled and nothing comes off:

As you can see in the photo, the transistors are perfectly located on both sides of the relay block, I also filled the remaining contacts with glue to be sure that nothing will short out or burn out anywhere:

The transistors are glued and the block is almost ready:

Now we are faced with the question - what should we connect the transistors to? To Arduino? No, then there won’t be enough outputs for other components, and in such situations the saving chip comes into play - the 74HC595 shift register. So much has been written about it on the Internet, so I won’t write 3 paragraphs here, I’ll just say that thanks to such microcircuits, you can increase the number of Arduino outputs, sacrificing only three for this. Moreover, they can be connected in series in a chain. Eat different variants similar microcircuits, for example with 16 outputs or 8, in different packages. In this project, I decided to use the 8-output option small body SO-16. Although the work is exquisite, it all takes up little space, which is already lacking in the compact body of the device, which is not designed for such modifications:

To indicate the current power of the device, I decided to use 8 LEDs, one for each transistor / relay pair, for this I used an eight-core cable, soldering each core to the corresponding control channel, but not directly to the register, but to resistors, electrically there is no difference, but Mechanically it’s more reliable, I think. After a thorough check (more on this below), I filled the microcircuit with the same glue and once again went through all the transistors with it - now this system has become even more “solid” and strong:

Voltage indication system

The time has come for theoretical tests of the display system. To display the current battery voltage, I used a screen from an old system unit from the times of the first Pentiums. There are no tricks with it, each segment is a simple green LED operating from 2-2.1 volts. The only exception is the unit - in it 2 segments are paralleled and placed on one leg. The screen has 16 legs in total: 1 plus and 15 minuses. That is, power is always supplied to the plus, and the supply of ground to a certain leg lights up the segment we need - everything is extremely simple, but how to implement this? To do this, we again use shift registers, this time 2 pieces. For prototyping on a breadboard, I used the same 74HC595, but in a DIP-16 package, because it’s much more convenient to work with them. In the next picture, as you can see, the system is already assembled and working:

But this system very different from what went into the final device. Let's start with the fact that initially I decided to use a stabilizer to power the screen, although in the end I abandoned it and connected each leg of the screen through a 560 Ohm resistor. Secondly, in this diagram, the LEDs are powered through another stabilizer, moreover, it powers and the shift register itself. But in the end, there was only one stabilizer left in my charger - KREN5V, made back in the USSR, as you guessed it, 5 volts.

However, at this stage, the method of powering the hardware was not so important - the main thing was to learn how to display meaningful information on the screen, for which it was necessary to find out which segment each of the register pins corresponded to and then create two arrays in the firmware - tens and units, into which, using ones and zeros, enter the desired mask for each displayed number, that is, 0-19 for the first two characters of the screen and 0-9 for the third character:

// Templates for the screen
char* dozens=("10000001","10111011","01100001","00101001","00011011","00001101","00000101","10101011","00000001","00001001", "10000000"," 10111010","01100000","00101000","00011010","00001100","00000100","10101010","00000000","00001000");
char* ones=("10000010","10111110","10001001","10011000","10110100","11010000","11000000","10111010","10000000","10010000");

Also, the order of connecting the registers in the process of further work has changed - the relay block will be the first in the chain, and only then the screen, the relays are still more important, however, at the moment this is not so significant, because the order does not really matter - it’s just in the firmware , in the output procedure, you need to swap a couple of lines and that’s it.

When the system started working, instead of the third shift register, I connected ready block relay. And for the relays to click, I needed a twelve-volt power supply (not from a Chinese switch, but a stabilized one, with smooth voltage selection). If you want to use an unstabilized one, use a nine-volt one, or even 7.5 - they will have 12 volts without load. The main thing is not to confuse constant with variable! The next photo shows how 12 volts are connected to the nozzles with two plugs with wires in the upper right corner 🙄

The screen is already working! I wrote a sketch that alternately displays numbers from zero to 199 on the screen, and their binary representation on the LEDs on the right. Well, it's fun!

Working with shift registers, as I already said, is carried out over three wires. Their contact numbers are set at the very beginning of my sketch:

// Contact that is connected to the ST_CP input of the 74HC595
int latchPin = 8, voltageX10,voltageGuard,ons,dz,
// Contact that is connected to the SH_CP input of the 74HC595
clockPin = 12,
// Contact that is connected to the DS input of the 74HC595
dataPin = 11;

When the system starts, the operating mode of these contacts, like the others we use, is set to OUTPUT:

void setup() (
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(relay220Pin, OUTPUT);
pinMode(fanPin, OUTPUT);

Well, the output of information to the registers looks like this:

digitalWrite(latchPin, LOW);



Moreover, initially shiftOut() takes as input type variable byte, and since it is much more clear for us to directly write ones and zeros into registers, the code uses a special function bitseq(), which converts the above templates into exactly what shiftOut() wants from us:

byte bitseq (char s)(
byte ab=0;
for (byte ba=0; ba<8; ba++){
if (s == "0") (bitWrite(ab,ba,0);) else (bitWrite(ab,ba,1);)
}
return ab;
}

By that time, my desktop looked something like the following photo. Don’t rack your brains wondering what on the montor is an Ambulance. Cool series, I'm already watching it for the second time. 🙄 By the way, to connect non-power circuits in my device, I used twisted pair cable, the same one of category 5e, I just have a lot of it - I don’t throw away old cables from the roof, but unravel them. But not all wiring is good for such things. The ones I used are not solid inside, but stranded, which makes them very elastic and not brittle, and they also have high-quality insulation. But I wouldn’t use a regular twisted pair cable with solid cores - it bends very tightly (well, relatively), and it would be completely unreasonable to solder it to small microcircuits in an SO-16 package. What do you say, they should have used DIP mikruhi? Ha, you haven’t yet seen what kind of masochism will begin right now, so let’s not pull the cat by the horns (yeah) - let’s go!

It's actually not such a bad idea to place small chips inside the indicator. After all, there is no space in the old case anyway, the front panel had to be placed on small spacers, and if I had used registers in DIP cases - wow, I don’t know how everything would fit in there!

As I already said, in the final version the segments are connected through resistors, and not directly, but, nevertheless, I decided to show the first option too: maybe someone will like it better. Since this screen itself is filled with something on the reverse side (what disgusting things these filler screens of yours are), and the surface of this fill is also concave inward, I cut out a small flat plate from a plastic payment card of guess which Belarusian monopolist in the field of telecommunications, which I glued directly to the screen and then glued the registers themselves onto it, having previously marked the first leg on the back of each of them (because “Don’t mix up the views, Kutuzau!”).

After soldering all the wires and, again, checking that everything worked, I filled everything with glue. Because one wrong move and the wire will break off from the contact, short-circuit something and there will be a big, big mess. But this won’t happen with glue, everything is fine with glue. Glue, in short, rules. Until you have to tear it off 😆 👿 But let’s not talk about sad things, here’s what happened after these manipulations:

So I’ve even connected these two blocks together (temporarily, though) so that I can once again enjoy the blinking numbers and clicking numbers:

Unfortunately, when combining the screen with registers into one, I had to slightly change the order in which its legs were connected, so after starting the entire system, instead of Arabic numerals I saw some alien ones:

Although, in fact, there is little alien in the one and nine, only in the middle there was some kind of garbage, but these are all minor things. The next step was to screw in a voltmeter, that is, create a voltage sensor, because the algorithm of my operation should depend on the current voltage charger.

Measuring Voltage with Arduino

Arduino is a good thing, it initially has analog inputs on which you can monitor the voltage in real time. The only catch is that the measurement range of these inputs extends from zero to only five volts, but our voltages will be almost 15, so this problem must be solved somehow. And here a simple voltage divider using two resistors comes to our aid. For example, for the absolute maximum we will take 20 volts (well, just in case, so that nothing, if anything, burns out), and our ceiling is 5, that is, a quarter of the maximum, which means we need to divide the voltage by 4. For To do this, take 2 resistors of such values ​​that the value of the first is 1/4, and the value of the second is 3/4 of the sum of their values. For example, 10 and 30 kOhm. Or 5 and 15 kOhm, or 2.5 and 7.5, well, you get the idea. It’s not worth taking less, because the current there is small. Well, connect according to the diagram: 10 between the analog input and ground, and 30 between the analog input and the battery charging output.

But it's not that simple - the analogRead() procedure will give you a value from 0 to 1024, where zero is zero, and 1024 is 5 volts for her or 20 volts for us. Therefore, to recalculate this value, we need to enter a certain coefficient, which we will set as a constant in the firmware header (float voltageX10Coefficient = 5.11;). Looking ahead a little, I will say that subsequently the voltage that Arduino sees, at a high current, began to jump with a spread of up to half a volt, so we had to connect our improvised sensor through a diode, after which I installed a 16V 1000 mF capacitor, and I also connected a 220 relay there B, but more on that at the end. Why am I talking about this now? Because the diode, as you know, slightly lowers the voltage, so I introduced a second coefficient to compensate for the presence of this diode (int voltageX10Shift = 35;), that is, first the second coefficient is added to the output value, and then what happens is divided by the first .

As a result, the voltage monitoring turned out to be a success - compare the readings with the tester (this is not a battery connected to the device, but that same homemade stabilized power supply):

Charger front panel

Next, it’s time to work on the face of our device. Initially, I had thoughts of making a new panel and sticking it there, but after thinking about it, I figured out how to use the old inscriptions, so everything turned out quite meaningful. In place of the current regulator, holes are drilled for the LEDs, and the arrow on top just shows in which direction the current will be greater, how cool!

Now the LEDs have already been put in place, and the screen has been inserted into a new place, and even the remaining holes have found a use: in the hole from the current regulator there will be a light bulb connected to the primary winding of the transformer - it will light up when charging is in progress, that is, when the transformer 220 volts are supplied. And if the charger seems to be charging, but the light doesn’t light up, then check to see if you forgot to plug the plug into the socket! In the hole from the 6-12 volt switch there is a plastic edging inserted for an LED, which will be connected directly to the battery through a resistor without a stabilizer and the brightness of its glow will show how charged the battery is. This is useful if the battery is completely dead and there is not even five volts on it to power the brain - then the diode will glow dimly and there will be no questions, like maybe the device is broken. Although, of course, I make an excuse: if there weren’t a hole, I wouldn’t even think about inserting anything there. This is what usually happens with men, if you know what I mean.

By the way, you say, where have you, Andryusha, seen car batteries discharged to 5 volts? Well, at that time I had not seen them anywhere, but after finishing work on this charger they brought me one of these. 3 volts. And I even charged it, and it is even alive, although, as I believe, it is sulfated to death. There was a second one in a similar condition, but nothing could save him 😆

This is what the back of the muzzle looked like at that time:

And in the next photo I’m slowly peeling off the glue and replacing the wires with resistors. Of course, I also amputated the stabilizer in the lower left corner of the photo as it was unnecessary. And by the way, soldering resistors is much easier than wiring - if I were doing it all over again now, I would do it right away, with resistors and these small microcircuits.

Also in this photo in the upper left corner you can see how I connected the LEDs. They have a common minus, it goes along the inner radius and is connected to general minus devices through a 3.3 kOhm resistor - I chose this one so that it would be bright and not blinding. It seems like it worked out just right. Why is there only one resistor? Because at any time, with the exception of the moment the load is switched between relays, only one LED will light on the display.

Why except for the moment of switching? Because if one relay turns off, and the second one then turns on - at the moment the first one is turned off and at the moment the second one is turned on, a spark will appear on their contacts, from these sparks carbon deposits will form on the contacts, due to which they will fail over time - it their resistance will increase, they will begin to warm up, and that’s it, memento sea! So it’s correct to turn on the second relay first, and as soon as it turns on, turn off the first one, then we get rid of sparks and the relays will live happily ever after! By the way, on the original switch everything is done exactly this way, so no, I didn’t come up with this, the applause and flowers in the car are sent to in this case to the designers of the original device, and not to yours truly. Well, not everything is Maslenitsa for the cat. 🙄

By the way, the switching delay between relays is set by this parameter:

// Duration of transition between relays in milliseconds
byte relayTransition = 80;

But what will happen if, somehow magically, two or more relays turn on at the same time for a time longer than the allotted time for switching, due to some kind of glitch? But it will be very bad: you will short-circuit a section of the secondary winding. The wires will begin to melt, smoke will come from the transformer, and Armageddon will generally occur. The same one that Michael Bay filmed.

So, dear gentlemen, ladies and van-damms, especially for this purpose I came up with a system of protection against such an Armageddon. A 220 Ohm resistor is connected to the positive of each LED. Why 220? Firstly, because that day the Moon was in Saturn, and secondly, because before the New Year I had the opportunity to wire up a couple of domestic tape recorders, as well as an equally domestic electronic piano (or a piano, I don’t know, but not a piano in short), so from there I unsoldered a whole box of these 220 Ohm resistors, I need to put them somewhere - so, great use!

On the other hand, all these resistors are connected and pulled to ground through a 4k7 resistor (this means 4.7 kOhm, it’s time to call a spade a spade!), of which I also have a shitload and more. So we measure the voltage at this point G, where all these 9 resistors converge, that is, we connect this point to the next analog input of the Arduino, which is set by the following parameter:

// Analog input for monitoring the number of switched on relays
byte guardInput = 4;

And from this voltage we immediately see how many LEDs are lit there at the moment, and since they are connected directly to the transistors, this is the same thing that we see, how many relays are turned on at the moment, and this is exactly what we need and it is necessary in this situation! That is, we set a voltage threshold, above which we firstly immediately cut off 220 volts using the appropriate relay, and secondly we try to correct the situation with the relays, and as soon as it is corrected, we turn on 220 again and continue to work as if nothing was wrong it happened. Everything is simple and reliable, I checked it!

This threshold is set here:

// Maximum allowed guardInput value
byte guardTreshold = 160;

And the procedure of the above-described check is performed every cycle of the loop and looks like this:

// Check for the number of switches on and automatically turn off - restore - turn on
if (voltageGuard > guardTreshold) (
digitalWrite(relay220Pin, LOW);
while (voltageGuard > guardTreshold) (
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, bitseq(ones));
shiftOut(dataPin, clockPin, MSBFIRST, bitseq(dozens));
shiftOut(dataPin, clockPin, MSBFIRST, bitseq(relays));
digitalWrite(latchPin, HIGH);
voltageGuard=analogRead(guardInput);
}
digitalWrite(relay220Pin, HIGH);
}

And now I’ll still show you the photo I promised 9 paragraphs ago, if only for the sake of decency:

A removed cover shows us the tension. Cuteness!

AC power relay

However, we need to move on. As you can see, the charger is gradually assembled, the wires are gradually lengthened and two new characters appear on the scene - that same 220-volt relay and a small twelve-volt cooler - eighty from the computer:

Relyukha is ordinary, no different from others. Pulls 220 volts at, like, 10 amperes. But we don’t need this, we have a 1 ampere fuse. But a reserve in such things is good, it is reliability. The coil of this relay operates on 12 volts, but there are similar ones for 5. I bought 25 of these at once on Ali, for cheap. Why did I take 12 and not 5? Look, no matter where I turned it on, I would still need a transistor, right? Even if it was 5 volts. But if it’s at 5, it needs to be connected through a stub, through which all the brains are already powered, it would get even warmer from this - why the hell is that necessary? You can directly poke at 12, but at least 15 will be there - she doesn’t care, she works. Moreover, starting from eight volts. I connected the LED to it simply for indication during testing, like if the LED lights up, it means it’s working and virtually 220 volts went to the transformer. It is connected directly to the output of the arduino, through the same KT315, just like the other relays in the same block. And yes, the rezuk is also 1 kOhm, although 2 will probably work there, you can install those that are larger, but keep in mind that the lower the rezuk’s value, the more current will go through the transistor. For general energy efficiency, these + - a couple of milliamps don’t matter, but for low-current outputs of the Arduino and registers - not really, so there you go.

Turning on this relay, as you probably already understood, occurs using

digitalWrite(relay220Pin, HIGH);

And turning off with

digitalWrite(relay220Pin, LOW);

Connecting a cooler to cool the charger

But the cooler seems to consume 140 milliamps, judging by the sticker on it, so the KT315 won’t work here, according to the specification they are only up to a hundred, so I took the KT815A. They go up to one and a half thousand milliamps and it will be enough. There are other options, I just always try to use what I have a lot of, maybe you, for example, will have some other transistor for the cooler, if it pulls up to 20 volts and up to 150 milliamps - put it, if n-p-n, then just look at the pinout for the legs, and if it’s p-n-p, then you need to change the circuit a little, but in this case it’s all unimportant. But there is one more nuance here...

Have you ever heard a cooler squeak? No, not from rotation, just squeaking? I didn’t hear it either, but I was lucky here. And all because Arduino generates intermediate values ​​of output voltages (more than zero, but less than five) using PWM, that is, these are fast, fast voltage fluctuations, pulse width modulator works for certain frequency, and transistors, as you know, also know how to operate at specified frequencies, so these pulses are transmitted through the transistor to the cooler and, due to its architecture, it begins to squeak. I won’t go into details, since I don’t know them myself, but all this can be treated by plugging in a 100 mF conductor with a plus on the base and minuses on the emitter of this transistor. The voltage there is up to 5 volts, so the condenser can be set to at least 6.3 volts. That's it, the squeaking will disappear and there will be nothing at all!

The number of the PWM contact by which the cooler is controlled is set by the following parameter:

// Output for fan control
byte fanPin = 6;

Its speeds from zero (0V) to 255 (5V) with reference to power levels are set by the following array:

// Fan speed settings
byte fanSpeeds=(0,0,80,90,100,110,120,180,255);

And the very setting of these speeds is prescribed in the procedures for increasing and decreasing power:

analogWrite(fanPin,fanSpeeds);

By the way, here’s a closer look at the relay with the cooler:

Further work on the front panel

But let's move on. Here I already tried on the fuse in its place in the new case - the old one supposedly had several voltages, although in fact only one was used, and a piece was broken off from it, and this one is like new, 220 volts, from my father’s supplies. Well, I installed the same bottom LED and glued it with the same glue.

Finally, it's time to assemble and put the front panel in place! As you can see, all the wires are already soldered, even the five-volt Krenka sticks out at the bottom of the frame, spacers are screwed into the body to move the panel a little (I already talked about this), because previously it was attached close to the body. As you can see, in many places I inserted the wires into casings so that nothing would fray or shorten anywhere. 12 volts to Krenka come directly from the diode bridge, with a wire of a class higher than simple twisted pair. The minus is connected to the common minus directly, but the plus is connected through a diode, otherwise Vasya Pupkin will reverse the polarity when connecting the battery and that’s it, finita la comedy, resolder half of the burnt components! And so you can be calm.

After I figured out a couple of times how the wires would go between the case and the panel, I decided to glue them in the right places so that they wouldn’t dangle or get in the way, I pressed them down with improvised objects on top, secured them with clothespins and left them there overnight so that the glue would dry. :

Installation of the Atmega328P controller with harness and other elements

By this time, on half of one of those same mounting plates, I had already mounted the lion's share of the remaining components - a socket for a microcircuit, quartz, conductors, a transistor for a cooler, etc. and so on.:

The board itself had to be cut off on one side - it was too big and wouldn’t fit. I wrapped the lower part, and then the entire part, with paper tape so that it would not short-circuit to anything during operation.

By that time, the front panel had already been finally installed in its place of honor, and the five-volt Krenka was screwed to the case behind the panel through a heat-conducting insulating gasket and a plastic insert for the screw - thanks to this, the microcircuit will be reliably cooled through the massive metal case, without being connected to it electrically.

Final configuration of device parameters

Here you can already see how the half-assembled system works, but again, so far only from the power supply, because in my design the socket to turn on the battery is connected at the very last moment. Well, it just so happened, what to do...

After turning it on, it was discovered that at a high current, when the ammeter goes off scale, the charger sees a voltage of 0.5-0.8 volts more than what is actually on the battery at the moment. The test showed that as much as half a volt was lost on the wires, so I replaced them with better ones, with a larger cross-section and soldered them to a cool plug that was very suitable for the overall design of the device. This solved the problem, but not 100 percent - at high currents some difference still remained. But I thought that this was not a bug, but a feature, because there is no point in charging the battery with such high currents - let it work as some kind of limiting factor!

Here, by the way, the charging of dad’s battery is in full swing, this can be seen on the ammeter. True, the 220-volt light bulb turned out to be quite dim and in the photographs it is almost impossible to see that it is on. But it burns, believe me!

The charger is ready!

Here's a bottom view of the device. Initially, I planned to seal this entire gap between the case and the panel, but then I changed my mind - it’s better to let it be ventilated!

View from the left side. Well, or from the right - it depends on how you look at it, excuse the pun.

Well, this is from above. Here you can see that I glued the panel to the protruding part of the ammeter - it turned out to be a large third point of support, otherwise the panel sat somehow unsteadily. And so everything is great, reliable and beautiful! By the way, imagine if instead of a Crystal I used a regular Moment, and through the gap all this light yellow crap would be visible. Fuuuuuck! 😳

And, of course, the rear view. I attached a beautiful grille to the fan that protects the fingers and other limbs of people and animals from injury. And here you can see the new power cord, which after charging conveniently screws onto the cooler and does not bother anyone!

By the way, after assembling and testing the device, I had to disassemble it again in order to lubricate this damn cooler, why didn’t I lubricate it right away, was there such a thought???

This is my first project on a programmable microcontroller. I spent almost a month working on it in the evenings. I even took a week’s break because I got tired of it, this work is so boring or something. But I'm happy. I'm happy with the experience, I'm happy that I was able to finish this job, I'm happy that I now have an excellent automatic charger of the "set it and forget it" class. And I am pleased that when my friends or acquaintances ask if I have a charger for their battery, I will hand it to them and proudly say that it was I who made this cool thing!

An Arduino and its added charging circuitry can be used to monitor and control the charging of NiMH batteries, like this:

Completed device

Rechargeable batteries are a great way to power your portable electronics. They can save you a lot of money when correct charging. In order for you to get the most out of your batteries, they must be charged correctly. This means you need a good charger. You can spend a lot of money buying a ready-made charger, or you can have fun making one yourself. In this article we will look at how you can create a charger controlled by Arduino.

First, it is important to note that there is no universal method charger that would be suitable for all batteries. Different types of batteries use different chemical processes to make them work. As a result, different types Batteries need to be charged differently. We cannot cover all battery types and charging methods in this article. So for the sake of simplicity, we'll focus on the most common type of AA-size battery, the Nickel Metal Hydride (NiMH) battery.

Accessories

List of components from left to right:

  • powerful 10 Ohm resistor (minimum 5 watts);
  • resistor 1 MOhm;
  • capacitor 1 µF;
  • MOSFET transistor IRF510;
  • temperature sensor TMP36;
  • power supply 5 volts;

How to charge NiMH AA batteries

Increasing the charging rate increases the risk of battery damage.

There are many ways to charge NiMH batteries. The method you use mainly depends on how quickly you want to charge your battery. The charge rate is measured in relation to the battery capacity. If your battery has a capacity of 2500 mAh and you charge it at 2500 mA, then you are charging it at a rate of 1C. If you charge the same battery at 250 mA, then you are charging it at a rate of C/10.

During fast charging battery (at speeds above C/10), you need to carefully monitor the battery voltage and temperature to avoid overcharging it. This may seriously damage the battery. However, when you charge your battery slowly (at a rate below C/10), you are much less likely to damage the battery if you accidentally overcharge it. Therefore, slow charging methods are generally considered safer and will help you increase battery life. Therefore, in our homemade charger we will use a charge rate of C/10.

Charge circuit

This charger is based on a circuit for controlling the power supply using Arduino. The circuit is powered by a 5 volt source, such as an AC adapter or computer unit nutrition. Most USB ports are not suitable for this project due to current limitations. The 5V source charges the battery through a powerful 10 ohm resistor and a powerful MOSFET transistor. The MOSFET transistor sets the amount of current flowing through the battery. The resistor is added as a simple way to control the current. Monitoring the amount of current is done by connecting each resistor pin to the Arduino's analog input pins and measuring the voltage on each side. The MOSFET transistor is controlled by the Arduino PWM output pin. Signal pulses pulse width modulation smoothed to a constant voltage by a filter using a 1 MΩ resistor and a 1 μF capacitor. This circuit allows the Arduino to monitor and control the current flowing through the battery.


temperature sensor

The temperature sensor is used to prevent battery overcharging and ensure safety.

As an additional precaution, a TMP36 temperature sensor has been added to the charger to monitor battery temperature. This sensor produces a voltage that varies linearly with temperature. Therefore, unlike thermistors, it does not require calibration or balancing. The sensor is installed in a drilled hole in the battery holder body and glued into the hole so that it presses against the battery when it is installed in the holder. The sensor pins are connected to the 5V bus, to the case and to the analog input pin of the Arduino.

AA battery holder before and after installation on breadboard

Code


The code for this project is quite simple. Variables at the beginning source code allow you to configure the charger by entering the battery capacity and the exact resistance of the high-power resistor. Safe threshold variables have also been added. The maximum permissible battery voltage is set to 1.6 volts. The maximum battery temperature is set to 35 degrees Celsius. The maximum charging time is set to 13 hours. If any of these safety thresholds are exceeded, the charger turns off.

In the body of the program you can see that the system constantly measures the voltage at the terminals of a powerful resistor. This is used to calculate the voltage values ​​across the battery and the current flowing through it. The current is compared with the target value, which is C/10. If the calculated current differs from target value more than 10 mA, the system automatically adjusts the output value to correct it.

Arduino uses a serial interface to display all current data. If you want to monitor the operation of your charger, you can connect the Arduino to USB port computer, but this is not necessary since the Arduino is powered by a 5V voltage source from the charger.

Int batteryCapacity = 2500; // battery capacity value in mAh float resistance = 10.0; // measured resistance of a powerful resistor int cutoffVoltage = 1600; // maximum voltage on battery (in mV), which should not be exceeded float cutoffTemperatureC = 35; // Maximum temperature battery that should not be exceeded (in degrees C) //float cutoffTemperatureF = 95; // maximum battery temperature that must not be exceeded (in degrees F) long cutoffTime = 46800000; // maximum time charge at 13 hours, which should not be exceeded int outputPin = 9; // the output signal wire is connected to digital pin 9 int outputValue = 150; // value of the output PWM signal int analogPinOne = 0; // the first voltage sensor is connected to analog pin 0 float valueProbeOne = 0; // variable to store the value on analogPinOne float voltageProbeOne = 0; // calculated voltage on analogPinOne int analogPinTwo = 1; // the second voltage sensor is connected to analog pin 1 float valueProbeTwo = 0; // variable to store the value on analogPinTwo float voltageProbeTwo = 0; // calculated voltage on analogPinTwo int analogPinThree = 2; // the third voltage sensor is connected to analog pin 2 float valueProbeThree = 0; // variable to store the value on analogPinThree float tmp36Voltage = 0; // calculated voltage on analogPinThree float temperatureC = 0; // calculated sensor temperature in degrees C //float temperatureF = 0; // calculated sensor temperature in degrees F float voltageDifference = 0; // difference between voltages on analogPinOne and analogPinTwo float batteryVoltage = 0; // calculated battery voltage float current = 0; // calculated current flowing through the load in (mA) float targetCurrent = batteryCapacity / 10; // target output current (in mA) is set to // C/10 or 1/10 of the battery capacity float currentError = 0; // difference between target and actual currents (in mA) void setup() ( Serial.begin(9600); // setup serial interface pinMode(outputPin, OUTPUT); // set the pin as output ) void loop() ( analogWrite(outputPin, outputValue); // write the output value to the output pin Serial.print("Output: "); // show the output values ​​for monitoring on the computer Serial.println (outputValue); valueProbeOne = analogRead(analogPinOne); // read the input value on the first probe voltageProbeOne = (valueProbeOne*5000)/1023; // calculate the voltage on the first probe in millivolts Serial.print("Voltage Probe One (mV): "); // show the voltage on the first probe Serial.println(voltageProbeOne); valueProbeTwo = analogRead(analogPinTwo); // read the input value on the second probe voltageProbeTwo = (valueProbeTwo*5000)/1023; // calculate the voltage on the second probe in millivolts Serial.print("Voltage Probe Two (mV): "); // show the voltage on the second probe Serial.println(voltageProbeTwo); batteryVoltage = 5000 - voltageProbeTwo; // calculate the voltage on the battery Serial.print("Battery Voltage ( mV): "); // show battery voltage Serial.println(batteryVoltage); current = (voltageProbeTwo - voltageProbeOne) / resistance; // calculate the charge current Serial.print("Target Current (mA): "); // show target current Serial.println(targetCurrent); Serial.print("Battery Current (mA): "); // show actual current Serial.println(current); currentError = targetCurrent - current; // difference between target and measured currents Serial.print("Current Error (mA): "); // show current setting error Serial.println(currentError); valueProbeThree = analogRead(analogPinThree); // read the input value of the third probe, tmp36Voltage = valueProbeThree * 5.0; // converting it to voltage tmp36Voltage /= 1024.0; temperatureC = (tmp36Voltage - 0.5) * 100 ; // conversion based on a dependence of 10 mV per degree with a shift of 500 mV // ((voltage - 500 mV) multiplied by 100) Serial.print("Temperature (degrees C) "); // show temperature in degrees Celsius Serial.println(temperatureC); /* temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; //convert to degrees Fahrenheit Serial.print("Temperature (degrees F) "); Serial.println(temperatureF); */ Serial.println(); // additional empty lines to make data easier to read when debugging Serial.println(); if(abs(currentError) > 10) // if the current setting error is large enough, then adjust the output voltage ( outputValue = outputValue + currentError / 10; if(outputValue< 1) // выходное значение никогда не может быть ниже 0 { outputValue = 0; } if(outputValue >254) // output value can never be higher than 255 ( outputValue = 255; ) analogWrite(outputPin, outputValue); // write new output value ) if(temperatureC > cutoffTemperatureC) // stop charging if battery temperature exceeds safe threshold ( outputValue = 0; Serial.print("Max Temperature Exceeded"); ) /* if(temperatureF > cutoffTemperatureF) / / stop charging if the battery temperature exceeds the safe threshold ( outputValue = 0; ) */ if(batteryVoltage > cutoffVoltage) // stop charging if the battery voltage exceeds the safe threshold ( outputValue = 0; Serial.print("Max Voltage Exceeded" ); ) if(millis() > cutoffTime) // stop charging if the charge time has exceeded the threshold ( outputValue = 0; Serial.print("Max Charge Time Exceeded"); ) delay(10000); // delay 10 seconds before the next iteration of the loop)

You can find a downloadable version of the source code at the link below.



Magnetic induction is a technology you probably remember from high school physics class. To transmit power wirelessly, you need two coils: a transmitter coil and a receiver coil. Alternating current in the transmitter coil generates a magnetic field which induces a voltage in the receiver coil. This voltage can be used to power mobile device or to charge the battery.


No less important elements will be inductors, which you can make yourself. These simple coils are wound from copper wires and are called air core coils. Creating such a winding for our purpose is very simple. Find a round cylinder with a diameter of about 5 centimeters, and wind the wire around it so that each turn does not overlap another turn, but at the same time is as close to the other turn as possible. A round cylinder can be, for example, a PVC tube. You may need to use duct tape or tape in 2-3 places to keep the structure stable.


In addition to Arduino and inductors, we will need: one NPN transistor type 2N3055, one diode bridge 1A ( diode assembly, they have four pins), one LED, one 100 ohm resistor, two 47 nF capacitors, a 9 V battery to power the Arduino, and preferably two prototyping boards. The diagram for connecting the components to create a wireless data transmission device is shown in the figure below.



The circuit can be tested using the simple Arduino code below.


void setup() ( pinMode(13,OUTPUT); ) void loop() ( digitalWrite(13,HIGH); delay(0.5); digitalWrite(13,LOW); delay(0.5); )

However, a simple wireless power transfer device can be made without an Arduino. Basically, we can only use one 2N2222 transistor. Connect its base terminal to the first end of the coil and its collector to the other end of the coil. The emitter pin is connected to the battery. As a result, such a simple design might look like this:




   Thank you for your interest in information project website.
   If you want interesting and useful materials came out more often and there was less advertising,
   You can support our project by donating any amount for its development.