Скочи на садржај

Матурски задатак 4ЕТР-Б6 – Лед расвета

Тема задатка је реализација новогодишње ЛЕД расвете која ће имати одређене светлосне ефекте (у овом случају треперење ЛЕД диода) док је кориснику омогућено да помоћу два тастера управља интензитетом осветљености у распону од 0 до 100%. Овде ћете пронаћи детаљно упутство и објашњење рада програма. Почео сам са 6. задатком из збирке, а ускоро ће бити још сличних текстова. Досадашња пракса је била да направим видео клип и објасним задатак кроз текст на блогу, а сада ће бити доступан документ за преузимање.

Потребно је уочити да се у задатку захтева да се ефекат треперења несметано одвија, независно од тога да ли је неки од тастера притиснут или не. Ово постижемо коришћењем прекида у раду са тастерима. Укратко, прекиди (енг. Interrupts) су механизам ослушкивања на очекиване догађаје. Онога тренутка када се деси догађај (деси се прекид) прекида се извршење главног програма и за тренутак се извршава рутина, односно функција прекида. Након извршене функције прекида, извршавање главног програма се наставља од оне линије кода где се догодио прекид. Интензитет осветљења диода се мења у функцијама прекида, док се у главном програму реализује ефекат треперења диода.

Електрична шема и шема повезивања кола


Потребне компоненте за реализацију склопа

  • Ардуино УНО
  • Протоплоча
  • ЛЕД диода – 3 ком.
  • Отпорник 220Ω – 3 ком.
  • Тастер – 2 ком.
  • Отпорник 1kΩ – 2 ком.

О раду са прекидима

Како би се омогућило да диоде несметано трепере (ипак се говори о новогодишњој расвети) неопходно је користити механизам „ослушкивања“ догађаја који се очекују. Догађај о којем се говори је притисак на тастере „Умањи“ или „Увећај“. Механизам који то омогућује се назива прекид (енг. Interrupt).

Суштина прекида је да се током „ослушкивања“ догађаја програм непрекидно извршава. Када се у току извршавања кода притисне неки од тастера долази до прекида у извршавању кода у одељку петље и извршава се потпрограм/функција која је везана за одређени прекид. Након тога се извршавање кода у петљи наставља од оног места (реда) кода где се извршавање прекинуло. Наравно, како се код брзо извршава, корисник неће приметити да је дошло до икаквог прекида, већ ће изгледати као да се све одвија истовремено – извршавање кода из одељка петље и дела из функције позване са настанком прекида. Функције које се позивају када дође до прекида се називају ISR-овима, рутинама сервиса прекида (енг. Interrupt Service Routine). У даљем тексту биће коришћена ова скраћеница када се говори о овим функцијама.

Видео туторијал


Програм – скица

// pinovi na koje su povezane diode, obavezno moraju da podrzavaju PWM
const int led1 = 9;
const int led2 = 10;
const int led3 = 11;

// pinovi na koje su povezani tasteri, moraju da budu 2 i 3 zbog koriscenja 
// prekida  (interrupt-a)
const int tasterUvecaj = 3;
const int tasterUmanji = 2;

// pocetni intenzitet osvetljaja dioda
// volatile - jer se vrednost menja u funkcijama prekida
volatile int osvetljenjeProc = 0;
int osvetljenjePWM;

void setup() {
  // Pinovi na koje su povezane diode se definisu da rade kao izlazi
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  // Pinovi na koje su povezani tasteri se definisu da rade kao ulazi
  // i to realizovani preko pullup otpornika
  pinMode(tasterUvecaj, INPUT);
  pinMode(tasterUmanji, INPUT);

  // pocetno stanje dioda - iskljucene (ne svetle);
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);

  // Osluskivanje stanja tastera - pritisak bilo kog tastera poziva odgovarajucu 
  // funckiju [povecajNivoOsvetljenosti ili smanjiNivoOsvetljenosti]
  attachInterrupt(digitalPinToInterrupt(tasterUvecaj), povecajNivoOsvetljenosti, RISING);
  attachInterrupt(digitalPinToInterrupt(tasterUmanji), smanjiNivoOsvetljenosti, RISING);

}

