|
Starten met de ATtiny2313
 Low-cost A/D conversie
op de ATtiny: zie de hardware tips pagina
C compiler tips, een real-time monitor, en I2C
master/slave libraries: zie de software
tips pagina
Probleempje: een I²C-chip (PCA9634) die ik graag als RGB
powerLED-controller wilde gebruiken (als uitbreiding voor mijn Rabbit, en om te spelen met I²C op mijn
omgebouwde NSLU2) is als hobbyist haast
niet betaalbaar verkrijgbaar, in ieder geval niet in een behuizing die
soldeerbaar is; pootjes minder als 1 mm apart ga ik niet zelf zitten
hobbyen... Wat te doen? Kan ik dit probleem op een andere manier
oplossen?
Lastige chips zijn wel te bestellen, maar wel met forse bestel- en
verzendkosten (20..30€) etc. Een mogelijke leverancier voor wat ik
zocht is DigiKey; die leveren ook
aan particulieren. Alleen, de behuizing die ik zocht was er niet, en
een TSSOP20-behuizing is mij te klein...
Als ik nu eens een goedkope microcontroller neem, en zelf de
functionaliteit daarin programmeer? Flexibel, ook voor andere zaken
inzetbaar, en effectief nog goedkoper ook. Zo gezegd, zo gedaan? Wel,
er komt natuurlijk wel een aantal extra stappen bij kijken:
- De chip moet goed verkrijgbaar (en betaalbaar) en hanteerbaar zijn
- De chip moet voldoende mogelijkheden hebben; hier I²C slave en
PWM (Pulse Width Modulation) uitgangen
- Je hebt een programmer nodig
- Je hebt ontwikkeltools nodig, liefst C/C++
Kant-en-klare bordjes met AVR processor? Kijk eens op de Arduino pages; is een uitgebreide
gebruikers-community bij. Leuk bordje is bijvoorbeeld de Arduino
Duemilanove (wel krachtiger dan de ATtiny).
Al met al is de keuze gevallen op de Atmel ATtiny2313. Een
goed verkrijgbare microcontroller met FLASH geheugen, in een eenvoudig
verwerkbare 20-pins DIL behuizing. Online gekocht, bij Conrad € 2.14 (#154166-89); voor iets
meer geld heb je bijvoorbeeld de ATmega ATMEG8535-16PU met 8-kanaals
A/D etc (#154257-89, maar was voor mij niet nodig; ooit in een ander
project?). Veel informatie op internet. Past zo op de standaard
gaatjesprint die ik gebruik voor prototypen. Een Flash-programmer voor
de seriële poort is zo gemaakt, en de tiny2313 is
'in-circuit'-programmeerbaar, dus je hoeft de chip niet eens uit je
schakeling te halen om de functionaliteit te veranderen.
De Atmel ATtiny2313
De ATtiny2313 is (als opvolger/vervanger van de AT90S2313) een prima
AVR microcontroller voor beginners. Een overzichtje van de
eigenschappen en functies van de ATtiny2313; zie ook de uitgebreide
documentatie in de datasheet
(PDF 2MB) :
- 8-bit AVR architectuur (1..2 cycles/instruction; Harvard memory
arch)
- 2kB flash programma geheugen, 10.000x schrijfbaar
- 128 bytes ram geheugen
- 128 bytes eeprom geheugen, 100.000x schrijfbaar
- Seriële poorten, timers, counters, etc
- 4 PWM kanalen (Puls Breedte Modultatie)
- I²C (TWI) slave en master mogelijkheid
- 20 pins, waarvan 18 als I/O te gebruiken
- maximaal 20 miljoen instructies per seconde bij een 20MHz klok
- interne oscillator, geen extern kristal noodzakelijk (maar kan
wel)
- Voeding 2.7 (1.8 voor V versie) tot 5.5V, dus werkt ook op twee
batterijen
De programmer
De programmer-componenten
1x Sub-D connector, 9-polig
3x weerstand 4K7
1x weerstand 10K
1x weerstand 33K
1x transistor BC549C
1x diode 1N4148
2x zener 5V1
1x 20-polig IC voetje
1x condensator 0.1 uF
1x condensator 33 uF/16V
1x 3-polige header
1x 2x5-polige header
gaatjesprint met eilandjes
Ik heb gekozen voor een low-cost programmer voor gebruik met een
seriële poort. Erg low-cost (denk minder dan € 10, en geen IC's nodig);
veiliger voor de computer dan de parallelle poort uitvoering, en zo in
elkaar te zetten met standaard verkrijgbare onderdelen; in een uurtje
had ik mijn programmer compleet.
Mijn versie is gebaseerd op het schema van de seriële programmer AVR
programmer Olimex AVR-PG1, en de vergelijkbare AVR programmer
van electronics-diy. Paar kleine modificaties, met name haal ik de
5 Volt uit de USB-poort van mijn laptop, dus een USB-kabeltje
gehalveerd, en hiervan de ground en +5V aangesloten op de 3-polige
header, zodat de tiny2313 voeding heeft en ook zonder seriële kabel
programma'tjes kan uitvoeren. En ik heb naast de 2x5-pinsISP
programming header een 20-polig IC-voetje geplaatst (Vcc op pin 20, GND
op pin 10, reset pin 1, etc), kan dus zowel losse 2313's als bordjes
met ISP (in-system programming) programmeren. Zie de foto hieronder,
met al een ATtiny in de 20-pins programming socket (opmerking: enkele
SMD-weerstanden zitten aan de onderkant).

Deze programmer is zowel compatible met de avrdude
software als met de PonyProg
software (zie bij 'De Tools'). De programmer is ook gelijk een
mini-applicatiebordje, in de zin dat programma's er ook gelijk kunnen
draaien; zie bijvoorbeeld 'Het eerste programma'tje' verderop.
De Tools
Ik wil de tools kunnen draaien op een laptop met Windows XP, of
Ubuntu Linux. Daar ik liever niet in assembler programmeer (weer een
andere assembly-taal) ga ik voor C: de GCC compiler suite is ook
verkrijgbaar voor de 2313. Minimaal is nodig de WinAVR omgeving, dit is
de GCC C/C++ compiler voor de AVR processoren, met alle
bijhorende tools. Een belangrijk onderdeel hiervan is de runtime
library AVR-libc, met uitgebreide
AVR-libc documentatie en voorbeelden
(ook over bijvoorbeeld interrupts, mixen met assembler code, etc).
De hele WinAVR GCC suite is command-line gebaseerd (dus zo'n
ouderwets DOS boxje), gebruik je liever een complete grafische IDE,
kijk dan naar de Atmel
AVR Studio 4. Dit programma is gratis te downloaden (eerst het
programma, en dan de twee service packs, en in de goede volgorde
installeren: programma, dan SP1, dan SP2). Werkt samen met de GCC
compiler, maar je kan ook in assembler werken.
Als je een programma gecompileerd hebt, moet je het ook in de 2313
zien te krijgen, oftewel je hebt een tool nodig om met de programmer te
kunnen praten. Het eenvoudigst qua omgeving is om hiervoor avrdude
te gebruiken; meegeleverd in WinAVR. Wil je echter dit niet vanaf de
command line hoeven te doen, dan kan je ook PonyProg gebruiken,
deze heeft een vriendelijker grafische gebruikersomgeving. Ik heb het
zelf overigens niet gebruikt, gebruik alleen avrdude.
Meer info over de C compiler: zie de software
tips pagina.
Het eerste programma'tje
De 'hello world' voor embedded systems is het laten
knipperen van een LEDje... Ik ben hiervoor uitgegaan van de
Nederlandstalige intro 'Knipperende LED',
waar op de site behoorlijk wat over de tiny2313 wordt uitgelegd. Zeker
lezen! Op de programmer twee extra onderdelen geplaatst: weerstand 470
Ohm plus een rode LED, en in serie aangesloten tussen Vcc en pin PD2
(pin 6 op het voetje): dus anders dan in de tutorial! Dit omdat
ik ook een extern kristal wil kunnen gebruiken: deze wordt op pin 4 en
5 aangesloten, waar in de tutorial de LED zit. Ook de source (bij mij knipper.c)
dus even hierop aanpassen...
Ik gebruik AVR Studio om te compileren; met 'F7'
vertaal je de hele boel. In de directory 'default' vind je
de gegenereerde files; de .hex file bevat de binary om in
de chip te branden. de .lss file bevat een uitgebreide
listing, inclusief startup code. AVR Studio doet een aantal
stappen; de meest belangrijke is het aanroepen van de compiler;
hieronder (verkort) weergegeven om te laten zien met welke opties
vertaald wordt:
avr-gcc -mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
knipper.c
De -Os optimaliseerd voor grootte. Let op: na dit
commando volgt er nog een aantal commando's om de uiteindelijke hex
file te maken; hier niet weergegeven (doet AVR Studio voor je,
maar wel van belang als je zelf een .bat of een makefile
wilt maken). Downloaden naar de chip gaat met avrdude en de
zojuist gemaakte seriële programmer:
avrdude -p t2313 -c siprog -P com1 -U flash:w:knipper.hex
En ja, het LEDje gaat na het downloaden vanzelf knipperen. Het hele
programma is 116 bytes (de grootte van de te downloaden binary, dus
inclusief libraries en opstartcode), niet slecht voor een heel C
programma!
Losgekoppeld van de computer, en op een regelbare voeding
aangesloten. Eens kijken hoe ver ik de voeding kan laten dalen... Zelfs
bij 1.33 Volt (de laagste stand die ik haal) blijft de uitgang keurig
op en neer gaan, al is door de te lage spanning de LED al niet meer
zichtbaar. Netjes, formeel is'ie maar vanaf 2.7 Volt gegarandeerd (en
de V-versie vanaf 1.8V). Houdt in dat'ie ook op twee oplaadbare
batterijen werkt, handig voor een volgens project dat ik in gedachten
heb (soort vuurvliegjes gebaseerd op de zonnecel van zo'n oude
LED-tuinlamp).
Fuse programming met AVRDUDE
Naast het programmageheugen heeft de tiny2313 nog meer
programmeerbare delen; met name de fuses voor het instellen van de
verschillende modes (zoals welke klok te gebruiken). Die fuses zijn
vaak wat raadselachtig (zo is 'programmed' een 0, en 'cleared' een 1),
maar gelukkig is er op het net wel wat uitleg verkrijgbaar, en is er
bijvoorbeeld de fuse
calculator, welke de fuse waardes netjes uitrekend aan de hand van
je keuzes. Als je de waardes berekend hebt kan je met avrdude
deze programmeren. Pas op; een verkeerde waarde kan je chip
onbruikbaar maken! Meer info ook op de
AVR Fuses HOWTO Guide (en natuurlijk in de datasheet).
Het is nuttig eerst eens de huidige waardes uit te lezen, met het
commando:
avrdude -p t2313 -c siprog -P com1 -U lfuse:r:-:h
-U hfuse:r:-:h -U efuse:r:-:h
Dit levert bij mij de waarden op (even zoeken in de output): low
fuse 0x64, high fuse 0xdf, extended fuse 0xff.
Dit zijn de standaard fabriekswaarden (interne RC oscilator, etc). Ik
wil de processor op het kristal laten lopen (extern kristal, 4 MHz,
geen deling door 8); dit levert een low fuse waarde op van 0xdf.
De high fuse en extended fuse kunnen ongewijzigd blijven! Commando:
avrdude -p t2313 -c siprog -P com1 -U lfuse:w:0xfd:m
En ja, programmer uitgebreid met een kristal en 2 22 pF
condensatoren, en mijn ledje knippert nu 4x sneller (in plaats van de 1
MHz interne RC-klok, de 4 MHz kristalwaarde). Zoals gezegd: een
verkeerde fuse waarde kan je chip onbruikbaar maken; altijd
dubbel-checken!!!
Interrupts
Altijd handig om een gevoel van tijd te hebben, dus een
interrupt-routine om ticks te tellen is plezierig. De timers lopen toch
al (vanwege de PWM), dus ik gebruik timer 0 om elke periode een
interrupt te genereren. Met een 4 MHz kristal; prescaler op 8, en 256
ticks voor een PWM-ronde kom ik zo op een PWM- en interrupt-frequentie
van haast 2 kHz (4MHz / 8 / 256). In de interrupt-routine gebruik ik
dit (om te testen) om een LEDje te laten knipperen; ziet er op de scope
goed uit. Timer 0 overflow interrupt (TOIE0) enablen, en
de globale enable flag aanzetten met de sei() functie:
#include <avr/interrupt.h>
volatile int pwm_counter;
ISR(TIMER0_OVF_vect) // Interrupt
service routine
{
pwm_counter++; //
16-bit counter @ ~2 kHz
PORTD ^= (1 << PD2); // toggle LED output at 1 kHz
}
...
TIMSK |= (1 << TOIE0); // enable timer0 overflow interrupt
sei();
// global enable interrupts
...
De timer interrupt wordt uiteindelijk gebruikt voor onder andere
het geleidelijk aan- en uit-zetten van de leds, en het bijhouden
van de real-time klok.
De I²C (of TWI)
Atmel noemt I²C "TWI", Two-Wire Interface, om trade-mark
issues te voorkomen. Ik had gehoopt code van het Arduino project te
kunnen gebruiken, maar helaas: hardware is anders. De ATtiny2313 heeft
een USI poort (Universal Serial Interface), die meerdere
standaarden — waaronder I²C — aankan. Toch was er ook voor de tiny op
internet wel wat te vinden; twee projecten vond ik met name van belang
(de Atmel eigen code uit de app.notes werkt volgens fora niet altijd
betrouwbaar, deze links hebben bijgewerkte versies):
- Deze I²C
dimmer applicatie, waar een circulaire buffer voor
communicatie gebruikt wordt: handig als je een message-based protocol
wilt. Overigens is deze app ook een slimme manier om een 8-kanaals PWM
te implementeren op de ATtiny.
- Deze I²C
eeprom simulatie, die zich gedraagt als een seriële
eeprom, dus meer een memory-mapped manier van communicatie
Ben met de eprom-simulatie aan de slag gegaan; was het eenvoudigst
hier een register-gebaseerde interface á la PCA9634 mee op te bouwen.
De code deed niet helemaal wat er gezegd werd, heb wat kleine
wijzigingen doorgevoerd, zoals de merge van de send- en receive-buffer
in een geheugenbuffer. De hele code is minder dan 500 bytes, dus ik heb
nog meer dan 3/4 over voor de eigenlijke applicatie. Alle
i2c-communicatie wordt in de interrupt afgehandeld; het main program is
een lege eindeloze loop.
Ook gezorgd dat de LED en een switch (met een weerstand van 1K, van
PD3/pin 7 naar aarde) ergens in het "eprom"-geheugengebied zijn
gemapped door in de eindeloze loop van het 'main'-programma deze
waarden heen en weer te kopiëren van de I/O naar de geheugenbuffer waar
de eeprom gesimuleerd wordt. Ja, ik kan nu (vanuit
de NSLU2) de LED aan en uitzetten, en de schakelaar uitlezen (via
de i2cset en i2cget commando's)! I²C
werkt. Ongeveer een week nadat ik de onderdelen van de programmer
binnenkreeg, toch netjes.
Ik ga overigens niet een 8-kanaals PCA9634 exact nabouwen (waarvoor
de dimmer-app een goed startpunt zou zijn); maar de extra intelligentie
van de tiny gebruiken voor een besturing op hoger niveau (commando's
als ga in zoveel seconden naar die helderheid); misschien dat dan een
message-based protocol als in de dimmer dan toch meer toepasselijk is.
Bovendien (in verband met de gevoeligheid van het menselijk oog) wil ik
meer een logarithmische curve, en daarvoor heb ik meer dan 8 (lineaire)
bits nodig, zit aan 12 te denken... Maar, dat wordt misschien nog wel
eens een andere pagina.
Een krachtiger LED
Bij Conrad enkele power LEDs
besteld, rood/groen/blauw, per kleur ongeveer 1 Watt. Deze LEDs
(181159-89; €14,14) mogen per stuk 350 mA hebben (mits goed
gekoeld, 188052-89), en dat is wat veel voor de ATtiny. Met enkele
low-cost HEXFETs IRL510 (162789-89; € 0,60) is het echter wel goed te
doen.
Een simpel schema'tje geeft ook een
stroombegrenzing, zodat ongeacht de voedingsspanning de stroom binnen
de veilige grenzen blijft: als de spanning over R2 te hoog gaat, gaat
T1 geleiden, en knijpt T2 dicht --> stroom wordt minder en de
spanning over R2 daalt, evenwicht bij ongeveer 0.63V. Let op, als de
FET in stroombegrenzingsmode werkt, valt er wel spanning over (gaat als
weerstand werken), en dissipeert hij dus ook vermogen: bescheiden
koelplaatje is nodig! Bij de gegeven waardes, en de blauwe LED (3.5V
spanning, x2) op 350 mA staat er 2.9V over R3, en dus 1.45V over de FET
--> 0.5W (en 1W over R3), bij de rode LED (2.5V, x2) meer: 3.45V
resp. 1.2W over de FET.
De ingang is compatible met de ATtiny op 5 Volt, en aangesloten op
de PWM-uitgangen op pin 14..16 (3 FETs in totaal, dus). Dit geeft een
lamp met behoorlijke lichtopbrengst, en instelbare kleur en helderheid.
Een eerste testprogramma'tje is gebaseerd op
een RGB-LED tutorial,
hierin wordt gedemonstreerd hoe je de pulsbreedte modulatie (PWM)
gebruikt. Er zijn voor mij enkele kleine aanpassingen nodig: de
driver-trap zoals geschreven gedraagt zich als een inverter, dus uit →
aan, en omgedraaid. De 2313 heeft in zijn configuratieregisters bits
om de uitgang om te draaien, daarmee gedraagt het programma zich zoals
gewenst.
En verder...
Ben nog met wat extra zaken bezig, zoals een low-cost AD
conversie op de ATtiny; zie meer op mijn ATtiny
Hardware Tips pagina... En tips over de software/debug kant op de software tips pagina.
Plus: Een ongesorteerde dump van mijn bookmarks over de AVR:
Algemeen:
Programmers:
Onderdelen nodig?
|