Programmeren van de ATtiny, met voorbeelden

De ATtiny chip kun je programmeren met de Arduino Uno. Met de nieuwste versie van de Arduino IDE is het vrij eenvoudig. Je kunt de ATtiny ook programmeren met een programmer, maar gebruik van de Arduino Uno heeft één groot voordeel: je kunt om de ATtiny een schakeling bouwen, zodat testen en programmeren samen gaan. Hierbij hoef je de draadjes naar de Uno maar zelden los te halen (zie verderop bij de stoplicht sketch).

Naamgeving

Bij de Attiny serie staat het eerste cijfer altijd voor de hoeveelheid flashgeheugen in kByte. De ATtiny85 heeft dus 8 kByte flash geheugen. Helaas is er weinig logica te ontdekken in de overige cijfers van deze reeks. Naast flashgeheugen hebben deze chips soms ook een geringe hoeveelheid SRAM en EEPROM geheugen. Hieronder staat hoe je de diverse ATtiny's moet aansluiten:

ATtiny's met 8 pootjes

Sluit deze ATtiny's als volgt aan op de Arduino:

ATtiny's met 14 pootjes (ATtiny44 en ATTiny84)

Sluit deze ATtiny's als volgt aan op de Arduino:

ATtiny's met 20 pootjes (ATtiny2313 en ATtiny4313)

Sluit deze ATtiny's als volgt aan op de Arduino: Om je de Arduino Uno voor dit doel te kunnen gebruiken moet je eenmalig het programma ArduinoISP uploaden. Je vindt dit programma in de IDE onder menu Bestand > Voorbeelden.

