
Batterymeter
hb020/batterymeter
Handheld Battery AC and Time Domain characterization tool on Attiny series 2

Handheld Battery AC and Time Domain characterization tool on Attiny series 2
Batterymeter is an open-source printed circuit board by hb020, from the hb020/batterymeter repository on GitHub. It is a 4-layer board of 106 × 29.2 mm with 145 parts on 120 nets, routed with 1,232 tracks and 169 vias.
It is built around the ATTINY3226-SU, CH340E and OPA4388ID, with the MCP1642B-33I/MS, 74AUP1G02SE and DG4052EEQ-T1-GE3 among its other parts. Its parts include 69 resistors, 35 capacitors, 14 ICs, 7 connectors and 6 diodes. It belongs with the power boards and the AVR (ATmega, ATtiny) boards of this library.
This repository is about a "pen size" (handheld) tool for quick measurement of various types of battery resistances/impedances.
This tool uses 2 different methods for measuring impedance values:

This document handles the reasoning behind the creation of this tool, the methods used, the software and the hardware.
This tool was designed with the following design restrictions:
Battery impedance is a complicated subject. A battery does not have one impedance, and even if you get a number, it can mean many things. Also, the battery impedance depends on a lot of different things, like state of charge (SoC), state of health (SoH), temperature, and of course the measurement method. Therefore, various norms exist for measuring the various resistances and impedances of the different battery types. Some of them are:
Outside of these norms, various other test methods have arisen lately. Below is an explanation of the different methods I investigated.
Various models of battery impedance exist, depending on the chemistry. For Li-Ion cells, the "Combined Randle and Warburg Circuit Model" is often cited as fairly complete, and, with some variations, also applicable to some other chemistries.

Equivalent circuit model of a Li-Ion battery half-cell system, and nyquist plot of a frequency sweep. (source)

