Arduino Projekten

Tue 20-Aug-19
01:35:55




Interupt en 8 Led's

Datum: Sat 08 March 2014
Samenvatting: Met een interupt gaan 8 Led's 1 voor 1 aan.


Om kennis te maken met Interupts is het een goede manier om eenvoudig te beginnen. Doel, de 8 Led's, die (via de decoder 74htc138) op de analoge pinnen A0 .. A2 zijn aangesloten moeten 1 voor 1 aan gaan met een eenvoudig (software) tellertje [RowCount]. Dit is hetzelfde idee als het aflopen van de rijen op de RGB-Panelen, er is weinig ballast en dus eenvoudiger te begrijpen.

De voorbeelden maken gebruik van het knipper-Led voorbeeld van de Arduino [IRC-01], of te wel: Interupt - Led aan - Interupt - Led uit. Dit werkt leuk bij de voorbeeld knipperfrequenties van 1Hz of 2Hz. Bij hogere frequenties (hoger dan 100Hz) is de Led gewoon aan. Het is dan niet te zien wanneer deze uit is. Het PWM-principe op 50%.

Bij mijn 8 Led's via de decoder (74hct138) weet ik zeker dat er altijd maar 1 Led aan is. Daar zorgt de decoder immers voor. Branden er meer Led's (zie foto), dan weet ik zeker dat de ingangen van de decoder aktief "knipperen". Immers bij LAAG is de éne Led aan, bij HOOG is de andere Led aan. Bij het optellen(via [RowCount]) van de 3 bits op de ingang van de decoder, zullen alle 8 Led's branden. Hoe sneller de 3 bits optellen, hoe sneller de 8 Led's zullen afwisselen met branden, tot ze allemaal "tegelijk" aan lijken te zijn.

Allereerst moet er een berg documentatie worden doorgespit. Naast de datasheet, zijn er diverse tutorials gevonden:

  • De datasheet van de fabrikant van de Arduino micro-controler - Link (35MB-pdf).
  • Theorieën over Interupts (hoe lang duurt het/ watchdogs/ volatile) - Link.
  • Algemene uitleg over timers voor fequentie-tellers en tijdmetingen, maar zonder interupts - Link.
  • Hoe zijn de interupt-frequenties te berekenen - Link.
  • En uiteindelijk iets wat past voor de RGB-Paneel interupt, nauwkeurige uitleg over gebruik van de registers met figuren - Link. Een timer die optelt of aftelt maar wel snel interupts kan geven en uitleg hierover.

De Timers

In het kort, de Arduino Uno heeft 3 timers:

  • Timer 0 wordt onder ander gebruikt door funkties als [delay();] en [millis();]. Deze timer is 8 bits en telt dus vanaf 0 t/m 255. Gebruik van deze timer wordt in de diverse voorbeelden sterk afgeraden, tenzij men goed weet wat men doet.
  • Timer 2 wordt onder ander gebruikt door funktie [tone();]. Ook deze timer is 8 bits en telt dus vanaf 0 t/m 255.
  • Timer 1 wordt gebruikt door funkties voor servo-motoren. Deze timer is 16 bits en telt dus vanaf 0 t/m 65535. Deze timer wordt in veel voorbeelden gebruikt. <= Deze gaat er gebruikt worden.

Alle Arduino timers zijn veelzijdig, erg veelzijdig. Zo kunnen zij:

  • optellen/ aftellen.
  • interupts genereren bij hun Topwaarde (255/ 65535)/ Bodemwaarde (0)/ vooraf ingestelde waarde.
  • nog veel meer verschillende functies uitvoeren, te uitgebreid om hier even op te sommen.

Hierdoor bestaan er veel afkortingen die verwarring brengen voor onervaren gebruikers (zoals ik nu nog ben, qua deze timers ). Zo zijn de volgende afkortingen (met hun uitleg) uit het uitgebreide datasheet van de micro-controler te halen. Afkortingen, die ook veel gebruikt worden in de voorbeelden op internet.

  • TCCR1A = Timer Counter Control Registers 1A
  • TCCR1B = Timer Counter Control Registers 1B
  • OCR1A = Output Compare Register 1A
  • CTC = Clear Timer on Compare
  • WGM12 = Waveform Generation Mode timer 1 bit 2
  • CS12 CS11 CS10 = Clock Select (timer) 1 bit 2..0
  • TIMSK1 = Timer Interupt MaSK 1
  • OCIE1A = Output Compare match Interrupt Enable 1A

