Stop the war!

Stop the war in Ukraine! Fuck putin!

More information is at:

There is a fund to support the Ukrainian Army:, and there is a special bank account that accepts funds in multiple currencies: I donated to them. Please donate if you can!

Killer putin

Killer putin. Source:

Arrested putin

"It hasn't happened yet, but it will happen sooner or later. Beautiful photo, isn't it?" Source: twitter.

My observations from learning electronics

| comments

I’ve wanted to learn electronics for a long time, and it always seemed a huge field where you’d need to know psychics and differential equations well. Then it started two years ago with the Make: Electronics book and I’ve been learning about this very interesting field of hardware. It is also interesting to note the differences between hardware and software — programming has been my job for eight years. The following is how I understand electronics now and may or may not be entirely correct. I welcome your feedback and clarifications.

It took time to understand even the basics: voltage and current. I find it much more straightforward to think of voltage as what it actually is: the potential difference between two points. Once I realized the relationship between voltage, current, and resistance (the Ohm’s law of course), I amazingly noticed a few analogies in the real world:

  • highway a.k.a. autobahn — there are people in point A who need to get to point B quickly. There are multiple roads between them and the fastest is a highway. So the wish/need to move to point B is the potential difference (voltage) of where they are and where they want/need to be. Now a good question is how fast can they go? In theory, they would go as fast as possible, given the physical limitations (max speed of the car or the air resistance), but there are also “logical” limitations, such as the maximum allowed speed — this is equivalent to the internal resistance of a battery. Current is the number of cars passing through a point in a second: less resistance means more current.
  • personal desire to change something — you’re here and now, but you want to change something, for example, refactor a feature in your program at work — that’s the potential difference. How fast you move towards the final state is the current. And there may be resistance: higher-priority tasks, the requirement to design the change and get it approved, missing tests. If your desire (voltage) is low and the resistance is high, you’ll have a very small current, i.e. no refactoring. However if the voltage is high and the resistance is high, the current will increase and you’ll try to push through, increasing the tension (generated power).
  • grocery store — here the voltage is all the groceries available in the store. People get in, go through and select stuff — that’s the current, which is limited by the internal resistance — the necessity to go through the checkout process to pay. If a lot of people expect bad weather soon and come in quickly to buy lots of stuff, the store will have much less stuff afterwards — that is, the voltage drops during and after high current until it’s recharged by getting more stuff from suppliers.

Main observations

I made three major observation from my small experience so far:

There are no absolute values

Say, you have a standard battery that outputs 9 V. In fact, when it’s fresh it outputs about 9.5 V (an estimate) and when it’s old the output can be 6.5 V (an estimate) — so you actually have a range of possible voltages. It’s even worse with a bipolar junction transistor: a typical 2N2222 transistor can have the current amplification factor from 35 to 300! This varies based on multiple parameters: collector current, base current, the collector-emitter voltage, ambient temperature.

As far as I see, the idea here is that you assume some normal conditions and design your circuit based on them. E.g., when using a linear voltage regulator to have stable 5 V, it drops about 2 V, so it’s fine to have a range of 7–10 V from a battery.

Since everything is not precise, you really have to know what you’re building. And to do know that, you need to know the requirements, even if they are your own and it’s a project just for fun. Also, you need to have an approximate schematic of what you’re building because just throwing components on a breadboard without thinking will likely lead to burned components due to voltage mismatch or too much current.

In programming, we work with concrete, specific numbers on top of the abstraction layer of digital electronics. If you have an algorithm not involving truly random numbers, you can run it and always get the same specific result. You may also get away more easily without software requirements.

Every component has a specification (datasheet)

The datasheet specifies a lot of data about the component, meaning that it’s been extensively tested by the manufacturer. At least, it tells you absolute maximum values, so if you stay in the expected range, the component will work properly. There are also recommended values.

However, even the absolute maximum values are not absolute. That is, a switch may allow maximum 0.2 A of current – this doesn’t mean that if you pass 0.25 A for a second, the switch will burn our for sure.

By the way, if you pass too much current through an LED, it will “burn out”. But what does it mean? In fact, the current itself will not kill the LED, but the power will. Power W = V * I. In case of an LED, power converts into heat, and an LED can dissipate only so much heat, so heat will “burn out” and kill the LED when there is too much of it. If you had a very effective cooling system, you could pass more current without burning it, but that’s not a common use case.

Also, there are a bunch of categories of components and lots of components inside each category. This separation and single purpose is nice and allows to compose small pieces into bigger ones, those into bigger ones, etc.. Of course, manufacturers already produce components of different levels of integration: discrete transistors, logic gate ICs, Arithmetic Logic Units, microcontrollers, microprocessors, System-On-Chips.

In the software projects I’ve worked on, it’s typically different: a class is written, usually with at least a few responsibilities because it’s hard to keep them separate when you have an approximate idea how to do your task. Then it may be unit-tested with a few examples of input data and verifying that the output is as expected. Corner cases are rarely tested and are not always obvious. If you’re lucky to work in a language with a property-based testing library, those tests are broader. Other requirements for the class may not be considered at the creation time, so that someone else comes back in a month and decides that the user of the class should do its work concurrently and calls the methods on various threads/queues; mutable data + concurrency — boom! or even worse, an occasional boom in production! On the other hand, it’s typical that a software entity is more flexible and evolves step-by-step while the program is developed.

Everything has a price