Nyquist plot, related to Li-Ion cell chemical processes. (source)
The EIS (Electrochemical Impedance Spectroscopy) method allows one to get a good view of the various components of the battery impedance. With this method an AC load of varying frequency is imposed on the battery, and the voltage swing over the battery is measured. The frequency sweep can go from the millihertz into the megahertz range, and can be used to generate a Nyquist plot like shown above.
Through model fitting, the values of the individual components in the model can than be determined.
For Li-Ion, the values of these components can be used as indicators.
As an example, experimental results on Li-Ion batteries show that when the battery capacity drops from 3100 mAh to 2600 mAh due to ageing, the value of Rb rises from 44 mΩ to 51 mΩ, the value of RSEI remains between 6 mΩ and 7 mΩ, and the value of Rct rises from 6 mΩ to 20 mΩ.
In spite of the insights EIS can give, it has a couple of drawbacks:
As a result, this method is very interesting, but unsuited for implementation in a handheld tool.
Fast measurement of full impedance spectra is possible via the use of multi-sine methods, or via time domain methods. More about this later on.
Few "small lab" tools exist that support EIS. Examples are the Biologic Potentiostat, Hioki IM3590 and BT4560, or the BK Precision BA8100, all costing several thousands of Euros. But one can already get an idea about EIS via the CN0510 circuit, for a significantly lower budget:
An implementation example of a tool is CN0510 from analog.com. It allows EIS measurements on various types of batteries. Note however that the signal handling board (EVAL-AD5941BATZ), by default, is only usable in the frequency range of about 4Hz - 5Khz. Outside of that, the accuracy is degraded, and below 1Hz, the noise of the input circuitry gets quite noticeable (1/f noise). With the following minor modifications, 0.5Hz - 5kHz can be made possible though:
For the impedance analysis and the model fitting, several software packages exist, like ZView or impedance.py. See the /EISMeasurements directory in this repository for some fitting tests with both of these tools.
For more information on EIS and alternative methods, see for example https://www.gamry.com/application-notes/EIS/basics-of-electrochemical-impedance-spectroscopy/ or https://doi.org/10.1016/j.jpowsour.2020.228742.
Note that EIS is used in a lot of fields, not only for batteries. However, research on batteries has gotten a significant boost lately with the widespread arrival of electric cars.
As mentioned above, EIS frequency domain analysis is not only complicated, but also lengthy. Time domain analysis methods have come up lately that allow acceptable approximations to the results that can be obtained via EIS. One of the approaches is called DCIS (Direct Current Impedance Spectroscopy), which is described here: https://www.mdpi.com/1996-1073/14/15/4396/htm
The idea behind DCIS (and other time domain methods) is that when one exposes the battery to current pulses, the voltage relaxation times give away details of the different RC components in the battery model. Care must be taken to exclude non linear behaviour and to tune the current pulses in such a way that the correct components can be derived easily.
One key phrase:
In the battery model, when the polarization potential change |∆ϕ| caused by an external signal is less than 10 mV and the signal time is short enough, the effect of concentration polarization (Zd in battery model) can be ignored.
I therefore need to keep the test currents low, and the pulses short. Both requirements perfectly fit my tool's design requirements.
In regular Li-Ion batteries, the various components show at various frequencies:
The approach is that for every individual component, 1 specific timed constant current pulse will be used. The width of the pulse is about 5 * RC time of the component. That gives:
The pulses are spaced out by a small relaxation time. The voltage drop over the battery is measured at the end of each current pulse, and the battery resistance at that point in time is calculated:
Unfortunately, I will want to do multiple measurements to drown out noise and do power line frequency compensation. That makes T3 unsuited for my tool, and I must limit myself to Rb and RSEI.
The timings mentioned above are suitable for your average Li-Ion 18650 cell. If you want to use the DCIS method on other battery layouts or chemistries, you can adapt the timings via SCPI commands (see CAL:T(1|2|PAUSE) {uint16} below).
The current pulse is sent through the battery, that is placed in series with a known resistor. The battery resistance is deducted from the relation between the voltage fluctuation over the known resistor and the voltage fluctuation over the battery. Hence, there is no need for a known current source, nor a known voltage reference.
With Ubatt as the voltage drop over the battery, Uref the voltage over the reference resistor, and Rref the reference resistor: Rbatt = Rref * (Ubatt/Uref).
Since Ubatt and Uref are so small, they are amplified by an AC coupled low noise instrumentation amplifier. The output signal is fed into the differential ADC of the processor. In order to avoid amplification differences and other signal path differences, multiplexing via a common measurement circuit is used. An input switch allows switching between the battery and the reference resistor.
The frequency cut-off point of the high-pass filter at the input of the instrumentation amplifier is well below the frequencies used in the measurements.
The (potentially large) DC offset at the entry of the circuit is cancelled at the start of the measurements, by a low impedance short of the signal to VCC/2. The short is applied for as long is needed, and stopped when the processor sees a close to 0V differential signal on the ADC.
In order to reduce the noise and the influence of the power line frequency, multiple samples are taken, and the results are averaged. The timing of the samples is adapted to the configured power line frequency: an identical number of samples is taken for each opposing polarity of the power line signal.
The software allows setting of the power line frequency (50 or 60) via SCPI commands.
This is the industry standard AC 1kHz test. A small 1kHz current (ideally sine wave) is applied to the battery, and the AC voltage at the battery is measured. The impedance is then deducted from the current and the voltage. This method is widespread, low power, and fast, so I can include it in my tool.
The maximum voltage swing allowed depends on the battery type, as above certain levels, the values would be skewed by other factors. For NiCd, that limit is about 20mV, and for Lithium chemistries, 10mV seems to be indicated. As a result, I do not set a test specific current, but adapt the test current to the selected range.
The "correct" duration of the test varies. EC 61951-1 for example states that the test duration must be 1 to 5 seconds, but that is not handy for fast manual use. A test duration of 100ms suffices normally.
The CPU I chose does not have a sine wave generator. It does have PWM, but making a sine wave with that was hard to do while running the ADC. As a result, I generate a 1kHz square wave on CPU, and do the transformation to a sine wave with an analog phase-shift circuit. That signal is then, after some amplification and level shifting, fed into a voltage controlled current sink.
Instead of a full fledged FFT/DFT, Goertzel's Algorithm is used. It is essentially a mathematical bandpass filter that gives a magnitude (and phase) reading. It is especially suited as I generate the 1kHz tone myself and can sync the ADC sampling to that tone generation. As a result, it is very light on resources: I can do the calculations while sampling, and do not need large memory buffers.
About the configuration of Goertzel:
Some of the inspirations:
The CPU having limited RAM, I prefer to do the tone generation, ADC sampling and AC analysis all in sync, run-time. I do not sample and analyse later, as that would take too much RAM. It also gives me the possibility to make the sampling as long as I want, increasing noise suppression. It however requires an optimised ADC loop, so I go outside of megaTinyCore's analogRead() function.
As I have low noise pre-amps, I do not use the PGA: I set gain 0.
The trigger generator is TCA0, the most capable of the timers on the CPU, and I trigger the ADC sampling via the Event system (ADC_START_EVENT_TRIGGER_gc and USERADC0START). During sampling, I generate the 1kHz square wave in code, and do the Goertzel calculations. Tests have shown that at a 10kHz trigger signal, I have about 20us CPU time left per sample. 12kHz would not be possible, unless I raise the ADC clock rate. Maybe also CCL could help, but I haven't looked.
Interrupts are only used for error conditions on the ADC. Other interrupt sources, like the time library, are disabled, as it would provoke jitter or overruns.
As this is time critical code, debugging support is available in code, via USEREVSYSEVOUTC for example.
I do not use tone(), as that is interrupt driven.
A sine wave of 1 kHz is sent through the battery, that is placed in series with a known resistor. The battery resistance is deducted from the relation between the AC voltage over the known resistor and the AC voltage over the battery. Hence, there is no need for a known current source, nor a known voltage reference.
For more details, see the chapter on "Ratiometric approach" in the description of the DCIS method.
Also here, DC offset cancelling and power line frequency compensation is used. See the related chapters in the description of the DCIS method.
This method is frequently encountered, because it is very simple. It is in essence a DC measurement technique.
The cell shall be discharged at a constant current of value I1. At the end of a discharge period of T1 s, the voltage U1 during discharge shall be measured and recorded. The discharge current shall then be immediately increased to a constant value of I2, and the corresponding voltage U2 during discharge shall be measured and recorded again at the end of a discharge period of T2 s.
Therefore: Rdc = (U1 - U2)/(I2 - I1)
The currents I1 and I2, and the times T1 and T2 depend on the type and capacity of the battery. Example: For NiCd, I1 is normally between 0.2 and 1 times the C value in Amps, I2 = 10 * I1, T1 = 10, T2 = 3. For Lead Acid batteries, the currents can become even larger.
Those large currents, and the accompanying dissipation, make it unsuited for integration in a small handheld tool. Also, because this is such a crude method, abstracting most of the battery model, I am not using this method.
Please note that the flash memory is close to the limit: it is 97% full.

