Microchip launched a new generation of ATtinys. Is it worthwhile to consider them for your next DIY project?
The short answer is: Yes, provided you are an ATtiny aficionado, you need more memory or better peripherals, and you are a bit adventurous. And the good news is that there is support for these chips in the Arduino universe.
Which MCU type is the right one?
When it comes to the question of which MCU is the right one for hobby projects, you mostly hear that ESP32, RP2040, or other ARM MCUs are the right choices. And they are all supported by the Arduino framework! Sometimes, you also hear that nothing below a Raspberry Pi is sufficient. Well, it all depends on what you are aiming for.
For most of my projects, I prefer the AVR MCUs, since they are extremely energy-efficient. I have installations (electronic geocaches) out in the wild that by now have run for 10 years on one battery. These MCUs have power-down current consumption of around 100 nA (that is 0.0001 mA!), from which they can be woken up in a few microseconds. ESP32- or ARM-MCUs need considerably more current during deep sleep, and can then only be rebooted. They also use considerably more power when active (20-100 mA instead of 2-10 mA). So, if you do not need Wi-Fi or Bluetooth connectivity and if your main objective is to be as energy-efficient as possible, I believe the AVR chips are the right ones for your project. My favorite for smaller projects, such as the Sunset Cache Box, is the ATtiny1634, which has 16 KB of flash memory and 1 KB of RAM.
What has happened so far?
In 2016, Microchip launched a new family of ATtiny chips with a slightly enhanced AVR architecture, but with some differences in communicating with the chips. In 2022, the newest addition to this family was introduced, the ATtiny3224/6/7, which is definitely something to consider when planning your next project.
The SOIC version of the ATtiny3226 comes in the same package as the SOIC version of ATtiny1634 but has 32 KB of flash and 3 KB of RAM (instead of 16 KB/1 KB). In addition, the peripherals it contains are superior, the execution speed of some instructions has been improved, and similar to the ATmega328P, it has hardware multiplication. Even better, these chips are cheaper than the ATmega328P. There are unfortunately no DIP versions around. However, the SOIC-20 footprint is still something that a hobbyist can handle with the soldering iron. The ATtiny3226, as well as the ATtiny3216, definitely look interesting. So, let us take a closer look.
But not only the hardware counts. The chips have also to be integrated into the Arduino framework. Spence Konde published the first version of the megaTinyCore for the new chip family in June 2019, which makes the new chips available in the Arduino framework. Since then, a lot of improvements have been made.
The new family
Fortunately, this time, the Zoo of different chips has a much more regular structure than in the past. The MCUs in the new family, called tinyAVR 0/1/2 series or megaTinyAVR, have a naming scheme as follows. After the name
ATtiny, the size of flash memory in KB (2, 4, 8, 16, 32) follows, then there is one digit for the series (0, 1, or 2), and finally one digit for the number of pins (2=8 pins, 4=14 pins, 6=20 pins, 8=24 pins). For instance, ATiny1614 has 16 KB flash, is a 1-series ATtiny, and has 14 pins.
Not all combinations have been implemented, but most of the ones that are reasonable are now on the market. Besides different memory sizes and pins, they also have varying kinds of peripherals. However, even here, the way the peripherals are assigned to the different types is quite regular. You will find a good overview of the different MCU types in the blog post on the new ATtiny family by Technoblogy.
So, what are the differences between the different series? The 1-series came out first in 2016. After that, a stripped-down version of the 1-series was developed: the 0-series. They are a bit cheaper but lack some functionality the 1-series has. Since the price difference is negligible, there is actually no reason to consider these in your hobbyist project.
Finally, in 2021, Microchip started to launch MCUs of the 2-series, culminating in the ATtiny322X in 2022. Interestingly, these are not upgrades of the 1-series. In other words, it makes sense to take a look at MCUs from the 1- and 2-series.
Meanwhile, these new chips appear to be generally available. I found them at DigiKey, RS-Online, and also at Reichelt, whereby the 2-series chips are not in the Reichelt catalog yet. The prices are very reasonable and actually cheaper than comparable classic AVR parts. The smaller chips are available for €0.40 to €0.60. The larger ones for up to €1.70. Given that the prices even for the largest pieces are so low, it probably makes a lot of sense to focus on them.
A point-by-point comparison of the ATtiny32X6 with the ATtiny1634 and the ATmega328P
Since the ATtiny1634 and the ATmega328P are my favorite MCUs (and, in particular, the latter one is probably an all-time favorite of most Arduino lovers), it makes sense to compare them point by point with the high-end chips of the 1- and 2-series of the new ATtiny family. I have chosen the 20-pin MCUs because these are available as SOIC-20, similar to the ATTiny1634. The 24-pin MCUs of these series are only available as VQFN, which is something you cannot solder manually.
|Flash||32 KB||32 KB||16KB||32 KB|
|RAM||3 KB||2 KB||1 KB||2 KB|
|EEPROM||256 B||256 B||256 B||1 kB|
|Pins/GPIOs||20/17||20/17||20/17||28/22 or 32/24|
|Packages||SOIC, SSOP, VQFN||SOIC, VQFN||SOIC, QFN||DIP, TQFP, VQFN|
|Power-down @ 5V/3.3V||0.1 µA/0.1 µA||0.1 µA/0.1 µA||0.1 µA/0.1 µA||0.2 µA/0.1 µA|
|Active @ 5V16MHz/3.3V8MHz/3.3V1MHz||7.5 mA/2.6 mA/0.3 mA||8.0 mA/2.6 mA/0.3 mA||-/2.3 mA/0.4 mA||9.5 mA/3.0 mA/0.5 mA|
|Instruction set||AVRxt (hardware multiplication, fast store)||AVRxt (hardware multiplication, fast store)||AVRe||AVRe+ (hardware multiplication)|
|Internal MHz max||20||20||8||8|
|External MHz max||20||20||12||20|
|Accuracy internal osc.||3.5 %||5 %||10 %||10 %|
|Timer/Counter||3x 16-bit, 1x 16-bit RTC||3x 16-bit, 1x 12-bit, 1x 16-bit RTC||1x 8-bit, 1x 16-bit||2 x 8-bit, 1x 16-bit|
|ADC||differential 12-bit with programmable gain (375 ksps)||2x 10-bit (115 ksps)||10-bit (15 ksps)||10-bit (15 ksps)|
|DAC||0||3x 8-bit (350 ksps)||0||0|
|USART||2 (one-wire, auto-baud)||1 (one-wire, auto-baud)||2||1|
|TWI||1 (100, 400, 1000 kHz)||1 (100, 400, 1000 kHz)||1 (slave-only, 100, 400 kHz)||1 (100, 400 kHz)|
|Programming interface||UPDI||UPDI||HVPP, SPI||HVPP, SPI|
Memory, pins, packages, and power consumption
The new chips obviously have enough memory for serious projects. The ATtiny3226 is also apparently the winner in the category RAM. And most of the time, the number of GPIOs should also suffice. The SOIC-20 package of the new ATtinys and the classic ATtiny1634 is not the comfortable DIP form factor, but it still can be easily soldered manually. With respect to power consumption, there appears to be little change to the classic parts.
When it comes to the instruction set, one notes that this has been improved. One now has hardware multiplication, and some instructions have become faster. These are all the subroutine calls (
xCALL), all indirect store instructions (
PUSH instruction, and the set/clear bit instructions on I/O registers (
CBI). Interestingly, one instruction is now one clock cycle slower. The
LDS (load direct) instruction takes now three instead of two cycles. Although these changes are not revolutionary, they can help when timing is tight, as in bit-banging I/O. Nevertheless, I would not consider that as a strong argument for using the modern AVR parts.
Clocking the MCU
As for the classic AVR chips, 20 MHz is the maximal clock frequency. However, the modern AVR chips have internal oscillators that can deliver this frequency (instead of 8 MHz). Moreover, these internal oscillators are much more accurate than the ones in the classic chips. And with the appropriate pre-scaler, you can get all the frequencies you would care about. So there is no need to attach crystal oscillators. And there is actually no possibility to do that. The only other option is to use an external clock. I believe that these highly accurate internal oscillators make life much easier, and the use of external oscillators is only necessary for projects that have high demands on accuracy.
There are more timer/counters, and they have a higher resolution than the ones known from the classic AVR chips. Most notable is the dedicated real-time counter (RTC), which can be driven by an ultra-low-power 32 kHz oscillator. This can be used to continue timekeeping while the MCU is in the standby state. And one can use it to wake up periodically, as it was previously done with the watchdog timer interrupt (which does not exist on the newer parts). With the RTC on standby, only 1 µA is used instead of up to 5 µA with the WDT in power-down. Whether this is an argument for using the new AVRs depends, of course, on the application requirements.
ADCs, DACs, and PTCs
The analog-to-digital converters (ADCs) have generally improved quite a lot. In the 1-series, you have two separate 10-bit ADCs. In addition, there are three (!) 8-bit digital-to-analog converters (DACs), and a peripheral touch controller (PTC). The latter two are things, you usually find only on the larger AVRxxxDy MCUs. The PTC, though, is only supported by the binary Microchip QTouch library, which has not yet been integrated into the Arduino framework.
On the 2-series MCUs, you have instead of the ADCs, the DACs, and the PTC, one differential 12-bit ADC with programmable gain! In both cases, the ADCs are many times faster than the ones on the classic AVRs!
While these are very impressive peripherals, I usually do not have much use for them.
The USART(s) on the modern AVRs, the ATtiny3226 has two of them, has a lot more to offer than the ones on the classic chips. They cater to a larger number of different bit rates using a fractional baud rate generator, they can be used to implement one-wire communication similar to the one I implemented in the SingleWireSerial library, and they have an auto-baud feature, which sets the baud rate according to a synchronization byte received after a break condition.
Continuing with the remaining serial communication peripherals, TWI and SPI are at least as good as on the ATmega328 chip. In fact, now 1 MHz TWI is supported, which was not the case before. And they beat the ATtiny1634, which has only TWI slave and SPI master functionality.
Memory integrity checks
Let us now take a look at features not seen before on classic AVRs. First, there is the CRC scan. At each reset, one can instruct the CRC scan module to automatically check the flash memory and compare it with a precomputed and stored CRC value. This is probably not a feature that is high on my priority list. However, for long-term installations, it makes sense since flipped bits (caused by radiation or other causes) in flash memory can make life very difficult and lead to hard-to-diagnose failures.
So, what are CCL LUTs? CCL stands for configurable custom logic. The idea is that one can configure combinatorial logic circuits. The inputs of such circuits can come from GPIOs, peripherals, and from the event system, which we will talk about in a minute. The outputs can be GPIOs, the event system, and the outputs can even raise interrupts (on the 2-series chips). The single circuits, which can have 3 inputs, are specified using look-up tables (LUTs), i.e., essentially truth tables that specify the Boolean function the circuit is supposed to implement. This means CCL can help to deal with the most time-critical parts of a system and can be thought of as substituting discrete logic circuits.
The event system connects different peripherals with each other without going through the CPU. For example, a timer overflow event in a timer can be connected via an event channel to the ADC, starting a conversion. This is something usually implemented using interrupts, which costs a few cycles. With the event system, it is instantaneous.
My projects so far never involved something like having direct connections between peripherals, perhaps mediated by logical circuits. However, that does, of course, not mean that this will stay so in the future.
Interrupts on the classic AVRs have just one level. If one interrupt is served, then another one can take over only if the interrupt routine of the first interrupt enables interrupts again. The interrupts are prioritized so far as if many different interrupts are pending, then the interrupt priority decides which to handle next.
With the modern AVRs, things are much more flexible. First, there exists one non-maskable interrupt, the CRC scan failure interrupt. This one will fire if enabled, even when the interrupts are globally blocked. Second, we have two levels of interrupts. One can declare one IRQ to be level 1, which will interrupt all level 0 interrupt routines. The level 0 interrupts still have priorities. However, they can be changed. Furthermore, one can serve the interrupts in a round-robin way, guaranteeing that each one is eventually served.
Having two levels of interrupts can sometimes make life much easier. For example, I wished, I had something like that when implementing the debugWIRE debugger dw-link in order to prioritize dwbugWIRE communication.
Programming and debugging
The main difference between the modern and the classic AVR chips is the hardware interface for programming the chips. One needs new hardware (and software) to do the actual hardware programming. This is something, we will discuss in the next section.
UPDI: Unified programming and debugging interface
The classic AVR chips can all be programmed using the ISP/SPI protocol. Debugging takes place by either using debugWIRE or JTAG.
With the modern AVR chips, tiny or mega, this has changed. UPDI is now the protocol for programming and debugging. This protocol just uses one (asynchronous serial) open-drain, half-duplex, bidirectional UART line using the auto-baud feature. In other words, for programming and debugging, it uses just one line in addition to GND! The SWD protocol for ARM MCUs uses a data line and a clock line together with GND. The JTAG protocol needs even more lines.
Conceptually, UPDI looks to be very lean and clean. However, you have to find or build a new programmer. Of course, one could use the Microchip programmers/debuggers such as Atmel ICE or Snap. But these are quite pricey. Instead of that, the SerialUPDI solution is probably the cheapest and easiest solution. You simply take a USB-UART converter and join the RX and TX line, using a resistor and/or diode. Spence Konde covers the possibilities in his SerialUPDI guide.
From this guide, you will also learn that FT232 converters are not ideal, because they have by default a high latency when changing I/O directions. This can be reconfigured under Windows and Linux, but not on macOS. CH340 and CP2102 chips are a much better choice. PL2303 and HT42B435 are apparently chips to be avoided. Further, if you plan to program 3.3 V and 5 V systems, it is best to choose a board that allows for changing the supply voltage. Further, make sure that the signal voltage is not fixed at 3.3 V as it is on some converters. This works with the older AVRs, but the new generation requires 0.7Vcc as the minimum voltage for recognizing a high level, which is 3.5 V on a 5 V system.
First experiments with a CP2102 board worked out perfectly, as shown above. I had to select
SerialUPDI ... w/write delay on macOS. But otherwise, it worked out fine, not only with the blink sketch, but also with larger sketches. With a CH340 converter, it also worked, but I had to remove the 470 Ω resistor.
If you do not have a USB-UART converter lying around, but you have an Arduino Nano or UNO that you do not need any longer, then you can use the converter on the board. Simply connect GND and RESET on the board, which will make all ATmega328P pins high impedance, and then use the TX and RX pins. These are named the wrong way around compared to ordinary serial converters because the pins are labeled from the perspective of the ATmega chip. And it will work only for 5 V systems, though.
I tried that out with the Nano boards I have. Although the original Arduino Nano you can see in the photo uses an FTDI 232RL, it worked without a problem. It was, perhaps, a tad slower. On the other hand, a clone that used a CH340 did not work. I have no idea why.
In summary, SerialUPDI seems to work. Perhaps, a bit of experimentation is necessary in order to get the best configuration.
Conclusion and outlook
Since no open-source debugging solution is available, I will also have a look into that in the near future. In other words, I plan to write a gdbserver for the megaTinys, either as a Python script or as an Arduino sketch for, e.g., the Nano Every.