elemente practice in dezvoltarea sistemelor cu arduino uno-proiect 5
TRANSCRIPT
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
1/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
45
ProiectProiectProiectProiect 5555 –––– ButoaneButoaneButoaneButoane şşşşiiii sistemulsistemulsistemulsistemul dededede întreruperi întreruperi întreruperi întreruperi
Conținutul lucrării pe scurt:• Prezentarea modulului de interconectarea a unui buton la
placa Arduino Uno• Modalități de configurare a întreruperilor externe și a
întreruperilor asociate mecanismelor de tip timer• Exemplu de cronometru cu activare directă a sistemului de
întreruperi
Echipamente necesare lucrării:• Placă de dezvoltare Arduino Uno sau compatibilă• Cablu de conectare USB• 2 breadboard 30 pini sau 1 breadboard 60+ pini + fire de
interconectare• 3 butoane, 3 rezistoare 10kohm, 3 condesatoare 100nF• 2 shift-register TPIC6B595• 2 rezistoare 220ohm• Afișaj pe 7 segmente 2 caractere anod comun
Secțiuni lucrare:• Modalități de conectare a unui buton• Modalități de manipulare software a intrărilor digitale• Exemplu de manipulare software a intrărilor digitale• Exemplu de numărător pe două caractere• Exemplu de cronometru cu activare directă a
sistemului de întreruperi
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
2/15
Elemente practice de b
ModalitModalitModalitModalităţi deăţi deăţi deăţi de interconectareinterconectareinterconectareinterconectare
Butoanele și comutatoarele (de intrări pentru un sistem e
logic sau ”1” logic un pin de io comandă sau o condiție de
Imaginea de mai jos prezintăintrare a plăcii Arduino (Butope ”0” logic – la apăsarea un”0” logic.
Microcontrolerele Atmel AVRpull-up internă care poate fitrebui să fie configurat ca intrsă fie înscris 1). Din acest mla placa Arduino se poatrezistențe de pull-up externeurmătoare).
Atenție!!! Conectarea directăplăcii Arduino fără activareapull-up internă poate distrudatorită curentului tranzitoriu
închiderea contactului. Nu seastfel de schemă deoarece o
în timpul dezvoltării poathardware.
ză în dezvoltarea sistemelor cu microprocesoare in
46
a unui butona unui butona unui butona unui buton
utoane fără revenire) reprezintă cele maibedded. Astfel de dispozitive sunt capabil
ntrare de uz general semnalizând în acestintrare.
schema clasică de conectare a trei butoa1 – PIN2, Buton 2 – PIN3, Buton 3 – PI
ui buton starea pin-ului de intrare va trece
dispun de o rezistență derogramată software (pinulare și în registrul de ieșiretiv conectarea unui buton
face direct fără unei(imaginea de pe pagina
a unui buton la un pin alsoftware a rezistenței dege fizic pinul de intrarefoarte mare care apare larecomandă utilizarea uneisimplă omisiune software
conduce la distrugeri
egrate
imple exemplesă tragă în ”0”
mod sistemului
e la trei pini de4) cu comandădin ”1” logic în
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
3/15
Elemente practice de b
O altă problemă care apare îtip buton sau comutator esteimperfecțiunilor mecanice
închiderea sau la deschiderede oscila ie a semnaluluieronată a comenzii (citire msituație se utilizează un conpentru a netezi semnalul dcelălalt.
ză în dezvoltarea sistemelor cu microprocesoare in
47
cazul utilizării unei element defenomenul de bounce. Datorităale contactelor electrice laelementelor apare un fenomen
are poate conduce la citireaultiplă). Pentru a evita aceastădensator (schema de mai jos)
trecere dintr-un nivel logic în
egrate
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
4/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
48
ModaliModaliModaliModalităţi de manipulare software a intrărilortăţi de manipulare software a intrărilortăţi de manipulare software a intrărilortăţi de manipulare software a intrărilor
Mediul Arduino IDE pune la dispoziția programatorului funcția digitalRead(pin) care returnează starea pinului dorit. Pinul citit se poate configura în prealabil ca fiind de
intrare pinMode(pin, INPUT) dar având în vedere faptul că după reset toții piniimicrocontrolerului sunt configurați implicit ca intrări acest lucru nu este obligatoriu decât
în cazul în care pinul respectiv a fost configurat anterior ca ieșire.
Plecând de la schema din secțiunea anterioară (cu sau fără debouncing hardware – darcu rezistență externă de pull-up) se poate testa programul următorul program pentru oexemplificare a funcției digitalRead .
const int buton1 = 2;
const int buton2 = 3;
const int buton3 = 4;
int a1 = 0;
int a2 = 0;
int a3 = 0;
void setup() {
pinMode(buton1, INPUT);
pinMode(buton2, INPUT);
pinMode(buton3, INPUT);
Serial.begin(9600);
}
void loop(){
if (digitalRead(buton1) == LOW) {
a1++;
Serial.print("Butonul 1 s-a apasat butonul de ");
Serial.print(a1,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(200);}
if (digitalRead(buton2) == LOW) {
a2++;Serial.print("Butonul 2 s-a apasat butonul de ");
Serial.print(a2,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(200);}
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
5/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
49
if (digitalRead(buton3) == LOW) {
a3++;
Serial.print("Butonul 3 s-a apasat butonul de ");
Serial.print(a3,DEC);
Serial.print(" ori.");
Serial.println();//debouncing software
delay(200);
}
}
Se observă că citirea celor trei butoane presupune o buclă infinită care verifică continuustarea pinilor la care sunt conectate cele trei butoane și afișează pe serială numărul deapăsări al fiecărui buton în parte. Se mai observă că programul introduce și undebouncing software (o mică întârziere după declanșarea fiecărei apăsări de buton)
pentru a nu prinde evenimentul în mod eronat de mai multe ori. Se poate experimenta șiobserva efectul înlăturării debouncing-ului software
O altă modalitate de a prinde un eveniment de tip închidere circuit / apăsare buton sepoate face și prin utilizarea întreruperilor externe. Mediul Arduino IDE pune la dispozițiaprogramatorului funcția attachInterrupt(întrerupere, isr_asociat, mod) care permite manipularea celor două întreruperi externe INT0 și INT1 alemicrocontrolerului. Din păcate acestea sunt singurele întreruperi care sunt accesibileprin intermediul limbajului de bază al mediului Arduino IDE. Butoanele trebuie să fieconectate la pinii 2 (INT0) și 3 (INT1) ai plăcii Arduino. Parametrii funcției sunt:
întrerupere - 0 pentru INT0 și 1 pentru INT1, isr_asociat – numele unei proceduri caresă trateze apariția întreruperii și mod – specifică evenimentul extern la care să sedeclanșeze întreruperea LOW (pinul devine ”0” logic), FALLING (pinul trece din ”1” în”0”), RISING (pinul trece din ”0” în ”1”) sau CHANGE (orice tip de tranziție – la butonacest mod va conduce la declanșare dublă la fiecare apăsare). Funcția perechedetachInterrupt(întrerupere) permite dezactivarea întreruperii activate cuajutorul funcției precedente. Pentru testarea celor două funcții se poate rula programulurmător utilizând aceiași schemă electrică – efectul programului este identic cu celprecedent.
include
const int buton3 = 4;
volatile int a1 = 0;
volatile int a2 = 0;
int a3 = 0;
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
6/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
50
void setup() {
attachInterrupt(0,ISR_b1,FALLING);
attachInterrupt(1,ISR_b2,FALLING);
Serial.begin(9600);
}
void loop(){
if ((PIND & (1
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
7/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
51
• Citirea butonului 3 nu se mai face cu ajutorul funcției digitalRead descrisăanterior ci, direct, prin intermediul registrului intern PIND care stochează stareapinilor de intrare a portului D – pinul 4 al plăcii este conectat la pinul PD4 almicrocontrolerului (a se revedea lucrarea 3). Verificarea stării pinului 4 al plăciiconstă în verificarea stării bitului 4 din registrul PIND. Utilizarea alias-ului PINDnecesită includerea fișierului de definiții avr/io.h . Acest mecanism se află înspatele implementării funcției digitalRead specifică mediului Arduino IDE.
Exemplu de activare directă a întreruperilor externeExemplu de activare directă a întreruperilor externeExemplu de activare directă a întreruperilor externeExemplu de activare directă a întreruperilor externe
Placa de dezvoltare Arduino permite activarea tuturor pinilor I/O ca surse de întreruperiexterne. Este adevărat că spre deosebire de pinii 2 și 3 (INT0 și INT1) restul pinilor I/0
(PCINTx) nu pot configura întreruperi externe declanșate de prinderea unui evenimentextern de tip front crescător, front descrescător sau zero logic (RISING, FALLING,LOW) ci doar de modificarea nivelului logic (CHANGE). Pentru a configura întreruperileexterne asociate cu alți pini decât 2 sau 3 este nevoie să configurăm în mod directregistrele interne ale microcontrolerului. Programul următor reface comportamentulprogramelor anterioare fără a apela la funcția attachInterrupt. Se vor utiliza trei
întreruperi externe INT0 – pin 2 – buton 1, INT1 – pin 3 – buton 2, PCINT2 – pin4 =PCINT20 – buton 3.
#include
#include #include
volatile int a1 = 0;
volatile int a2 = 0;
volatile int a3 = 0;
void setup() {
sei();
EIMSK |= (1
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
8/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
52
Serial.print(a1,DEC);
Serial.print(" ori.");
Serial.println();
Serial.print("Butonul 2 s-a apasat de ");
Serial.print(a2,DEC);
Serial.print(" ori.");Serial.println();
Serial.print("Butonul 3 s-a apasat de ");
Serial.print(a3,DEC);
Serial.print(" ori.");
Serial.println();
delay(1000);
}
ISR(INT0_vect) {
a1++;
_delay_ms(400);}
ISR(INT1_vect) {
a2++;
_delay_ms(400);
}
ISR(PCINT2_vect) {
a3++;
_delay_ms(1000);
}
Programul include fișierele de definiții avr/interrupt.h [16] și avr/io.h pentru aputea utiliza denumirile registrelor și biților care sunt utilizați în configurarea sistemuluide întreruperi precum și a denumirii standard a subrutinelor de tratare a întreruperilor –ISR(INT_vect).
Pentru activarea sistemului de întreruperi (la nivel global) se utilizează instrucțiuneasei(); care echivalează cu setarea bitului I în registrului intern SREG.
Pentru activarea întreruperilor INT0 și INT1 se setează biții INT0 și INT1 din registrulintern EIMSK, de exemplu: EIMSK |= (1
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
9/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
53
de buton 3 va fi prinsă de două ori, lucru care poate fi evitat prin mărirea temporizării dedebounce software.
Funcțiile ISR pentru cele trei întreruperi trebuie declarate de forma ISR(INT_vect) unde INT_vect va fi INT0_vect, INT1_vect, PCINT2_vect. [17]
În cazul ISR-urilor reale (nu generate de mediul Arduino) sistemul de întreruperi estedezactivat pe durata execuției ISR-ului (pentru ca un ISR să nu întrerupă un alt ISR).Pentru a preveni blocarea programului (în ISR) nu trebuie folosite în cadrul unui ISRfuncțiile puse la dispoziție de mediul Arduino. De exemplu, utilizarea funcției delay încadrul unui ISR (pentru debouncing-ul software) va conduce la blocarea programuluideoarece această funcție utilizează întreruperea asociată timer-ului 0 – apelată într-uncontext de dezactivare a sistemului de întreruperi va introduce un delay infinit –
întreruperea asociată timer-ului 0 nu se va declanșa niciodată. Această funcție poate fi înlocuită cu macro-ul _delay_ms(nr_ms) prezent în biblioteca util/delay.h .
Exemplu de numărător pe două caractereExemplu de numărător pe două caractereExemplu de numărător pe două caractereExemplu de numărător pe două caractere
Având în vedere cunoștințele noi prezentate vom încerca să implementăm unnumărător simplu cu ajutorul unui afișaj de două caractere pe 7 segmente. După resetafișajul va arăta 00, la fiecare apăsare a butonului 1 numărul se va incrementa(incrementarea din 99 va duce în 00), la fiecare apăsare a butonului 2 numărul de peafișaj se va decrementa (decrementarea din 00 va duce în 99), butonul 3 va resetanumărul la 00 (nu vom fi deranjați de declanșarea dublă a evenimentului având învedere că este o operație de reset).
Schema electrică a numărătorului este prezentată în imaginea următoare. Se observăcă datorită utilizării a două registre de deplasare nu mai apare efectul de aprindereslabă a unor segmente în cazul afișării de cifre diferite pe cele două caractere – nu semai efectuează comanda prin intermediul aceluiași registru a celor două caractere.Comanda de aprindere a segmentelor este stabilă – fiecare caracter are propriulregistru.
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
10/15
Elemente practice de b ză în dezvoltarea sistemelor cu microprocesoare in
54
egrate
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
11/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
55
Pentru testarea montajului se utilizează următorul cod sursă:
#include
#include
#include
const int latchPin1 = 7;
const int clockPin1 = 8;
const int dataPin1 = 9;
const int latchPin2 = 10;
const int clockPin2 = 11;
const int dataPin2 = 12;
volatile int digit1 = 0;
volatile int digit2 = 0;
const int numbers[] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111};
void setup() {
//activare int0 si int1
EIMSK |= (1
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
12/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
56
ISR(INT0_vect) {
if (digit1==9) {
if (digit2==9) {
digit1=0;
digit2=0;
}else {
digit1=0;
digit2++;
}
}
else digit1++;
_delay_ms(400);
}
ISR(INT1_vect) {
if (digit1==0) {if (digit2==0) {
digit1=9;
digit2=9;
}
else {
digit1=9;
digit2--;
}
}
else digit1--;
_delay_ms(400);}
ISR(PCINT2_vect) {
digit1 = 0;
digit2 = 0;
_delay_ms(400);
}
Exemplu de cronometru cu activare directă a sistemului de întreruperiExemplu de cronometru cu activare directă a sistemului de întreruperiExemplu de cronometru cu activare directă a sistemului de întreruperiExemplu de cronometru cu activare directă a sistemului de întreruperi
La fel cum se pot activa întreruperile externe ale plăcii Arduino se pot utiliza șimecanismele de tip timer care au fost utilizate în cadrul lucrării anterioare prinintermediul unei biblioteci specializată – prin accesarea directă a registrelor interne deconfigurare a microcontroler-ului. Pentru a exemplifica acest lucru vom reface exemplucu cronometru din lucrarea precedentă utilizând schema de interconectare prezentatăanterior – pentru măsurarea independentă a duratei de o secundă nu vom utiliza
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
13/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
57
funcțiile bibliotecii TimerOne ci rutinele implicite asociate timer-ului intern 1.Funcționarea cronometrului va fi următoarea: numărătoarea se va face în zecimal (00-99), butonul 1 va porni cronometrul, butonul 2 va opri numărătoarea fără a ștergerezultatul astfel încât numărătoarea să poată fi reluată, butonul 3 va reseta numărul desecunde la 00 indiferent de modul de funcționare (oprit / pornit). Evenimentele asociatecelor trei butoane vor fi prinse similar ca și în cazul numărătorului (folosind întreruperi).Programul ce trebuie încărcat este următorul:
#include
#include
#include
const int latchPin1 = 7;
const int clockPin1 = 8;
const int dataPin1 = 9;
const int latchPin2 = 10;const int clockPin2 = 11;
const int dataPin2 = 12;
volatile int digit1 = 0;
volatile int digit2 = 0;
const int numbers[] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111};
void setup() {
// activare intrerupere Timer1 overflow
TIMSK1 = (1
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
14/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
58
void loop(){
digitalWrite(latchPin1, LOW);
shiftOut(dataPin1, clockPin1, MSBFIRST, numbers[digit1]);
digitalWrite(latchPin1, HIGH);
digitalWrite(latchPin2, LOW);shiftOut(dataPin2, clockPin2, MSBFIRST, numbers[digit2]);
digitalWrite(latchPin2, HIGH);
delay(1000); }
ISR(TIMER1_OVF_vect) {
if (digit1==9) {
if (digit2==9) {
digit1=0;
digit2=0;
}
else {digit1=0;
digit2++;
}
}
else digit1++;
}
ISR(INT0_vect) {
_delay_ms(400);
//pornire timer FCPU/256
TCCR1B |= (1
-
8/9/2019 Elemente Practice in Dezvoltarea Sistemelor Cu Arduino UNO-Proiect 5
15/15
Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate
59
= 0. Parametrul INT_vect în funcția ISR pentru timer-ul 1 este TIMER1_OVF_vect.[18]
Pentru ca timer-ul 1 să facă overflow la fiecare secundă trebuie calculat factorul descalare (divizare) în funcție de frecvența de ceas a microcontrolerului. La o frecvență de
16MHz (cum este în cazul plăcii Arduino) se poate folosi un factor de scalare de 256care va produce overflow la fiecare 1.048576 secunde.
Timp_overflow = Incrementări * (Frecv_CPU/factor_scalare)-1 = 65536 / (16000000 /256)