Daarnaast moet je de Arduino IDE klaar maken voor gebruik. Hiertoe moet je een link aangeven naar de betreffende "board manager". Ga hiertoe via menu Bestand naar Voorkeuren en voeg de link toe aan het veld "Meer Boards Managers". Als je meerdere links hebt, scheid deze dan met een komma.
Voor bijna alle andere types, waaronder de ATtiny13:
https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json
Alleen voor de ATtiny 25, 45, 85, 24, 44, 54:
https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json
Dit zijn twee geheel verschillende board managers. De laatste heeft minder keuzemogelijkheden en is daardoor voor beginners makkelijker te gebruiken.
Voor de ATtiny2313 (en vele andere ATtiny's):
http://drazzy.com/package_drazzy.com_index.json
Ga vervolgens via menu Hulpmiddelen via Board naar Board Beheer. Als het goed is zijn er bruikbare borden voor jouw ATtiny en kun je deze installeren. Je kunt deze borden nu kiezen in de lijst met Arduino's. Voor de ATtiny 2313 kies je "AtTinyCore by Spence Konde".

Voordat je gaat uploaden moet je onder menu Voorkeuren bij Programmer kiezen voor "Arduino as ISP".

Installeer een bootloader (laatste optie onder menu Hulpmiddelen. De booloader zorgt ervoor dat de ATtiny in een bepaalde configuratie wordt opgestart. Als je dit niet doet dan kan het zijn dat alles goed lijkt te gaan, maar dat later blijkt dat bijvoorbeeld het delay tien keer te lang duurt. Als je de instellingen van de ATtiny verandert dan moet je de bootloader eveneens opnieuw branden.

Nu kun je jouw programma's uploaden.

Op internet zie je soms dat je eerst een "bare minimum" moet uploaden (dat is een programma met niets erin (dus een lege setup en een lege loop functie). Als je problemen hebt kun je dat nog proberen, maar dit lijkt niet (meer) nodig te zijn.
Bij mij werkte dit allemaal prima, maar als dat bij jou niet zo is dan kun je op internet nog tips vinden, zoals het aanbrengen van een condensator e.d.

Pin layout (ook wel "pinout" genoemd)

Je moet de nummers van de pootjes van de ATtiny niet verwarren met de pinnummers, zoals je die in je Arduino programma moet gebruiken. Op internet vind je heel gemakkelijk de uitgebreide pinout van jouw ATtiny. Hierbij zie je bij elke pootje meerdere nummers en codes staan. Het pinnummer hangt immers af van de functie die je aan de pin geeft. Zo is bij de ATtiny13 pootje 3 digitale pin 4, maar analoge pin 2. Dus goed kijken naar zo'n pinout dan gaat het vanzelf goed!

ATtiny met 8 pootjes

Over pootje 1

In de pinouts krijg je de indruk dat pootje 1 van deze ATtiny's gebruikt kan worden voor o.a. digitale in- en uitvoer. Maar dat is alleen zo als je een wijziging aanbrengt in de ATtiny instellingen en bovendien kan die pin dan minder stroom leveren dan de andere pinnen. Dat veranderen van de instellingen moet met een hoge-spanning programmer (12 V) gebeuren. Als je vervolgens een wijziging wil aanbrengen in de sketch dan moet je de ATtiny weer terugzetten met een hoge-spanning programmer. Dit is voor de meeste mensen erg lastig en daarom ga ik er verder van uit dat we deze pin niet zullen benutten voor digitale input of output. Dat houdt wel in dat ik het programma voor twee stoplichten die samen een kruispunt veilig houden niet op de ATtiny met 6 poten kan realiseren. Met ATtiny's met meer pootjes lukt het wel. Zie verderop bij de ATTiny84.
Pootje 1 gebruiken voor een schakelaar
Pootje 1 is wèl voor analogRead() te gebruiken mits de spanning lager is dan ca. 2 volt. Daarmee kun je hem onder andere gebruiken voor een schakelaar. Je moet de schakelaar dan laten schakelen tussen bijvoorbeeld 2,5 volt en 5 volt. Met twee vrij hoge weerstanden lukt dat erg goed (zie de afbeelding hiernaast). Tijdens het uploaden moet je de schakelaar (gele draad) loskoppelen van de chip.
Uitleg: de schakelaar staat normaal open en dus krijgt pootje 1 de afgedeelde spanning van 0,5 VCC (2,5 V). AnaloogRead() geeft dan ongeveer 500. Zodra de schakelaar wordt ingedrukt, sluit deze de tweede weerstand kort, zodat op pootje 1 de volledige VCC komt te staan. AnalogRead() geeft dan ongeveer 1000. Leg de dempel in je programma dus op 750. Ik heb in het voorbeeld voor twee 47 kΩ weerstanden gekozen, maar een stuk hoger mag ook. Lager kan ook wel, maar als je ze te laag kiest dan verspil je onnodig energie. Als je in plaats van een schakelaar die normaal open is, een schakelaar die normaal dicht is hebt, dan verandert de schakeling niet, maar je Arduino code wel (> wordt <, of omgekeerd):
while (AnalogRead(0) < 750); // Wacht tot de knop wordt ingedrukt
Hieronder volgen twee voorbeelden van goed werkende programma's.

Stoplicht voorbeeld

Gelijktijdig testen en programmeren gaat prima
Zelfs de ATtiny13 is krachtig genoeg om een stoplicht te maken. Sluit een rode, oranje of gele en een groene led met hun lange pootje aan op de pootje 6, 5 en 3 van de ATtiny en het andere pootje via een weerstand van ca. 220 Ω naar GND. Upload onderstaand programma. Je kunt gemakkelijk de delays aanpassen aan je wensen. Ik heb bij elke kleur een led aangesloten, maar als je meerdere stoplichten tegelijk wil laten werken dan kun je gewoon een aantal leds parallel schakelen, dan kan de ATtiny makkelijk aan.
#define rood 1 // ATtiny13A/45/85 pin 6 
#define oranje 0 // ATtiny13A/45/85 pin 5 
#define groen 4 // ATtiny13A/45/85 pin 3 
#define roodAan digitalWrite(rood, HIGH); delay(7000);
#define oranjeAan digitalWrite(oranje, HIGH); delay(3000);
#define groenAan digitalWrite(groen, HIGH); delay(5000);

void setup() {
  pinMode(rood, OUTPUT);
  pinMode(oranje, OUTPUT);
  pinMode(groen, OUTPUT);
  roodAan;
}

void loop() {
  digitalWrite(rood, LOW); // Zet vorige kleur uit
  groenAan;
  digitalWrite(groen, LOW);
  oranjeAan;
  digitalWrite(oranje, LOW);
  roodAan;
}

Dobbelsteen voorbeeld
Getest met de ATtiny45 en de ATtiny85

Dit dobbelsteen programma is te groot voor de ATtiny13. Het kan wel aangepast worden, maar dan moet je de ATtiny direct programmeren, hetgeen buiten het kader van deze pagina's valt. Vanaf de ATtiny25 zou het wel moeten lukken.
Voor een eenvoudige dobbelsteen heb je 4 digitale pinnen nodig voor de ogen en één voor de schakelaar. Als je ook nog geluid wil hebben als de dobbelsteen "rolt" zou je pootje 1 kunnen gebruiken voor de schakelaar en pootje 3 voor het geluid. Ik wilde het programma zo simpel mogelijk houden, dus geen geluid. Deze dobbelsteen werkt zeer goed met een drukknop. Als je een trilschakelaar hebt dan kun je de dobbelsteen laten "rollen" zodra je deze schudt. Dat voelt natuurlijker dan de drukknop.
Er zijn speciale trilschakelaars ("vibration sensor" of "shake switches") met een dunne en een dikke draad. Deze kun je schakelen als een gewone drukschakelaar. Je kunt hiervoor ook een tiltschakelaar gebruiken. Het type SW-520D is zeer goedkoop en werkt erg goed. Als je deze rechtop monteert dan is hij normaal dicht en bij beweging open. Je moet dan dus een paar keer in het programma een keer HIGH vervangen door LOW. Als je de schakelaar op zijn kop monteert dan is dat niet nodig.
Zodra je de dobbelsteen aanzet lichten ter controle alle zeven ledjes op. Als je de schakelaar indrukt (of de dobbelsteen schudt) dan zal de dobbelsteen "rollen" door tien keer een waarde te laten zien van 1 tot 6. Je kunt dat zelf mooier maken door bijvoorbeeld de delaytime geleidelijk iets langer te maken en misschien een willekeurige volgorde te nemen.
/*
  Dobbelsteen met ATtiny 25 of hoger
  Arduino pin 0, 1, 2, 3, 4 = ATtiny pootje 5, 6, 7, 2, 3
  Sluit als volgt aan:
  pootje 5: middelste oog
  pootje 6: twee ogen diagonaal rechts
  pootje 7: twee ogen diagonaal links
  pootje 2: middelste ogen van de rij ogen aan beide zijkanten
  pootje 3: drukknop of iets dergelijks
  Je kunt alle leds via een weerstand aansluiten, of de gecombineerde leds op één weerstand met de halve waarde
  Omdat je in de leds kijkt mag je deze weerstanden wat groter kiezen dan normaal
  Bijvoorbeeld voor het middelste oog 440 Ohm en voor de gecombineerde ogen 220 Ohm
*/
#define knop 4
void setup() {
  for (byte i = 0; i < 4; i++) pinMode(i, OUTPUT);
  pinMode(knop, INPUT); 
  for (byte i = 0; i < 5; i++) aan(i);
  while (digitalRead(knop) == HIGH);
  randomSeed(millis());
}

void loop() {
  while (digitalRead(knop) == HIGH); // LOW bij breek of tril-schakelaar 
  byte r = random(1, 7); // Kies 1, 2, 3, 4, 5 of 6
  for (byte i = 0; i < 4; i++) digitalWrite(i, LOW); // Zet alle ogen uit
  for (byte i = 0; i < 10; i++) { // Laat ogen "rondgaan"
    rol(1 + i % 6); delay(300);
    for (byte j = 0; j < 4; j++) digitalWrite(j, LOW);
  }
  rol(r);
  delay(500);
}
void aan(byte i) {
  digitalWrite(i, HIGH);
}

void rol(byte i) {
  switch (i) {
    case 1: aan(0); break;
    case 2: aan(1); break;
    case 3: aan(0); aan(1); break;
    case 4: aan(1); aan(2); break;
    case 5: aan(0); aan(1); aan(2); break;
    case 6: aan(1); aan(2); aan(3); break;
  }
}

ATtiny84

Twee gekoppelde stoplichten

Hier laat ik zien dat je met deze ATtiny een eenvoudige verkeerslicht installatie kunt maken.
Uitleg bij het programma
In onderstaande sketch staat eerst zes keer een #define. Daarmee krijgen de pootjes een makkelijk te onthouden naam. De volgende zes #defines zetten een licht aan en soms een delay. Zo staan de delays dicht bij elkaar en kun je ze makkelijk aanpassen aan jouw eisen.
Voor wie hier niet zo goed bekend mee is: bij het compileren wordt het woord dat direct achter #define staat overal in het programma vervangen van wat er achter dat woord staat (inclusief eventuele puntkomma's, maar exclusief commentaar). Zo kun je een programma kort houden en leesbaarder maken. Een voorbeeld: #define Rood 1 betekent dus dat overal in het programma het woord Rood vervangen wordt door 1.
Ik gebruik de pootjes 3 t/m 8, zodat de twee stoplichten symmetrisch op de chip worden aangesloten. Deze keuze heeft als bijkomend voordeel dat alle pootjes in één lus op OUTPUT gezet kunnen worden.
Schema
Hoe je de ledjes aansluit kun je zien in de sketch en in het schema hiernaast. Vergeet niet bij elke led een weerstand aan te sluiten. Kies de weerstand zo dat alle ledjes ongeveer even helder zijn en dat ze genoeg licht geven. Meestal zal de waarde boven de 100 Ω liggen. Voor een "echte" toepassing in een modelbaan zul je beide lichten dubbel willen uitvoeren. Je kunt per pootje twee normale ledjes aansluiten zonder dat de ATtiny kapot gaat.
#define rood_1   3 // ATTiny84 pootje 10 ATTiny2313  5
#define oranje_1 4 // ATTiny84 pootje 9  ATTiny2313  6
#define groen_1  5 // ATTiny84 pootje 8  ATTiny2313  7
#define rood_2   8 // ATTiny84 pootje 7  ATTiny2313  11
#define oranje_2 7 // ATTiny84 pootje 6  ATTiny2313  8
#define groen_2  6 // ATTiny84 pootje 7  ATTiny2313  9
#define rood_1Aan   digitalWrite(rood_1, HIGH);
#define oranje_1Aan digitalWrite(oranje_1, HIGH); delay(2000);
#define groen_1Aan  digitalWrite(groen_1, HIGH);  delay(5000);
#define rood_2Aan   digitalWrite(rood_2, HIGH);
#define oranje_2Aan digitalWrite(oranje_2, HIGH); delay(2000);
#define groen_2Aan  digitalWrite(groen_2, HIGH);  delay(5000);

void setup() {
  for (byte kleur = rood_1; kleur <= rood_2; kleur++) pinMode(kleur, OUTPUT);
  rood_2Aan;
}

void loop() {
  digitalWrite(rood_1, LOW);
  groen_1Aan;
  digitalWrite(groen_1, LOW);
  oranje_1Aan;
  digitalWrite(oranje_1, LOW);
  rood_1Aan;  // Hierna mag het andere licht op groen springen
  delay(500); // Veiligheidsmarge voor randje-rood rijders
  digitalWrite(rood_2, LOW);
  groen_2Aan;
  digitalWrite(groen_2, LOW);
  oranje_2Aan;
  digitalWrite(oranje_2, LOW);
  rood_2Aan;  // blijft aan tot andere licht op rood springt
  delay(500); // Veiligheidsmarge voor randje-rood rijders
}

De ATtiny2313

Deze chip heeft meer pootjes dan de ATtiny en dat geeft dus meer mogelijkheden voor invoer en uitvoer. Verder zijn de specificaties erg vergelijkaar met die van de ATtiny84. Het twee-stoplichten programma werkt zonder veranderingen ook met deze chip, maar je moet de draden naar de lampjes dan wel iets anders aansluiten (zie de listing bij de ATTiny85 hierboven). De overgebleven pootjes zou je kunnen gebruiken voor bijvoorbeeld een gekoppeld voetgangerslicht.