Dit, gecombineerd met zoeken naar voorbeelden, maakt dat er iets te programmeren is om mee te experimenteren.

C++ regels herschrijven.

Veel voorbeelden gebruiken de volgende constructies om registers in te stellen en te programmeren.

TCCR1B |= (1 << CS10); // Set CS10 bit so timer runs at clock speed
Counter += 1; // Increase Counter

Vanwege mijn Pascal en assembly ervaring herschrijf ik zulke regels liever tot:

TCCR1B = TCCR1B | B00000001; // Set the Prescaler (CS12 CS11 CS10 = bit 2..0 - Clock Select)
Counter = Counter + 1; // Increase Counter

Het is niet zo flexibel dat het op meerdere platforms gaat lopen, maar maakt het voor mij (in deze fase) wel makkelijker leesbaar. Ik wil gewoon vanuit de praktijk weten hoe het in elkaar steekt.

Interupt van de Timer

In dit projekt wordt bij een interupt de volgende functie aangeroepen. Dit komt uit de standaard Arduino Libraries en wordt ook zo gebruikt in de vele voorbeelden.

ISR(TIMER1_OVF_vect)

Experimenten tonen aan dat het argument voor de functie, [TIMER1_OVF_vect], anders is bij de diverse soorten interupts die kunnen worden gegenereerd. Dit argument kan namelijk ook zijn: [TIMER1_COMPA_vect] en dit verschil is een bron van verwarring. Bijvoorbeeld of de interupt-functie [ISC()] wel (goed) aangeroepen wordt.

En uiteindelijk ...

Het resultaat van dit kleine projekt kan ik nu gaan combineren met het grote RGB-Paneel projekt.


Broncode: [1: Interupt & 8 Led's]

1: De broncode van Interupt & 8 Led's

(Sat 08 March 2014) In dit voorbeeld worden de poorten opzettelijk direkt aangesproken, want dit gaat ook bij het RGB-Paneel gebeuren.

Deze broncode heeft 42 regels met programma-code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//     ---------------------------------------------------------
//     |  Experimentation Kit for Arduino Example Code         |
//     |  Interupt : 8 Led's & Timer Interupt                  |
//     ---------------------------------------------------------

void setup()
{ // Set some pins To Output
  DDRC = DDRC | B00000111;    // pinMode(a  , OUTPUT); pinMode(b  , OUTPUT); pinMode(c  , OUTPUT);
  InitTimer();
}

void loop()
{
}

//==========================================================================================
//==                                                                                      ==
//==========================================================================================

volatile byte RowCount = 0;

void InitTimer()
{ // Initialize Timer1
  cli();                        // Disable Interrupts
  // Timer Counter Control Registers 1A & 1B
  TCCR1A = 0;                   // Make all bits of this register to 0
  TCCR1B = 0;                   // Make all bits of this register to 0

  OCR1A = 65535;                // set Output Compare Register 1 to the desired timer count
  TCCR1B = TCCR1B | B00001000;  // turn on CTC mode (WGM12 = bit 3 - Waveform Generation Mode)
  TCCR1B = TCCR1B | B00000010;  // Set the Prescaler (CS12 CS11 CS10 = bit 2..0 - Clock Select)

  TIMSK1 = TIMSK1 | B00000010;  // set Timer Interupt MaSK 1 to compare interrupt
                                // (OCIE1A = bit 1 - Output Compare match Interrupt Enable 1A)
  sei();                        // Enable Interrupts
}

ISR(TIMER1_COMPA_vect)
// De Interrupt Service Routine
{ // Select the Row.
  PORTC = ( PORTC & B11111000 ) | RowCount;  // Set the pin-nr's to the RowCounter
  RowCount = (RowCount + 1) & 7;


Broncode: [1: Interupt & 8 Led's] 

Afbeeldingen

int8led_1.jpg
1/1: int8led_1.jpg.

De aansluitingen van Interupt & 8 Led's

8 Led's via de decoder (74hct138)

Arduino Uno

Pwr USB ?
 
?
aref
gnd Gnd's
? d13
ioreff d12
reset d11
+3.3v d10
+5v d9
Gnd's gnd d8
Gnd's gnd
Vin d7
d6
Grote Led + A (A0) a0 d5
B (A1) a1 d4
C (A2) a2 d3
a3 d2
a4 d1
a5 d0