Журнал LinuxFormat - перейти на главную

LXF164:Соз­да­вать биб­лио­те­ки

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(За­жи­га­ем свет, га­сим свет)
 
Строка 111: Строка 111:
 
Те­перь, когда основ­ной код биб­лио­те­ки го­тов, нуж­но соз­дать со­от­вет­ст­вую­щий ему за­го­ло­воч­ный файл. У на­с он бу­дет таким:
 
Те­перь, когда основ­ной код биб­лио­те­ки го­тов, нуж­но соз­дать со­от­вет­ст­вую­щий ему за­го­ло­воч­ный файл. У на­с он бу­дет таким:
  
#ifndef LXFLED_h
+
#ifndef LXFLED_h
  
#define LXFLED_h
+
#define LXFLED_h
  
 
class LXFLED{
 
class LXFLED{
Строка 175: Строка 175:
 
Здесь мы про­иг­но­ри­ро­ва­ли соб­ст­вен­ный со­вет и не до­ба­ви­ли ни од­но­го ком­мен­та­рия, и про­стой при­мер ра­бо­ты с на­шей биб­лио­те­кой вы­гля­дит так:
 
Здесь мы про­иг­но­ри­ро­ва­ли соб­ст­вен­ный со­вет и не до­ба­ви­ли ни од­но­го ком­мен­та­рия, и про­стой при­мер ра­бо­ты с на­шей биб­лио­те­кой вы­гля­дит так:
  
#include <LXFLED.h>
+
#include <LXFLED.h>
  
 
LXFLED light1(5);
 
LXFLED light1(5);

Текущая версия на 16:39, 30 октября 2018


Элек­тро­ни­ка. Ап­па­рат­ные про­ек­ты с от­кры­тым ко­дом, рас­ши­ряющие ваш кру­го­зор


Содержание

[править] Arduino: Пи­шем биб­лио­те­ки

По­след­няя ста­тья! На­пи­сав, как соз­дать соб­ст­вен­ную биб­лио­те­ку Arduino и еще не­мно­го по­рез­вить­ся со све­то­дио­да­ми, Ник Вейч зачехля­ет па­яль­ник.

(thumbnail)
Наш эксперт. Ко­гда LXF толь­ко поя­вил­ся, его дер­жа­ли на пла­ву исключительно скрип­ты Bash от Ни­ка Вей­ча. По­том их за­ме­ни­ли «лю­ди», и это, по мне­нию Ни­ка, ста­ло ша­гом на­зад...

В про­шлый раз мы го­во­ри­ли о муль­ти­п­лек­си­ро­вании ме­то­дом Чар­ли для управ­ления несколь­ки­ми све­то­дио­да­ми. Сей­час мы вкрат­це рас­смот­рим, как вынести все про­бле­мы на­ру­жу, восполь­зо­вав­шись спе­ци­аль­ной мик­ро­схе­мой для реа­ли­за­ции ло­ги­ки. Про­грам­ми­руе­мые мик­ро­схе­мы мо­гут силь­но оза­да­чить, когда вы си­ди­те и чи­тае­те ру­ко­во­дство за ру­ко­во­дством, что­бы в го­ло­ве от­ло­жи­лись ис­поль­зуе­мые кон­так­ты и про­то­ко­лы. К сча­стью, в этом слу­чае у нас есть удоб­ная сто­рон­няя биб­лио­те­ка, ко­то­рая зна­чи­тель­но уп­ро­ща­ет де­ло.

Но до то­го... не на­пи­сать ли нам несколь­ко сво­их биб­лио­тек? В ми­ре Arduino это обыч­но де­ла­ет­ся, что­бы про­сто и безо­пас­но ис­поль­зо­вать ту или иную мик­ро­схе­му с соб­ст­вен­ной ло­ги­кой – хо­тя на прак­ти­ке биб­лио­те­ка мо­жет де­лать все что угод­но: слож­ные вы­чис­ления, пре­об­ра­зо­вания, про­це­ду­ры об­ра­бот­ки пре­ры­ваний – что угод­но. И вот вам крат­кое ру­ко­во­дство по на­пи­санию соб­ст­вен­ной биб­лио­те­ки, ко­то­рая станет ча­стью сре­ды Arduino.

[править] Ос­но­вы биб­лио­тек

Как вы, на­вер­ное, знае­те из пре­ды­ду­щих уро­ков, ис­ход­ный код Arduino на­пи­сан на C++, и в нем мно­го вспо­мо­га­тель­ных функ­ций из биб­лио­тек Arduino. Что­бы на­пи­сать соб­ст­вен­ную биб­лио­те­ку, нам при­дет­ся немно­го уг­лу­бить­ся в тем­ные пе­ще­ры язы­ка C++.

Для биб­лио­те­ки на C++ нуж­ны как минимум два фай­ла: сам код биб­лио­те­ки (в фай­ле с рас­ши­рением .cpp, так как это код на C++) и за­го­ло­воч­ный файл для это­го ко­да (с рас­ши­рением .h). Име­на фай­лов долж­ны быть оди­на­ко­вы­ми, так ком­пи­ля­тор со­поста­вит их друг с дру­гом.

За­го­ло­воч­ный файл – нечто вро­де оглавления основ­но­го ко­да. Он со­дер­жит «про­то­ти­пы» функ­ций (ко­рот­кая фор­ма со спи­ском па­ра­мет­ров и воз­вра­щае­мым зна­чением), по­мо­га­ющие ком­пи­ля­то­ру свя­зать код, от­ку­да про­ис­хо­дит об­ра­щение к биб­лио­те­ке, с са­ми­ми функ­ция­ми. Сю­да так­же сто­ит за­гля­нуть, ес­ли к биб­лио­те­ке нет до­ку­мен­та­ции, ибо здесь-то и оз­на­че­но, что де­ла­ет биб­лио­те­ка.

Ос­нов­ной код – это обыч­ный код, как то, что вы пи­ше­те в про­грам­ме для Arduino... поч­ти. Раз­ли­чие в том, что в биб­лио­те­ке все нуж­но за­клю­чить в оп­ре­де­ление клас­са. Мы уже поль­зо­ва­лись клас­са­ми, и да­же ес­ли вы не слиш­ком зна­ко­мы с ними, бес­по­ко­ить­ся осо­бо не о чем. Класс – это про­сто слож­ная пе­ре­мен­ная. Вме­сто од­но­го зна­чения в ней мо­жет быть столь­ко зна­чений, сколь­ко вам на­до. Кро­ме то­го, у нее мо­гут быть соб­ст­вен­ные функ­ции (по от­но­шению к клас­су обыч­но на­зы­вае­мые «ме­то­да­ми»), вы­пол­няю­щие оп­ре­де­лен­ные дей­ст­вия с пе­ре­мен­ны­ми клас­са. Го­раз­до про­ще по­яснить все на при­ме­ре. Так как на этот раз мы сно­ва во­зим­ся со све­то­дио­да­ми, мож­но соз­дать класс LED («све­то­ди­од»; кста­ти, од­но­имен­ный класс су­ще­ст­ву­ет и яв­ля­ет­ся ча­стью не основ­но­го ди­ст­ри­бу­ти­ва, а про­ек­та Arduino. Это не он – это про­сто при­мер соз­дания соб­ст­вен­ного класса).

Итак, у нас есть класс LED; ка­кие у него долж­ны быть свой­ст­ва? По­ду­май­те, о ка­ких ас­пек­тах (т. е. свой­ст­вах) объ­ек­та (в этом слу­чае, пред­став­ляю­ще­го ре­аль­ное уст­рой­ст­во) вам нуж­но знать. Так­же прикинь­те, ка­кие свой­ст­ва по су­ти не яв­ля­ют­ся па­ра­мет­ра­ми ре­аль­но­го уст­рой­ст­ва, но по­мо­гут вам управ­лять им.

(thumbnail)
> Пас­порт TLC5490 до­воль­но под­ро­бен, и это очень удоб­ная мик­ро­схе­ма для управ­ле­ния све­то­дио­да­ми или дру­ги­ми ак­тив­ны­ми ком­по­нен­та­ми — на­при­мер, не­боль­ши­ми элек­тро­дви­га­те­ля­ми.

Свой­ст­ва объ­ек­та LED мо­гут быть та­ки­ми:

» Но­мер кон­так­та (т. е. но­мер фи­зи­че­­ско­­го кон­так­та, к ко­то­ро­му он под­клю­чен)

» Яр­кость (ес­ли он под­клю­чен к кон­так­ту с ШИМ)

» Со­стояние (мож­но ли со­хранить в нем со­стояние све­то­дио­да или про­честь его, что­бы ска­зать, вклю­чен он или нет)

Од­но из этих свойств осо­бен­ное – это но­мер кон­так­та. Без него нель­зя под­клю­чить све­то­ди­од или управ­лять им. По­это­му но­мер кон­так­та сле­ду­ет сде­лать ча­стью «кон­ст­рук­то­ра» эк­зем­п­ля­ров клас­са. Это оз­на­ча­ет толь­ко то, что при соз­дании объ­ек­та LED нам обя­за­тель­но при­дет­ся ука­зать но­мер кон­так­та. Мож­но бы­ло бы соз­дать «вир­ту­аль­ный» све­то­ди­од, не под­клю­чен­ный ни к од­но­му кон­так­ту, но тогда при­шлось бы пи­сать бо­лее слож­ные ме­то­ды, про­ве­ряю­щие, за­дан ли но­мер кон­так­та, по­это­му про­ще за­да­вать но­мер кон­так­та при соз­дании объ­ек­та в обя­за­тель­ном по­ряд­ке. Тогда наш код в фай­ле LXFLED.cpp бу­дет на­чи­нать­ся так:

/* LXF LED library */

#include “Arduino.h”
#include “LXFLED.h”

LXFLED::LXFLED(int pin)

{

pinMode(pin_number, OUTPUT);

this->_pin_number = pin;

this->_state = false;

}

В верхней час­ти фай­ла обыч­но (да так и удобнее) раз­ме­ща­ет­ся ком­мен­та­рий с ин­фор­ма­ци­ей о том, что де­ла­ет код, а так­же с ин­фор­ма­ци­ей обо всех ко­пи­рай­тах и ли­цен­зи­ях и, воз­мож­но, с координата­ми ав­то­ра.

Да­лее мы под­клю­ча­ем несколь­ко фай­лов точ­но так же, как вы под­клю­ча­ли фай­лы в сво­их про­грам­мах для Arduino. В дан­ном слу­чае мы хо­тим под­клю­чить стан­дарт­ную биб­лио­те­ку Arduino (ско­рее все­го, на­шей биб­лио­те­ке по­на­до­бят­ся неко­то­рые функ­ции Arduino) и, что чуть бо­лее необыч­но, за­го­ло­воч­ный файл для на­ше­го ко­да.

За­тем сле­ду­ет объ­яв­ление са­мо­го клас­са. Оно всегда на­чи­на­ет­ся с кон­ст­рук­ции <Name>::<Name>, за ко­то­рой сле­ду­ет ли­бо па­ра пустых ско­бок, ли­бо спи­сок па­ра­мет­ров с ти­па­ми, ко­то­рые нуж­но пе­ре­дать клас­су при соз­дании эк­зем­п­ля­ра объ­ек­та. Мы ре­ши­ли, что нам ну­жен но­мер кон­так­та, по­это­му при­ве­ли его здесь. Пе­ре­мен­ная, здесь ука­зан­ная, никак не ка­са­ет­ся то­го, что на­хо­дит­ся вне биб­лио­те­ки, так что не бес­по­кой­тесь о кон­флик­тах с пе­ре­мен­ны­ми в основ­ном ко­де. В тер­ми­нах про­грам­ми­ро­вания, «про­стран­ст­во имен» ог­раничи­ва­ет­ся фай­ла­ми биб­лио­те­ки. В фи­гур­ных скоб­ках ука­зы­ва­ют­ся дей­ст­вия, ко­то­рые долж­ны про­изой­ти при соз­дании объ­ек­та; мы уста­навли­ва­ем ре­жим ра­бо­ты со­от­вет­ст­вую­ще­го кон­так­та в OUTPUT, что­бы управ­лять све­то­дио­дом.

Здесь так­же нуж­но за­дать зна­чения всех пе­ре­мен­ных клас­са. Кон­ст­рук­ция this-> – стан­дарт­ная кон­ст­рук­ция C++, ко­то­рая оз­на­ча­ет, что сле­дую­щая за ней пе­ре­мен­ная яв­ля­ет­ся чле­ном оп­ре­де­ляе­мо­го клас­са. Итак, соз­да­вае­мый эк­зем­п­ляр клас­са по­лу­ча­ет свой­ст­ва «но­мер кон­так­та» (_pin_number) и «со­стояние» (_state). С сим­во­ла под­чер­ки­вания при­ня­то на­чи­нать име­на пе­ре­мен­ных, ко­то­рые яв­ля­ют­ся при­ват­ны­ми для это­го клас­са. Это оз­на­ча­ет, что их зна­чения мож­но из­ме­нять толь­ко в ко­де са­мой биб­лио­те­ки, и ес­ли вы за­хо­ти­те из­менить со­стояние све­то­дио­да (или но­мер кон­так­та), при­дет­ся на­пи­сать со­от­вет­ст­вую­щие функ­ции (ме­то­ды!), ко­то­рые долж­ны быть ча­стью клас­са. Рас­ши­рим наш код, до­ба­вив несколь­ко про­стых ме­то­дов:

void LXFLED::on()

{

digitalWrite(_pin_number, HIGH);

this->_state = true;

}

void LXFLED::off()

{

digitalWrite(_pin_number, LOW);

this->_state = false;

}

Эти два ме­то­да про­сто вклю­ча­ют или вы­клю­ча­ют све­то­ди­од и об­нов­ля­ют его со­стояние. Те­перь на­пи­шем дру­гой ме­тод, ко­то­рый бу­дет воз­вра­щать со­стояние све­то­дио­да:

bool LXFLED::get_state()

{

return this->_state;

}

На­званию ме­то­да здесь пред­ше­ст­ву­ет тип воз­вра­щае­мо­го зна­чения; в дан­ном слу­чае это bool (бу­лев­ское, т. е. «ис­ти­на (true)» или «ложь (false)»). Этот ме­тод про­сто воз­вра­ща­ет зна­чение свой­ст­ва _state объ­ек­та.

Пре­ж­де чем пе­рей­ти к за­го­ло­воч­но­му фай­лу, нуж­но сде­лать еще кое-что. Мы ска­за­ли, что с по­мо­щью этой биб­лио­те­ки так­же мож­но управ­лять и све­то­дио­да­ми с ШИМ. Тогда при вклю­чении нуж­но ка­ким-то об­ра­зом за­да­вать их яр­кость. На уровне Arduino яр­кость уста­нав­ли­ва­ет­ся лег­ко – вклю­чением кон­так­та ме­то­дом analogWrite(), но как ра­бо­тать с этим зна­чением в биб­лио­те­ке? Для него мож­но на­пи­сать от­дель­ный ме­тод – ска­жем, PWM_on() или что-то вро­де это­го – но в C++ есть от­лич­ный трюк, ко­то­рым мы мо­жем восполь­зо­вать­ся, и это «пе­ре­гру­жение [overloading]».

Сно­ва оп­ре­де­лим ме­тод on(), но на сей раз с па­ра­мет­ром:

void LXFLED::on(int level)

{

analogWrite(this->_pin_number, level);

this->_state = true;

}

Это со­вер­шен­но дру­гой ме­тод, ко­то­рый за­да­ет зна­чение ШИМ, как мы и хо­те­ли, но на­звание ме­то­да точ­но та­кое же. Он ра­бо­та­ет бла­го­да­ря то­му, что ком­пи­ля­то­ру C++ хва­та­ет ума по­нять, что ес­ли мы вы­зы­ва­ем ме­тод с одним ар­гу­мен­том ти­па int, то нуж­но вы­полнить имен­но этот код. Ес­ли ар­гу­мен­та нет, вы­пол­ня­ет­ся пре­ды­ду­щий ме­тод. Мож­но оп­ре­де­лить сколь­ко угод­но ме­то­дов с оди­на­ко­вы­ми име­на­ми при усло­вии, что у них у всех бу­дут раз­ные спи­ски па­ра­мет­ров (при­ме­чание: здесь име­ют­ся в ви­ду ти­пы па­ра­мет­ров, т. е. нель­зя соз­дать три ме­то­да, в ка­ж­дом из ко­то­рых бу­дет по од­но­му ар­гу­мен­ту int с раз­ны­ми име­на­ми).

Те­перь, когда основ­ной код биб­лио­те­ки го­тов, нуж­но соз­дать со­от­вет­ст­вую­щий ему за­го­ло­воч­ный файл. У на­с он бу­дет таким:

#ifndef LXFLED_h
#define LXFLED_h

class LXFLED{

public:

LXFLED(int pin);

void on();

void on(int level);

void off();

bool get_state();

private:

int _pin_number;

bool _state;

};

#endif

Кон­ст­рук­ция #ifndef... в на­ча­ле – еще од­но стан­дарт­ное со­гла­шение C++. В слож­ных про­ек­тах мо­жет оказаться несколь­ко час­тей ко­да, ко­то­рые пы­та­ют­ся им­пор­ти­ро­вать од­ну и ту же биб­лио­те­ку. Ес­ли это про­изой­дет, по­след­ст­вия мо­гут быть непри­ят­ны­ми, по­это­му в ка­че­­ст­ве ме­ры пре­досто­рож­но­сти в за­го­ло­воч­ном фай­ле объ­яв­ля­ет­ся пе­ре­мен­ная с именем это­го фай­ла. За­тем мы про­ве­ря­ем ее в на­ча­ле – ес­ли она уже су­ще­ст­ву­ет, это оз­на­ча­ет, что биб­лио­те­ка уже бы­ла под­клю­че­на в ка­кой-то дру­гой час­ти ко­да и ее мож­но про­пустить.

Един­ст­вен­ное, что остается сде­лать здесь – на­пи­сать «за­глуш­ки» клас­са в основ­ном ко­де, т. е. пе­ре­чис­лить все пе­ре­мен­ные клас­са и все ме­то­ды с их ар­гу­мен­та­ми. Для пе­ре­гру­жае­мо­го ме­то­да on() нуж­но при­вес­ти все ва­ри­ан­ты.

Что­бы из­бе­жать оши­бок, луч­ше взять ко­пию основ­но­го фай­ла .cpp и про­сто уда­лить из него код, оста­вив за­го­лов­ки функ­ций. Так вы обес­пе­чи­те, что­бы ар­гу­мен­ты в за­го­ло­воч­ном фай­ле и в ко­де сов­па­да­ли.

[править] Клю­че­вые сло­ва

Дру­гой по­лез­ный файл, ко­то­рый мож­но най­ти в ка­ж­дой биб­лио­те­ке, на­зы­ва­ет­ся keywords.txt. Вы бу­де­те сме­ять­ся, но в нем за­да­ют­ся клю­че­вые сло­ва для ко­да биб­лио­те­ки. Есть два ти­па клю­че­вых слов – пе­ре­мен­ные и име­на объ­ек­та име­ют тип KEYWORD1, а ме­то­ды и функ­ции – тип KEYWORD2.

Нуж­но про­сто пе­ре­чис­лить все это в тек­сто­вом фай­ле с та­ким именем. Сна­ча­ла идет сло­во, за­тем та­бу­ля­ция (не про­бе­лы!), за­тем – тип клю­че­во­го сло­ва. На­при­мер, наш файл с клю­че­вы­ми сло­ва­ми для биб­лио­те­ки LED бу­дет вы­гля­деть так:

# Datatypes

LXFLED KEYWORD1

# methods

on KEYWORD2

off KEYWORD2

get_staus KEYWORD2

Вклю­чать файл keywords.txt в со­дер­жи­мое биб­лио­те­ки необя­за­тель­но, но лучше не полениться и сде­лать это – бла­го­да­ря ему под­свет­ка син­так­си­са в ре­дак­то­ре ко­да Arduino бу­дет ра­бо­тать пра­виль­но.

[править] При­ве­дем при­мер

По­следний этап соз­дания биб­лио­те­ки – при­мер, ил­лю­ст­ри­рую­щий ее ра­бо­ту. Его сто­ит пра­виль­но от­фор­ма­ти­ро­вать и снаб­дить мно­же­ст­вом по­лез­ных ком­мен­та­ри­ев – ес­ли дру­гие не смо­гут по­нять, как поль­зо­вать­ся ва­шей биб­лио­те­кой, они по­ду­ма­ют, что та не особо хо­ро­ша, и поч­ти на­вер­ня­ка не уго­стят вас пи­вком, столк­нув­шись с ва­ми где-нибудь на “Maker Faire” [ме­ро­прия­тие, про­во­ди­мое аме­ри­кан­ским жур­на­лом Make – се­ми­на­ры и пре­зен­та­ции на­уч­ных про­ек­тов, – прим. пер.] или еще где-нибудь.

Соз­дать при­мер про­сто. Для на­ча­ла нуж­но соз­дать ка­та­лог examples (буквы названия – обя­за­тель­но в нижнем ре­ги­ст­ре). Ту­да мож­но по­мес­тить все при­ме­ры. Ес­ли вы со­хра­няе­те их из тек­сто­во­го ре­дак­то­ра, помните, что ка­ж­дый при­мер дол­жен на­хо­дить­ся в од­но­имен­ном ка­та­ло­ге, а файл при­ме­ра дол­жен иметь рас­ши­рение .ino, это но­вое рас­ши­рение для фай­лов «эс­ки­зов» Arduino. Соз­да­вай­те столь­ко при­ме­ров, сколь­ко хо­ти­те, но по­за­боть­тесь о по­нят­ных име­нах для них.

Сре­да Arduino при за­пуске про­ве­ря­ет на­ли­чие при­ме­ров в фай­лах биб­лио­тек и до­бав­ля­ет их в ме­ню, что­бы поль­зо­ва­те­ли смог­ли най­ти и по­про­бо­вать ваш код. Их мож­но най­ти в ме­ню File > Examples > [имя ва­шей биб­лио­те­ки] > [имя ва­ше­го при­ме­ра].

Здесь мы про­иг­но­ри­ро­ва­ли соб­ст­вен­ный со­вет и не до­ба­ви­ли ни од­но­го ком­мен­та­рия, и про­стой при­мер ра­бо­ты с на­шей биб­лио­те­кой вы­гля­дит так:

#include <LXFLED.h>

LXFLED light1(5);

void setup(){}

void loop() {

light1.on(2);

delay(2000);

if (light1.get_state()) {

light1.off();

}

delay(1000);

}

Об­ра­ти­те внимание на от­ли­чия. Кон­ст­рук­ция #include в на­ча­ле нам уже зна­ко­ма, но за­тем мы оп­ре­де­ля­ем пе­ре­мен­ную light1, объ­ект клас­са LXFLED. Соз­дан­ная та­ким об­ра­зом пе­ре­мен­ная на­сле­ду­ет все свой­ст­ва и ме­то­ды клас­са, ко­то­рый мы объ­я­ви­ли ранее. При инициа­ли­за­ции мы планиро­ва­ли еще и за­дать но­мер кон­так­та, ко­то­рый бу­дет вы­хо­дом. Те­перь мы так и де­ла­ем (код кон­ст­рук­то­ра клас­са вы­зы­ва­ет­ся при соз­дании но­во­го эк­зем­п­ля­ра клас­са, т. е. при объ­яв­лении пе­ре­мен­ной light1 это­го ти­па). Сре­ди про­че­го это оз­на­ча­ет, что нам ниче­го не нуж­но де­лать в ме­то­де setup() для дан­ной пе­ре­мен­ной, так как все сде­ла­ет биб­лио­те­ка.

[править] За­жи­га­ем свет, га­сим свет

В основ­ном цик­ле вы­зы­ва­ют­ся ме­то­ды клас­са LXFLED пря­мо из соз­дан­ной на­ми пе­ре­мен­ной – ска­жем, что­бы вклю­чить свето­ди­од, мы вы­зы­ва­ем light1.on(). Ес­ли бы мы под­клю­чи­ли его к кон­так­ту с ШИМ, мы вы­зва­ли бы light1.on(xxx), что­бы вклю­чить его с за­дан­ной яр­ко­стью. По прав­де го­во­ря, в на­шем недо­де­лан­ном ко­де этим ме­то­дом мож­но поль­зо­вать­ся да­же для кон­так­тов без ШИМ (кто-то дол­жен это по­пра­вить).

Да­лее, об­ра­ти­те внимание на то, где мы про­ве­ря­ем со­стояние све­то­дио­да. Мож­но бы­ло бы вы­звать light.off(), но он не про­ил­лю­ст­ри­ру­ет на­ше за­ме­ча­тель­ное умение про­ве­рять это со­стояние. Так как пе­ре­мен­ная со­стояния за­да­ет­ся внут­ри ме­то­дов вклю­чения и вы­клю­чения и недоступ­на на­шей про­грам­ме, вы мо­же­те быть уве­ре­ны в том, что она аде­к­ват­но от­ра­жа­ет со­стояние. Здесь мы про­ве­ря­ем бу­лев­ское зна­чение в опе­ра­то­ре if, что­бы про­ве­рить, что све­то­ди­од вклю­чен, пре­ж­де чем пы­тать­ся его вы­клю­чать.

В том, что­бы де­лать это имен­но так, нет ниче­го осо­бен­но­го, но при­ят­но уви­деть, что оно ра­бо­та­ет. Ме­тод light1.get_state воз­вра­ща­ет бу­лев­ское зна­чение, ко­то­рое за­тем ана­ли­зи­ру­ет­ся опе­ра­то­ром if. Да, это не бог весть что – но оно ра­бо­та­ет и ил­лю­ст­ри­ру­ет все ог­раничен­ные воз­мож­но­сти на­шей скуд­ной биб­лио­те­ки.

В ком­плек­те по­став­ки Arduino мож­но най­ти мас­су при­ме­ров ре­аль­ных биб­лио­тек, но еще боль­ше биб­лио­тек на все слу­чаи жизни соз­да­ли поль­зо­ва­те­ли Arduino. По­ис­кав на фо­ру­мах на сай­те Arduino или на дру­гих сай­тах об Arduino, ко­то­рые вы обыч­но по­се­щае­те, мож­но озо­ло­тить­ся. Ес­ли биб­лио­те­ка за­гру­жа­ет­ся в ви­де фай­ла ZIP, ее мож­но рас­па­ко­вать в ка­та­лог arduino/libraries, и по­сле пе­ре­за­пуска ре­дак­то­ра Arduino она поя­вит­ся в нем.

Боль­шин­ст­во биб­лио­тек на са­мом де­ле пред­став­ля­ют со­бой сво­его ро­да драй­ве­ры для рас­про­странен­ных ком­понен­тов, та­ких как па­мять, уст­рой­ст­ва хранения дан­ных, кон­трол­ле­ры и т. д. Осо­бен­но по­ле­зен драй­вер для мик­ро­схе­мы TLC5940. Как мы уз­на­ли из про­шлой ста­тьи о муль­ти­п­лек­си­ро­вании, боль­ши­ми дис­плея­ми луч­ше все­го управ­лять с по­мо­щью мик­ро­схе­мы драй­ве­ра. На рын­ке их мно­же­ст­во, но TLC5490 об­ла­да­ет луч­шей функ­цио­наль­но­стью и доста­точ­но про­ста, что­бы ис­поль­зо­вать ее с Arduino.

У нее 16 вы­ход­ных линий, ка­ж­дая из ко­то­рых мо­жет ра­бо­тать в ре­жи­ме ШИМ со зна­чением от 0 до 4096, что вось­ми­крат­но пре­вы­ша­ет раз­ре­шение кон­так­тов ШИМ в Arduino. В ней так­же есть соб­ст­вен­ная схе­ма ог­раничения то­ка, и ка­ж­дый све­то­ди­од по­лу­ча­ет имен­но та­кой ток, ка­кой ему необ­хо­дим – нуж­но про­сто уста­но­вить эта­лон­ное зна­чение, под­клю­чив под­хо­дя­щий ре­зи­стор к од­но­му из кон­так­тов. Един­ст­вен­ная мел­кая слож­ность с TLC5490 – это иногда чрез­мер­но слож­ный про­то­кол уста­нов­ки зна­чений от­дель­ных ка­на­лов (пре­ж­де все­го из-за до­полнитель­ных воз­мож­но­стей, та­ких как со­об­щения об ошиб­ках, ко­то­рые мо­гут возник­нуть из-за неис­прав­ных све­то­дио­дов).

Так или ина­че, боль­шая часть этих слож­но­стей скры­та от ми­ра Arduino, по­то­му что кто-то на­пи­сал биб­лио­те­ку для этой микро­схе­мы. Вам при­дет­ся на­пи­сать мно­го ко­да, но схе­мы для управ­ления дис­плея­ми боль­ше­го раз­ме­ра мож­но со­единить в гир­лян­ду (хо­тя, конеч­но, ее мак­си­маль­ная дли­на для немер­цаю­ще­го дис­плея бу­дет ог­раниче­на ве­ли­чи­ной за­держ­ки рас­про­странения сиг­на­ла).

Биб­лио­те­ка для TLC5490 есть на на­шем DVD, и мы так­же при­во­дим прин­ци­пи­аль­ную схе­му ее ти­пич­но­го под­клю­че­ния. |

Персональные инструменты
купить
подписаться
Яндекс.Метрика