After years of staying away from the Arduino--too many abstractions getting in the way of knowing how things really worked--I was drawn back by the Uno R4 Minima.
UNO ARRRR 4 MINNIMEE, MATE!
Shiver me Timbres!
Feature-wise, the R4 looked a bit like the cool and popular Teensy. It features a 32-bit Renesas RA4M1 ARM Cortex M4 processor, 14-bit ADC's and a built-in 12-bit DAC.
It's a performance improvement from the Uno R3's 8-bit processor and 10-bit ADC's.
I bought two R4 Minimas and updated my Arduino IDE to the current version.
I also purchased a few R4 workalikes from SEEED: the XIAO-RA4M1:
 |
Seeed XIAO RA4M1 is a truly dinky Uno Minima R4--the connector seen here is USB-C, giving you an idea of its small size. |
The R4 can be easily programmed from the Arduino IDE; for me, plug it in and go.
After making sure a blink sketch worked, the next thing I tried was the analogWave.h library.
The library let me whip up audio frequency waveforms fast, fast, FAST, with only a few lines of code:
////////////////////
#include "analogWave.h" // Include the library for analog waveform //generation
analogWave wave(DAC); // Create an instance of the analogWave //class, using the DAC pin
int freq = 10; // in hertz, change accordingly
void setup() {
int pin = 0;
analogWriteResolution(12);
wave.saw(freq);
//limit of freq seems to be about 30hz to 10k for this library
}
void loop() {
// Read an analog value from pin A5 and map it to a frequency range
freq = map(analogRead(A5), 0, 1024, 0, 10000);
wave.freq(freq);
}
//////////////////////
When I connected the R4's DAC to my scope I was pretty disappointed--the output looked "stair-step":
I found
TriodeGirl's sketch that produced a better sounding ramp wave from the same hardware--but relied on banging the stuffing out of the MCU's registers; if I was going to do that, I might as well stick with the
RP2040 and
2350, which I felt were better documented.
 |
TriodeGirl's Audio output--looks much better--saw @ about 366hz. |
OK, how about creating an audio frequency sawtooth waveform using
analogWrite()?
I wrote a single value to the DAC, and on the next run through loop(),increased the output amplitude by one; when the output amplitude got to 255, returned it to zero.
That didn't work perfectly either; the output looked "hairy":
Read more about this error
here.
I decided I'd pass on the R4's DAC for all but the most "DC" applications.
Beyond that the SEEED and Arduino R4 Minima seemed affordable and tightly integrated into the world of Arduino; they will likely find their way into future projects.
ATTINY412 and UPDI
Microchip's ATTINY's had come a long way since I last used a "series 0" ATTINY85 (previous post
here).
Newer series 1 and 2 ATTINY's use a proprietary one-wire programming protocol called
UPDI; they could be reprogrammed without having to remove the chip from its PCB or breadboard.
Cool!
I got a few of these tiny spuds (all SMD)--for the rest of this post I will concentrate on the ATTINY412 and ATTINY1624.
 |
Attiny412--8 Pin SOIC SMD |
PROGRAMMING UPDI
The ATTINY 412 needed a toolchain; Bitluni's YouTube video got me started (here).
Using the "megaTinyCore" library I got a boring blink sketch to work using my Atmel ICE programmer.
Atmel's ICE documentation (here, go to page 40) was a bit crap about ICE > UPDI wiring, but I figured it out:
The code:
/*
pins for digital on ATTINY412
IC's PIN2 is 0
PIN3 is 1
PIN4 is 2
PIN5 is 3
PIN6 is 5
PiIN7 is 4
*/
int GPIOOUT = 4;
void setup() {
pinMode(GPIOOUT, OUTPUT); // pin 7 of ATTINY412
}
void loop() {
digitalWrite(GPIOOUT, HIGH); // turn the LED on (HIGH is the voltage level)
delay(250); // wait for a second
digitalWrite(GPIOOUT, LOW); // turn the LED off by making the voltage LOW
delay(250); // wait for a second
}
Next I tried to get an Arduino Nano going as a programmer, that meant getting a CH340 driver working, tricky on my Windows 11 Pro system; I followed the instructions from Sparkfun (here).
After a few reboots combined with unplugging and reconnecting the NANO, the CH340 was visible in Window's device manager; the Nano came to life with its preprogrammed blink.
Next I created an INO file and folder to upload UPDI code into an Arduino Nano clone.
I got the code from GitHub here; here's how I got the data onto the Nano.:
- Create new folder "jtag2updi" for the sketch << new directory must be named exactly this
- Put all the files from the repo: ino, cpp .h, blah blah, into this directory
- Open up the Arduino IDE
- Open the seemingly empty .ino file in the jtag2updi directory using Arduino sketch IDE
- Compile
- Upload to Nano
- Worked!
I DREAMT OF WIRES
Evening 1 the Nano UPDI toolchain worked but it stopped working soon after.
Try as I might to get firmware to upload--any firmware, to any UPDI ATTINY, using different NANO's--nope.
I even went back to the Atmel ICE--double nope.
That anxious night I dreamt of fixing the problem: soldering MCU's to the roof of a fast moving train, using my scope to look at logic levels while in a warm swimming in a pool, and best of all, talking tech with Cornelius from "Planet of the Apes."
No eureka moment!
I ended up finding an excellent ATTINY video from IMSAI guy (here) who laid out the 4 steps in the Arduino IDE that must be done right for any ATTINY UPDI upload to work:
- I had to choose the right board family ("414/412/212/402", something like that?)
- I had to choose the right serial port (for me, the CH340 on the Nano programmer, found on Port 6 of my Windows 11 system)
- I had to choose the right programmer ("JTAG2UPDI")
- I had to choose the right processor (in my case, ATTINY412)
I missed the step where I needed to choose the right processor; I had the rest right; sorry, Cornelius.
With that sorted I had no more issues with the Nano > ATTINY412 toolchain.
BTW, the "series 1" ATTINY MCU's--412 is part of this series--has an 8-bit
DAC. I did some quick experiments and, unlike the R4, the built-in DAC worked great.
 |