void loop()
{
  osvetljenjePWM = map(osvetljenjeProc, 0, 100, 0, 255);
  diodeTrepere();
}

void povecajNivoOsvetljenosti() {
  if (osvetljenjeProc < 100) osvetljenjeProc += 10;
}

void smanjiNivoOsvetljenosti() {
  if (osvetljenjeProc > 0) osvetljenjeProc -= 10;
}

void diodeTrepere() {
  analogWrite(led1, osvetljenjePWM);
  analogWrite(led2, osvetljenjePWM);
  analogWrite(led3, osvetljenjePWM);
  delay(200);
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  delay(200);
}
// pinovi na koje su povezane diode, obavezno moraju da podrzavaju PWM
const int led1 = 9;
const int led2 = 10;
const int led3 = 11;

// pinovi na koje su povezani tasteri, moraju da budu 2 i 3 zbog koriscenja prekida  (interrupt-a)
const int tasterUvecaj = 3;
const int tasterUmanji = 2;

// pocetno stanje osvetljaja dioda
// volatile - jer se vrednost menja u funkcijama prekida
volatile int ukljuci = LOW;

void setup() {
  // Pinovi na koje su povezane diode se definisu da rade kao izlazi
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  // Pinovi na koje su povezani tasteri se definisu da rade kao ulazi
  // i to realizovani preko pullup otpornika
  pinMode(tasterUvecaj, INPUT);
  pinMode(tasterUmanji, INPUT);

  // pocetno stanje dioda - iskljucene (ne svetle);
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);

  // Osluskivanje stanja tastera - pritisak bilo kog tastera poziva odgovarajucu funckiju
  attachInterrupt(digitalPinToInterrupt(tasterUvecaj), ukljuciDiode, RISING);
  attachInterrupt(digitalPinToInterrupt(tasterUmanji), iskljuciDiode, RISING);
}

void loop()
{
  digitalWrite(led1, ukljuci);
  digitalWrite(led2, ukljuci);
  digitalWrite(led3, ukljuci);
}

void ukljuciDiode() {
  ukljuci = HIGH;
}

void iskljuciDiode() {
  ukljuci = LOW;
}

Објашњење рада скице (програма)

Одељак дефинисања променљивих и константи

const int led1 = 9;
const int led2 = 10;
const int led3 = 11;

Диоде су повезане на пинове 9, 10 и 11 и те вредности се смештају у променљиве. Пинови 9, 10 и 11 су намерно изабрани зато што подржавају модулацију ширине импулса која омогућава постепено повећавање и смањивање јачине светлости диода. Такви пинови су обележени знаком „~“ (тилда). Променљиве су целобројног типа и њихова вредност се не може променити у току извршавања кода због употребе кључне речи „const“, па се другачије могу назвати целобројним константама.

const int dugmeUvecaj = 3;
const int dugmeUmanji = 2;

Такође пинове на који су повезани тастери се дефинишу као целобројне константе са вредностима 2 и 3. Ово је такође важно јер пинови 2 и 3 на Ардуино УНО плочи имају могућност рада са прекидима!

volatile int osvetljenjeProc = 0;
int osvetljenjePWM;

Променљива чија ће се вредност мењати у ISR-овима се дефинише као „volatile“. Овај корак је битан, јер у противном програм неће исправно радити! Дефинише се „несталну“ променљива целобројног типа osvetljenjeProc која ће садржати информацију о проценту јачине осветљености диоде (могуће вредности од 0 до 100). Друга целобројна променљива osvetljenjePWM ће се користити као помоћна, да би се опсег од 0 до 100% јачине светлости превео на опсег од 0 до 255 који ће се користити код подешавања јачине осветљености диоде (другим речима, то је дозвољени опсег вредности функције analogWrite).