For example, you need to protect an output pin of an integrated circuit so that current isn’t forced into it. Easy, you know to add a diode! However, a diode will drop approximately 0.7 V in forward voltage, so you need to decide if the rest of the circuit can live with that. Maybe, not, in which case you can take a Schottky diode with a voltage drop of ~0.1 V, however it may cost more, or be physically bigger, or tolerate less current. If this approach doesn’t work either, you may have to make bigger changes in the schematic.

Another example: you have a circuit powering from a battery and you want to add a power switch. That’s super easy: just add a switch after the positive battery’s lead. But now you have to at least think about the maximum current it can handle. Strictly speaking, you could’ve thought about it before as well, but those were just wires, and e.g. 22 AWG wires are fine for this small project, we deal with less than 1 A let’s say. Still, if your switch can handle only 0.1 A and the circuit consumes 0.2 A, you’ll need to find another switch.

By contrast, in software development, it’s easier to miss this point. A simple example: you have some code in multiple places, so of course you want to extract it into a function for easier maintainability in the future. Adding a function will add some overhead to the generated assembly code because it needs the prologue and epilogue and the jump instructions. So you may tell the compiler to inline the function everywhere — this removes the previous overhead, but makes the compiler more complicated and possibly increases the compilation times. A few possible explanations: I’m much more familiar with software; or software is inherently more flexible.

Extra observations

  • Soldering is easy. Soldering SMD components is harder, but is still quite easy until they become very small. Desoldering components is much more “fun” — even DIP-16 chips isn’t easy having only a soldering iron and desoldering wick; let alone, a QFP-44 chip.
  • Laying out the traces on a PCB has a lot of options and possible solutions. You want to find the optimal layout with the minimal length of the traces, but the requires experimentation with dozens of steps. So it’s easier to think of the task as a puzzle.
  • Building stuff in the real world using real hardware is fun! Especially when it works as you wanted.
  • ICs don’t care about current, the digital logic only wants to know if the voltage means “0” or “1”. But you can’t measure voltage without having a current; having both will necessarily add resistance to the mix => the inputs of an IC have a very big resistance, but not unlimited.
  • So you have an IC and it needs to read an input of a pushbutton. Besides the contact bouncing, another thing to remember is that an input should always be in a defined state. If a pushbutton is open, there is no electrical connection inside and the input will float from the EM noise. In this case, the standard practice is to use pull-up or pull-down resistors and there’s an interesting detail there. If we’re using a pull-up resistor to keep the input state high by default and the button is open (not pressed), then the voltage at the input pin will be almost Vcc and the current will flow into the pin; however when the button is closed (pressed), its connection to ground will be lower resistance than via the pin, so the voltage at the input pin will be 0 V and the current will flow out of the pin (and through the pull-up resistor to ground as well).
  • Voltage dividers are effectively everywhere: any circuit with serial components that have any resistance will have voltage drop on every one of them. It is kind of obvious if you know the Kirchhoff’s voltage law, but it is also not obvious in practice. In the point above, when you attach a pull-up resistor to an input, the voltage at the pin will never be equal to Vcc because the resistor will drop some voltage (and the button is connected to ground, so there is no Vcc there) — the voltage divider of the resistor and the input transistor in the IC; the pin has a very big resistance (in order not to consume a lot of current), whereas the pull-up resistor is comparatively small, that’s why the voltage drop is also small. And here you need to figure out which voltage drop is fine for your IC and calculate the value of the resistor.
  • Just like in quantum physics, measuring a system changes it. Even by using a simple multimeter to measure voltages in your curcuit, you change its behavior (very slightly).
  • For practical electronics, you need a model, not physical explanation. For example, take a bipolar junction transistor — as I mentioned above, it can have the current amplification factor of 35 to 300, it jumps wildly when the current or voltage at the inputs changes. How are you supposed to use it in an amplification circuit? I don’t know. However you can use a transistor as an electronic switch if you know a few basic principles and calculations. In the majority of applications, you don’t have to know how it actually works on the physical level; it’s enough to have a model saying that if Vb > (Ve + ~0.7 V), then the BJT will allow current from the collector to the emitter, and you need to make sure that the base current will enable the saturation mode, so that your collector current isn’t limited by the transistor.
  • I was confused for a while at the BJT applications. I’d seen the cases where a transistor was used as a switch to allow or disallow current through a device, say a relay: you connect Vcc to one pin, an NPN BJT’s collector to another and the emitter to ground. Then I needed to use a transistor to control an IC’s reset pin, but the problem was that it didn’t make sense somehow: there is only one pin, so do I connect it to the collector directly, do I need a current-limiting resistor, and will it work with an input pin?! After reading multiple articles I realized that this application is different, in fact, it’s very similar to the pushbutton case: you need a resistor connected to the collector and the pin is also connected to the collector, so when the BJT is off, you get almost Vcc and when it’s on, you get almost GND.
  • Speaking of which, I want to highlight this initially bizarre thing again: you have an output pin of an IC and you want to control an LED with it — very easy, connect it to the pin in series with a resistor and… do you connect the resistor to Vcc or ground? Initially I thought that the output pin means the current flows out of it to ground — this is called “current source” configuration because the IC is the source. However, there is an alternative: “current sink” when the IC is the sink and the current flows from Vcc into the pin to ground. It may seem weird that an output pin can work that way. The trick here is that the “output pin” refers to an idea that the chip controls the environment, not the otherwise, and since it can allow or disallow current in both configurations, it makes sense.

Informational resources

A few great books:

A few websites that have been very helpful: