Digispark ATtiny85 mit Arduino und AVR-GCC in Betrieb nehmen
Der ATtiny85 hat 8 KB Flash-Memory, 512 Byte RAM, 4 ADC-Kanäle, SPI, I2C, PWM und das alles in einem kompakten 8-Pin-Gehäuse. Er kann von 1,8 bis 5,5 Volt betrieben werden und eignet sich für allerhand Mini-Anwendungen. Beim Digispark ist er bereits so auf einer Platinge gelötet, dass er direkt an einen USB-Anschluss gesteckt und verwendet werden kann, und das für einen schmalen Taler.
Inbetriebnahme des Digistump Digispark Attiny85
- wird er korrekt erkannt?
Den Digispark am USB-Port einstecken und via lsusb schauen, ob er korrekt erkantn wird.
lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 051: ID 16d0:0753 MCS Digistump DigiSpark
[...]
Micronucleus kompilieren und installieren
- Der Digispark kommt mit dem Micronucleus USB-Boot-Loader
- So kann man direkt via USB Programme laden
- Achtung - diese Bootloader braucht ca. 2KB des Flash-ROMs im ATtiny85
-
Kompilieren und Installieren des Micronucleus-Kommandozeilen-Programms unter [Gentoo-] Linux
- USB-Entwicklungsbibliotheken libusb-devel installieren, wenn nicht bereits vorhanden
# emerge dev-libs/libusb dev-libs/libusb-compat
- Micronucleus von Githup clonen, kompilieren
git clone https://github.com/micronucleus/micronucleus.git
$ cd micronucleus/commandline
$ make
Building library: library/micronucleus_lib.c...
gcc -Ilibrary -O -g -D LINUX -c library/micronucleus_lib.c
Building library: library/littleWire_util.c...
gcc -Ilibrary -O -g -D LINUX -c library/littleWire_util.c
Building command line tool: micronucleus...
gcc -Ilibrary -O -g -D LINUX -o micronucleus micronucleus.c micronucleus_lib.o littleWire_util.o -static -L/usr/lib64 -lusb
/usr/lib/gcc/x86_64-pc-linux-gnu/14/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lusb: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:76: micronucleus] Error 1
- Wie man sieht, kann man Micronucleus zumindest auf meinem Gentoo-System nicht statisch linken, weil keine libusb-1.0.a vorhanden ist
- deshalb linken wir kurzerhand dynamisch, dies wird auch so im Makefile erwähnt: If you get an error about missing USB libraries, unset STATIC
$ gcc -Ilibrary -O -g -D LINUX -o micronucleus micronucleus.c micronucleus_lib.o littleWire_util.o -L/usr/lib64 -lusb
$ ldd micronucleus
linux-vdso.so.1 (0x00007ffd37fe9000)
libusb-0.1.so.4 => /usr/lib64/libusb-0.1.so.4 (0x00007f0eb6ecd000)
libc.so.6 => /usr/lib64/libc.so.6 (0x00007f0eb6cdd000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0eb6f2d000)
- Das fertige Binyary kann dann als root nach /usr/local/bin kopiert werden
$ su
Password:
# cp micronucleus /usr/local/bin/
- um Micronucleus als normaler Benutzer verwenden zu können, braucht man eine UDEV-Regel
-
Hier kann man verschiedene verwenden, es sind auch Beispiele dabei, ich nehme diese
- Datei /etc/udev/rules.d/60-micronucleus.rules mit folgendem Inhalt erzeugen:
ACTION=="add|change", SUBSYSTEMS=="usb", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", ENV{ID_MM_DEVICE_IGNORE}="1", TAG+="uaccess"
- udev-Regeln neu laden
# udevadm control --reload-rules
Testen von Micronucleus
- Mit diesem Hex-File, dass einfach nur die LED auf dem Digispark blinken lässt, kann schon mal getestet werden
- der Digispark muss zum Programmieren an-/abgesteckt werden, da der Bootloader nur in den ersten 5 Sekunten eine Programmierung zulässt, danach wird die Applikation gestartet
- Hex-File hier downloaden: … Download simple-test.ino.hex
- Die Micronucleus-Kommandozeilen-Option –run startet die Applikation direkt nach dem Flashen
chrissie@fehmarn ~ $ micronucleus --run simple-test.ino.hex
> Please plug in the device ...
> Device is found!
connecting: 33% complete
> Device has firmware version 1.6
> Available space for user applications: 6012 bytes
> Suggested sleep time between sending pages: 8ms
> Whole page count: 94 page size: 64
> Erase function sleep duration: 752ms
parsing: 50% complete
> Erasing the memory ...
erasing: 66% complete
> Starting to upload ...
writing: 83% complete
> Starting the user app ...
running: 100% complete
>> Micronucleus done. Thank you!
Updaten des Boot-Loaders im Digispark
- Der Digispark wird per default (jedenfalls bei mir) mit dem Bootloader 1.6 ausgeliefert. Das Upgraden bringt zusätlichen freien Speicher!
- Upgradevorgang
micronucleus --run firmware/upgrades/upgrade-t85_default.hex
- Man gewinnt ĂĽber 600 Bytes, das kann in boards.txt im Verzeichnis ~/.arduino15/packages/digistump/hardware/avr/1.6.7/ fĂĽr Arduino direkt so eingetragen werden:
#digispark-tiny.upload.maximum_size=6012
digispark-tiny.upload.maximum_size=6650
Arduino IDE
- arduino-1.8.19-linux64.tar.xz von der Arduino-Homepage downloaden: Arduino Software
- nach /opt/ entpacken
fehmarn ~ # cd /opt/
fehmarn /opt # tar -xvf /home/chrissie/Downloads/arduino-1.8.19-linux64.tar.xz
fehmarn /opt # cd bin/
- Binary symlinken (bei mir ist /opt/bin im PATH), avr-gcc-Version kurz antesten
fehmarn /opt/bin # ln -s ../arduino-1.8.19/arduino arduino
chrissie@fehmarn ~ $ /opt/arduino-1.8.19/hardware/tools/avr/bin/avr-gcc --version
avr-gcc (GCC) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
- Es gibt auch andere Installationsmöglichkeiten …
Arduino IDE einrichten
- erster Start
Die Original-Homepage http://www.digistump.com/ ist mittlerweile leider verschwunden. Das macht aber nichts, es gibt alles auf Github, und auch sonst sind genug Ressourcen zum Digispark im Internet verfĂĽgbar. Es muss ĂĽber Preferences die Board-Manager-URL eingestellt werden. Ausserdem empfiehlt es sich, bei compilation [x] show verbose Output anzuklicken, und [ ] check for updates on startup auszumachen
- Digistump board manager url
https://raw.githubusercontent.com/digistump/arduino-boards-index/refs/heads/master/package_digistump_index.json
Über den Board-Manager muss nun das Digistump-AVR-Board installiert werden. Das dauert ein wenig…
Danach muss das Board ausgewählt werden, hier Digispark Default 16.5 MHz
- erstes Mini-Test-Programm kann nun eingetippt, kompiliert und hochgeladen werden
- Dies ist das Programm zum Hex-File oben, das zum Micronucleus-Test verwendet wurde
// the setup routine
void setup() {
// initialize the digital pin as an output.
pinMode(0, OUTPUT); //LED on Model B
pinMode(1, OUTPUT); //LED on Model A
}
// the loop routine runs over and over again forever:
int i;
void loop() {
for(i=1; i<=300; i+=10) {
digitalWrite(0, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(1, HIGH);
delay(100+i); // wait
digitalWrite(0, LOW); // turn the LED off by making the voltage LOW
digitalWrite(1, LOW);
delay(100+i); // wait
}
}
- Achtung: Beim Uploaden aus der Arduino-IDE: Fehler bei micronucleus
...
Micronucleus failed:
/home/chrissie/.arduino15/packages/digistump/tools/micronucleus/2.0a4/launcher -cdigispark --timeout 60 -Uflash:w:/tmp/arduino_build_66147/simple-test.ino.hex:i
Running Digispark Uploader...
Plug in device now... (will timeout in 60 seconds)
micronucleus: library/micronucleus_lib.c:66: micronucleus_connect: Assertion `res >= 4' failed.
- Es muss der Aufruf von Micronucleus aus der IDE heraus verändert werden
- Dazu direct die Platform-Datei editieren, path und pattern so verändern
chrissie@fehmarn ~ $ vi .arduino15/packages/digistump/hardware/avr/1.6.7/platform.txt
#tools.micronucleus.cmd.path={runtime.ide.path}/hardware/digistump/avr/tools/avrdude
#tools.micronucleus.cmd.path.linux={runtime.ide.path}/hardware/digistump/avr/tools/avrdude
tools.micronucleus.cmd.path=/usr/local/bin/micronucleus
tools.micronucleus.upload.params.verbose=
tools.micronucleus.upload.params.quiet=
tools.micronucleus.upload.pattern="{cmd.path}" --run --timeout 60 "{build.path}/{build.project_name}.hex"
- Nun kann direkt aus der IDE kompiliert und hochgeladen werden
\o/
Programmieren direkt in C, ohne Arduino-Oberfläche und Bibliotheken
Das ist interessant, wenn man Speicher sparen will, Dinge tun will die man so in der IDE nicht kann oder ganz einfach IDEs generell hasst.
Einfaches Blink-Programm
- Es hat länger gedauert, bis ich herausgefunden habe, dass die Ports einen Offset von 0x20 haben
- Es steht jedoch im Attiny Datasheet auf Seite 20 ganz oben:
I/O Registers within the address range 0x00 - 0x1F are directly bit-accessible using the SBI and CBI instructions. In these registers, the value of single bits can be checked by using the SBIS and SBIC instructions. Refer to the instruction set section for more details. When using the I/O specific commands IN and OUT, the I/O addresses 0x00 - 0x3F must be used. When addressing I/O Registers as data space using LD and ST instructions, 0x20 must be added to these addresses.
- Dies wird sofort klar, wenn man sich die Data Memory Map des ATmega8 ansieht
- folgende beispielhafte Datei main.c erzeugen oder hier downloaden
//
// raw attiny 85 program by chrissie ^ x-tra-designs
// thanks to the internet for help
//
// #define DDRB (*(volatile unsigned char*)0x17)
// #define PORTB (*(volatile unsigned char*)0x18)
// In this case, ports have an offset of 0x20
#define DDRB (*(volatile unsigned char*)0x37)
#define PORTB (*(volatile unsigned char*)0x38)
// Digispark LED is on Pin 1 for newer versions, Pin 0 for old version
#define LED0 0
#define LED1 1
#define _NOP() do { __asm__ __volatile__ ( "nop "); } while (0)
void my_delay(volatile long time) {
while(time > 0) {
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
time--;
}
}
int main(void)
{
DDRB |= (1 << LED0); // Set pin to output
DDRB |= (1 << LED1); // Set pin to output
PORTB |= (1 << LED0); // Set pin to high
PORTB |= (1 << LED1); // Set pin to high
for (;;) {
PORTB ^= (1 << LED0); // cycle both pins
PORTB ^= (1 << LED1);
my_delay(25000);
}
return 0;
}
- Kompilieren des Programmes zu einem Standard a.out fĂĽr AVR-Controller
-
es werden hier bewusst keine weiteren Compiler-Optionen gesetzt, da es ein einfacher Test zum Verständnis sein soll
- Kompilieren, erzeugen von a.out
/opt/arduino-1.8.19/hardware/tools/avr/bin/avr-gcc -Os -mmcu=attiny85 main.c
- Anzeigen des im ATtiny verwendeten Speichers
/opt/arduino-1.8.19/hardware/tools/avr/bin/avr-size --format=avr --mcu=attiny85 a.out
AVR Memory Usage
----------------
Device: attiny85
Program: 214 bytes (2.6% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
- Umnwandeln von a.out zu einem .hex-File, dass in den ATtiny geladen werden kann
/opt/arduino-1.8.19/hardware/tools/avr/bin/avr-objcopy -O ihex -j .text -j .data a.out a.hex
- Laden des Hex-Files via Micronucleus
micronucleus --run a.hex
- Die LED am Digispark sollte nun (schnell) blinken
Abfrage und Schalten eines Port-Pins
//
// raw attiny 85 program 2 by chrissie ^ x-tra-designs
// thanks inernet for help
//
#define PINB (*(volatile unsigned char*)0x36)
#define DDRB (*(volatile unsigned char*)0x37)
#define PORTB (*(volatile unsigned char*)0x38)
// Digispark LED is on Pin 1
#define LED1 1
#define _NOP() do { __asm__ __volatile__ ( "nop "); } while (0)
void my_delay(volatile long time) {
while(time > 0) {
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
_NOP(); _NOP(); _NOP(); _NOP(); _NOP();
time--;
}
}
int main(void)
{
// keep pin0 to input
DDRB |= (1 << LED1); // Set pin1 to output
for (;;) {
if (!(PINB & 0x01)) // switch pulls pin to GND
PORTB |= (1 << LED1);
else
PORTB &= ~(1 << LED1);
my_delay(1000);
}
return 0;
}
- Downloaden Download main2.c
-
kompilieren, konvertieren und laden wie oben
- Aufbau mit Taster
- Wenn man den internen Pullup einschaltet, kann man den 10KOhm-Widerstand sparen.
- Demo-Video
Wie geht das alles unter Windows?
Unter Windows geht das ganz sicher auch alles. Die Arduino-IDE gibt es fĂĽr Windows. Bei Micronucleus im Git-Repository liegt ein Windows-Treiber bei. Der Rest sollte alles in WinAVR enthalten sein. Da ich kein Windows verwende, beschreibe ich das jedoch nicht.