The case chosen is a Hammond 1593DBK. That case comes with flat and curved front/back panels. Use the flat one for the back.
The nose cone is 3D printed, see the nose cone STEP file. The holes for the pins may be too small, I had to drill them out.
The pogo pins in the nose cone are regular R100-1W sockets, with P100-B1 pogo pins. For images and dimensions, see the pogo-* files in the /img folder.
The probe connector at the back is a "avionics" XS10 4P male connector, the same as on the YR1035+. This connector accepts regular YR1035+ compatible 4W probes, or in conjunction with the nose pogo pins, a custom made - probe (just half of the regular 4W probe). The nose pogo pins are directly connected to the + pins on the XS10 connector. As a result, one can also connect a 4W rig:

The serial connector/charge plug is a USB micro B. I should have chosen USB-C, but I still had a lot of USB micro B connectors.
The navigation switch is a SLLB510100 from Alps Alpine. You probably need some glue to fix it on the PCB, as the "fixing" tabs on the side are very/too small.
The reference resistors are all used in a 4W (kelvin) setup, either through the use of 4W resistors, or in a "poor man's" way, via the PCB layout:
.
All components on the board are specified in the kicad files. The choice of components is, as can be expected, influenced by the component shortage during 2021-2022.
The input circuitry is protected against reverse polarity and moderate overvoltage.
If a rechargeable battery is used, the USB charges the battery via trickle charging at about 0.05C for your average 850mAh NiMh AAA battery. This charge current is so little that charging while ON is not possible. Therefore: Charge while OFF.
ON: short press button at the back.
OFF: long press button at the back, or via software control.
Switch between AC and DCIS measurement, or leave remote control: press the navigation switch.
Change range: via left/right of the navigation switch. The 'Auto' range is at both ends.
Note that due to the time-critical way the measurements are done, button presses are only detected between measurements, sometimes resulting in sluggish reactivity. See below under Imperfections.
The procedure for the calibration of the trim pot on the PCB is explained in the schematic.
The calibration of the current ranges is best done through measurement of the used resistors, and storage via the SCPI commands, or via code.
By default, the meter prints out all measurement results on the USB serial output:
The serial interface also supports a reduced set of SCPI commands. Any command (valid or not valid) on the serial interface will interrupt "local" measurements, and will allow remote control via the SCPI commands. To go back to "local" control, just press the navigation switch.
SCPI commands should be terminated with newline. Chaining (;) is not supported.
The following SCPI commands are supported:
*IDN?: Identify.*HELP?: Usage. List all supported commands.SYST:ERR?: Show the last error message.SYST:DIAG:(ON|OFF): activate or deactivate diagnostic output. Once set, it prints additional info after a measurement, even when going back to "local" control.MEAS:VOLT:(INP|INT|AC|DCIS)?: various measurements, one per command.
INP: input (test) voltageINT: internal battery voltage and battery gauge percentageAC: 1kHz impedance: R~DCIS: RB and RSEICONF:RANGE (AUTO|1|2|3|4): Set the current range.CONF:RANGE?: Get the current range.CAL:INPV {uint16}: Set input voltage multiplication factor (mV@1V).CAL:INPO {int16}: Set input ADC offset (between +500 and -500). Best is to define INPV and INPO via fitting, to compensate for some small non-linearities.CAL:INTV {uint16}: Set internal voltage multiplication factor (mV@1V).CAL:VMIN {uint16}: Set internal battery range min (mV).CAL:VMAX {uint16}: Set internal battery range max (mV).CAL:R(1|2|3|4) {uint16}: Set reference resistor value, for a specific range. The integer value to be entered is to be expressed as a multiple of a factor that depends on the range: 1:mΩ, 2:100µΩ, 3: 10µΩ, 4:µΩ.CAL:T(1|2|PAUSE) {uint16}: Set DCIS timings for T1, T2, and Tpause (the pause time between the pulses), in (µs). T1 must be between 100 and 500, T2 between 100 and 50000, and Tpause between 5000 and 10000.CAL:PLF (50|60): Set power line Frequency (50 or 60).CAL:SAVE: Save all cal values to EEPROM.DIAG:CAL?: Show all active calibration values (may not be saved yet).| Type of voltage | Range | Resolution |
|---|---|---|
| Input/Test | 0 - 20.00 V | 10 mV |
| Internal battery | 0.800 - 2.000 V | 1 mV |
Below 1.1V input voltage, the resistance measurements will not work, and the display will show "low v".
Internal battery voltage is only readable via SCPI. Below 0.8V internal battery voltage, the device will likely not function.
The numbers below apply to all resistance types: (R~, Rb, RSEI):
| Range | range | resolution | max test current |
|---|---|---|---|
| 1 | 150.00 Ω | 10 mΩ | 0.1 mA |
| 2 | 10.000 Ω | 1 mΩ | 1 mA |
| 3 | 1000.0 mΩ | 0.1 mΩ | 10 mA |
| 4 | 100.00 mΩ | 0.01 mΩ | 100 mA |
Accuracy depends on the calibration, but with proper calibration, can be as good as 0.05% full scale.
The software (settingsShow4Digits()) allows the removal of the least significant digit.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 13 | 0 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R22, R23, R24, R49, R50, R51, R52, R54, R55, R56, R57, R59, R63 |
| 13 | 100nF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C1, C8, C10, C12, C14, C15, C21, C22, C23, C26, C31, C33, C34 |
| 10 | 100k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R6, R9, R28, R29, R31, R41, R42, R45, R60, R68 |
| 7 | 10nF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C16, C17, C18, C19, C28, C29, C30 |
| 7 | 10uF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C6, C7, C9, C11, C25, C32, C35 |
| 5 | 10M | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R5, R8, R18, R19, R69 |
| 5 | 10k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R11, R46, R47, R61, R65 |
| 5 | 1k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R7, R34, R35, R38, R40 |
| 4 | 47k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R25, R26, R27, R36 |
| 3 | 100uF 6.3V | Capacitor_SMD:C_1206_3216Metric_Pad1.33x1.80mm_HandSolder | C3, C4, C5 |
| 3 | 1M | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R14, R15, R39 |
| 3 | PTC 100mA | Fuse:Fuse_1206_3216Metric_Pad1.42x1.75mm_HandSolder | F1, F2, F3 |
| 3 | VESD03C1-02V | Diode_SMD:D_SOD-523 | D2, D6, D7 |
| 2 | 120 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R58, R62 |
| 2 | 1uF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C20, C24 |
| 2 | 270 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R16, R17 |
| 2 | 47 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R20, R21 |
| 2 | 4k7 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R13, R48 |
| 2 | 68 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R53, R64 |
| 2 | 74AUP1G02 | Package_TO_SOT_SMD:SOT-353_SC-70-5_Handsoldering | U13, U14 |
| 2 | Conn_01x02_Male | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | J5, J9 |
| 2 | DG4052EEQ-T1-GE3 | Package_SO:TSSOP-16_4.4x5mm_P0.65mm | U4, U5 |
| 2 | DMN62D0UDW-13 | Package_TO_SOT_SMD:SOT-363_SC-70-6 | Q1, Q2 |
| 2 | MAX4636EUB+ | Package_SO:VSSOP-10_3x3mm_P0.5mm | U3, U9 |
| 2 | MountingHole | MountingHole:MountingHole_3.2mm_M3_ISO14580 | H1, H2 |
| 1 | 0.5 Ohm precision | mylib:R_1206_3216Metric_4Wire | R2 |
| 1 | 100 | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R37 |
| 1 | 100pF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C13 |
| 1 | 100uF 25V | mylib:KCM55WC71E107MH13 | C2 |
| 1 | 15k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R33 |
| 1 | 1M | mylib:Potentiometer_Bourns_PV36W_Vertical | RV1 |
| 1 | 1M 1% | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R44 |
| 1 | 1N4148 | Diode_SMD:D_SOD-123 | D4 |
| 1 | 220 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R10 |
| 1 | 330k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R66 |
| 1 | 33pF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C27 |
| 1 | 4.7uH Shld | mylib:L_Coilcraft_LPS4018 | L1 |
| 1 | 45 Ohm precision | mylib:R_1206_3216Metric_4Wire | R4 |
| 1 | 470 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R12 |
| 1 | 470k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R67 |
| 1 | 5 Ohm precision | mylib:R_1206_3216Metric_4Wire | R3 |
| 1 | 50mOhm precision | mylib:R_Shunt_Ohmite_LVK12_ALT | R1 |
| 1 | 74AHC1G08 | Package_TO_SOT_SMD:SOT-23-5_HandSoldering | U8 |
| 1 | 82k | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R32 |
| 1 | 8k2 | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R30 |
| 1 | 9M1 1% | Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R43 |
| 1 | ATtiny3226-SU | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U1 |
| 1 | Battery_Cell | Battery:BatteryHolder_Keystone_2466_1xAAA | BT1 |
| 1 | CH340E | Package_SO:MSOP-10_3x3mm_P0.5mm | U10 |
| 1 | Conn_01x02_Female | Connector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_Horizontal | J1 |
| 1 | Conn_01x03_Male | Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical | J6 |
| 1 | Conn_01x04_Male | Connector_JST:JST_XH_B4B-XH-A_1x04_P2.50mm_Vertical | J2 |
| 1 | Conn_01x11_Male | Connector_PinHeader_2.54mm:PinHeader_1x11_P2.54mm_Vertical | J4 |
| 1 | I2C_OLED_128x32 | mylib:I2C_OLED_128x32 | U2 |
| 1 | Jumper_2_Bridged | Jumper:SolderJumper-2_P1.3mm_Bridged_Pad1.0x1.5mm | JP1 |
| 1 | LED | LED_SMD:LED_1206_3216Metric_Pad1.42x1.75mm_HandSolder | D5 |
| 1 | MCP1642B-33I/MS | Package_SO:MSOP-8_3x3mm_P0.65mm | U7 |
| 1 | MMBZ20VAL,215 | Package_TO_SOT_SMD:SOT-23 | D1 |
| 1 | OPA4388ID | Package_SO:SOIC-14_3.9x8.7mm_P1.27mm | U6 |
| 1 | PCA9536D | Package_SO:SOIC-8_3.9x4.9mm_P1.27mm | U12 |
| 1 | Polyfuse | Fuse:Fuse_1206_3216Metric_Pad1.42x1.75mm_HandSolder | F4 |
| 1 | SW_Push | Button_Switch_THT:SW_Tactile_SPST_Angled_PTS645Vx83-2LFS | SW3 |
| 1 | SW_SLLB5 | mylib:SW_SLLB510100_handsolder | SW4 |
| 1 | TLV9062xD | Package_SO:VSSOP-8_3.0x3.0mm_P0.65mm | U11 |
| 1 | USB_B_Micro | mylib:USB_Micro-B_mine | J3 |
It measures 106 × 29.2 mm and has 4 copper layers, 1.6 mm thick.
145 parts, built around the ATTINY3226-SU, CH340E, OPA4388ID and MCP1642B-33I/MS. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the hb020/batterymeter repository on GitHub, at the commit this page was made from: the board is kicad/batterymeter/batterymeter.kicad_pcb and its schematic kicad/YR1035Plus/YR1035Plus.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask hb020 before reusing the design.

hb020/batterymeter
Handheld Battery AC and Time Domain characterization tool on Attiny series 2

hb020/batterymeter
Handheld Battery AC and Time Domain characterization tool on Attiny series 2

jtflanagan/AppleTini
Teeny 4.1-based multifunctional Apple II peripheral card




mayermakes/MyGenWashy
Generic washing Machine Controller - Result of the TuttleButtle Hackathon 2025

etherkit/EtherKeyerMini
A simple Morse Code keyer that does the basic functions you need


mayermakes/analog-bridge
modular logic probe (3V3 logic level, 16 channels per device, SCPI)