Одељак конфигурације

pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);

Дигитални пинови 9, 10 и 11 на које су повезане диоде led1, led2 и led3 су конфигурисани да раде као излази.

pinMode(tasterUvecaj, INPUT);
pinMode(tasterUmanji, INPUT);

Дигитални пинови 2 и 3 на које су повезани тастери „Увећај“ и „Умањи“ су конфигурисани да раде као излазни.

digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);

Пинови led1, led2 и led3 су постављени на ниски напонски ниво (на почетку извршавања програма, диоде ће бити искључене)

attachInterrupt(digitalPinToInterrupt(tasterUvecaj), povecajNivoOsvetljenosti, RISING);
attachInterrupt(digitalPinToInterrupt(tasterUmanji), smanjiNivoOsvetljenosti, RISING);

Ово је кључни део програма када се говори о раду са прекидима и користи се функција attachInterrupt која има три параметра:

  • digitalPinToInterrupt(tasterUvecaj) – ово је препоручени начин повезивања дигиталног пина са бројем прекида. Дигитални пин 2 је повезан са прекидом INT.0, a дигитални пин 3 је повезан са прекидом INT.1;
  • povecajNivoOsvetljenosti – ISR функција која се извршава онда када се догоди прекид; наводи се само име функције;
  • RISING – трећи параметар дефинише окидање прекида (промена напонског сигнала на дигиталном пину). Могуће вредности су:
    • LOW – да покрене прекид кад год је пин на ниском напонском нивоу – 0,
    • CHANGE – да покрене прекид кад год пин промени стање,
    • RISING – да покрене када пин пређе са ниског на високи напонски ниво,
    • FALLING – да покрене када пин пређе са високог на ниски напонски ниво,

Исто важи и за другу attachInterrupt функцију.

Одељак петље

Коришћење прекида значајно побољшава читљивост програма и његову брзину извршавања, али и поједностављује његову структуру.

Тако у одељку петље постоје само две линије кода:

osvetljenjePWM = map(osvetljenjeProc, 0, 100, 0, 255);

diodeTrepere();

Променљивој osvetljenjePWM ће се доделити одговарајућа вредност из опсега од 0 до 255 у зависности од вредности променљиве osvetljenjeProc чији је могући опсег вредности од 0 до 100 (што представља процентуалну вредност јачине осветљења диоде) и то коришћењем функције map у наведеном формату.

Следи позив функције diodeTrepere.

Функције прекида (ISR функције)

Ове две функције ће се извршити оног тренутка када се буде одиграо догађај који се очекује. У овом случају је притисак тастера „Увећај“ када ће се извршити функција povecajNivoOsvetljenosti, односно smanjiNivoOsvetljenosti када се притисне тастер „Умањи“. Као што је дефинисано задатком, да повећање, односно смањење јачине осветљености диода буде у скоковима од 10%, тако ће и ове функције повећавати и смањивати вредност променљиве osvetljenjeProc за 10%. Наравно, постоји и логичка контрола у виду „иф“ блока која одржава вредност променљиве у границама између 0 и 100.

Функција diodeTrepere

Задатком је такође дефинисано да постоји одређени светлосни ефекат код диода. У овом случају је то треперење (наизменично укључивање и искључивање). Зато што се у задатку тражи да кориснику буде омогућено повећавање и смањивање јачине осветљености диоде, тако диоде морају најпре бити повезане на пинове који имају могућност Модулације ширине импулса. Други корак у решавању је коришћење функције analogWrite која омогућава да на дигиталном пину контролишемо напон у опсегу од 0 до 5V те ће диода светлети тачно одређеном јачином, коју одређује корисник. Диоде свелте одређени временски интервал (у овом случају је 200ms) након чега се диоде искључују функцијом digitalWrite на 200ms.