DAC output from ATTINY412--nice! |
I concluded that the ATTINY 412 would be a great processor for anything that has to be done super small (SOIC 8 pin, no external crystal needed) and super cheap (the 412 at the time of writing this was about 70c USD for Quantity 1).
Overall, a win. Great chip--1001+ uses.
An aside: PCBWAY
Many thanks to
PCBWAY for sponsoring this blog and for all the help they've provided over the years. You can help out this blog immensely by checking out PCBWAY,
here.
As soon as I get my first ATTINY series 1+2 project going, it's off to PCBWAY to get the PCB's made along with any other fabrication, including
3D printing and
assembly.
Please consider using PCBWAY for your next audio project.
ATTINY 1624: Amazing ADC value!
With the jtag2updi Nano toolchain working reliably I turned my attention to an
ATTINY 1624.
At the time of writing this post this was a USD $1.19 part--quite affordable.
I read
here that its "mux'd" built-in Analog to Digital converter ("ADC") can simultaneously bring in 15 (!!!) 16-bit resolution or better analog inputs.
Really? On a $1.19c part?
I had to see!!!
Not so fast....I screwed up and ordered TSSOP SMD ATTINY1624's--instead of the larger SOIC version--TSSOP presenting a truly tiny ATTINY.
Could I make these miniscule spuds work?
 |
To solder the TSSOP 1624's I dabbed some solder paste on 14-pin TSSOP to DIP adapters, dropped on the chips, and put them on a hotplate. After cleaning up the connections with solder wick, they worked! |
 |
Go A's! |
I got the mandatory blink sketch working then turned my attention to seeing if the ADC's really produced 16 bit output.
 |
Breadboard wiring for the 1624 ADC proof of concept |
The code:
unsigned long adc0,adc1,adc2 = 0;
unsigned long millis0=0;//initial ms reading
unsigned long millis1 = 0; // ms reading to compare
int x = 2;
unsigned long int next_millis = 0;
#define UART_TX_PIN 7
void setup() {
//start begin statement here.
pinMode(7, OUTPUT); //UART transmit (TX)
pinMode(PIN_PA3, OUTPUT); // LED
pinMode(PIN_PA4, INPUT); // use chip pin 2 as ADC
pinMode(PIN_PA5, INPUT); // use chip pin 3 as ADC
pinMode(PIN_PA6, INPUT); // use chip pin 3 as ADC
Serial.begin(9600);
millis0 = millis();
}
void loop() {
millis1 = millis();
//toggle LED without using delay() stupidity
if ((millis1 - millis0) > 250) {
int state = digitalRead(PIN_PA3); // Read current state
digitalWrite(PIN_PA3, !state); // toggle LED
millis0 = millis();
//print progress bar
Serial.print("#");
x++;
if (x > 3)
{
adc0 = analogReadEnh(PIN_PA4,16);
adc1 = analogReadEnh(PIN_PA5,16);
adc2 = analogReadEnh(PIN_PA6,16);
Serial.print(adc0);
Serial.print("; ");
Serial.print(adc1);
Serial.print("; ");
Serial.print(adc2);
Serial.print("; ");
Serial.println();
x = 0;}
}
} // end main loop
It worked! The programmed 1624 sent 3x ADC reads to serial out while flashing an LED.
Holy ADC, Batman!
In my mind, this means I could get high quality Analog to Digital conversion, 10+ channels worth, for less than $1.20USD per IC.
You're kidding right?
And I got all the extra functionality of the MCU to boot. I could use serial, I2C, or SPI to send this data downstream to other elements--maybe another ATTINY MCU.
The ATTINY series 1 and 2 had some other cool features. I really liked
Configurable Custom Logic or "CCL." This allowed me to create any small and reasonably simple logic part I could imagine using only an ATTINY--a really good introductory video for CCL is
here--I may dedicate another post to CCL.
OK enough for this one, I am typing way too much and still waiting for the AI to kick in.
Not yet? See ya next time.