Arduino: Предаване на фиксирани команди чрез nRF24L01
 

Посвещавам тази статия на моя приятел Николай Др. Николов, който събуди у мен увлечението по моделистиката в младежките ни години.


В моделистиката често са необходими освен пропорционални команди, така и фиксирани команди. Например: да включите светлини или клаксон на кола, да завъртите оръдие на модел на танк или да го накарате да "гръмне".

Оказа се, че в моята любима библиотека интернет има подобни проекти, но главно с цел обучение и практика. След като отделих цял ден в търсене на подобни проекти, накрая се оказа, че в действителност има само един такъв, който е мултиплициран и модифициран от двама-трима автори. Проектът онагледява изпращане на команда от една Arduino платка към друга чрез натискане на бутон в предаващата, а включване/изключване на светодиод в приемащата.

Естествено беше да изпробвам този обучителен проект. И каква беше изненадата ми и неприятното чувство, когато още при проверката се установи грешка. От практиката ми, се оказва, че неведнъж съм се натъквал на такива, бих ги нарекъл, "кухи" проекти в интернет сайтове. Разбира се, ядосах се, и тогава реших да публикувам моя статия на същата тема - без скрити кодове, без условности, без преднамерени "грешки" - с четири команди и четири светодиода.

След това реших да отделя повече време и да разгледам в подробности публикуваните кодове, за да ви покажа необходимите корекции за да стане той работещ. Той има за цел да покаже основния програмен код за предаване на една команда от бутон в предавател чрез nRF24L01 към приемник, в който командата се реализира визуално с включване и изключване на LED светодиод. Този проект може да намерите на няколко web сайта, но най-добре е описан в [2]:

За предаване на данните се използва дума, байт, наречен msg(0). В предавателя, след инициализиране на вход за бутон, на неговото състояние, както и при какво ниво следва да предава това състояние, то на това състояние се определя стойност 111, което число се изпраща към приемника с msg(0). В приемника се получава думата msg(0) след което с няколко програмни реда се извлича числото 111 и то служи като команда за управление на светодиода.

Обръщам внимание, че ако просто направите copy-paste на публикуваните кодове за предавател и приемник, няма да постигнете никакъв резултат. Необходимо е да въведете правилния синтаксис за инициализация на библиотеките.

Тоест, вместо:

    #include "nRF24L01.h" следва да бъде: #include <nRF24L01.h>
    #include "RF24.h" следва да бъде: #include <RF24.h>

И все пак, чисто методично статията има своето значение и аз силно препоръчвам да я прочетете и изпробвате кодовете, които може да вземете от архива в моята статия с нанесените поправки. Но ако разгледате статията, номерирана в "Литература" под № 1 ще намерите по-кратки обяснения, но правилни кодове. (поставих я на първо място, въпреки че я намерих последна).

Цитираните по-горе кодове са с илюстративна цел. Те не отчитат лошите контакти на бутоните, че натискането на един бутон е съпроводено често с много импулси поради тях. За да се избегне ефекта от ненадейно случайно преминаване през състоянията включено/изключено в Arduino IDE е съобразена специална команда за работа с тактилни бутони, на чието използване може да обърнете внимание в приложените в архива мои скечове. Описанието на тази и други команди може да намерите на официални сайт на Arduino:

    Debounce: https://www.arduino.cc/en/Tutorial/Debounce

Тази команда се използва заедно с millis(). Тя има за цел в кратък период от време да провери повторно състоянието на натиснатия бутон за потвърждение на неговото състояние: включено/изключено. Как се отразява това практически - именно едно натискане на бутона съответства само на една команда и не се влияе от трепкането и лошия контакт.

В архива към статията предлагам три комплекта кодове за предаване на една, три и на четири команди. Накратко принципът е следния:

Предавател:
    a) включваме необходимите библиотеки.
    b) наименуваме си байт чрез който ще предаваме данните "TxRx".
    c) инициализираме входовете на Arduino към които свързваме бутоните.
    d) отваряме канал за предаване чрез модула nRF24L01.
    e) всяка команда директно чете състоянието на бутона и го записва в TxRx.
    f) предаваме данните чрез командата:

    bool ok = radio.write(TxRx, sizeof(TxRx));

която означава, че ако в байта има данни, то те се предават чрез думата "TxRx" към nRF24L01.

Приемник:
    a) Действията от първите три подточки на предавателя са същите.
    b) Отваряме канал за приемане чрез nRF24L01.
    c) Проверяваме дали радиото приема и ако е така инициализираме четене на байта "TxRx"
    d) Следва цикъла който чете за всеки светодиод поотделно своята си дума TxRx[…], дали е или не е включен светодиода и команда за включване

    digitalWrite(led, ledOn);

Чрез оформяне на последователни цикли се разчитат съответните команди, идващи с номерацията на носещата дума "TxRx[…]"

Зажележка №1: последователността на номерацията на думите в предавателя трябва да бъде в съответствие с последователността на номерацията в приемника за да се осигури последователност и сигурност на командите.

Забележка №2: възможно е броя на думите в предавателя да бъде по-голям от броя на думите в приемника, но обратното не е възможно и води до объркване на последователността на командите и нестабилно случайно включване.

Ако проследите моите кодове, ще видите, че двете забележки са изпълнени. Например: броя на думите, които съответстват на командите в предавателя са шест, а в приемника са програмирани три (в единия код, четири в другия) но стриктно е спазена последователността им - 1, 2, 3.

Забележка №3: определят се броя на думите според броя на командите като TxRx[6], но тяхната последователност започва с TxRx[0] и задължително завършва най-много с TxRx[5], тоест нулата "0" е значещо число (0-5).

Забележка №4: в предавателя след инициализацията на определен вход за бутон, не използвам последователен резистор към захранването каквато е дадената схема в посочената литература. Използвам възможностите, които дава Arduino, а именно поставям входа във високо състояние, следователно директното свързване на бутон от входа към маса ще сменя това състояние от високо в ниско:

    pinMode(3, INPUT_PULLUP);

Забележка №5: в приемника нарочно, с експериментална цел, използвам възможностите на Arduino да инициализа аналоговите входове в цифрови. За целта инициализацията има следния вид:

    int led1 = 14;

където номерацията "14" съответства на последователността на аналоговите изходи като цифрови на Arduino:
   
    А0 = 14;
    А1 = 15;
    А2 = 16;
    А3 = 17;
    А4 = 18;
    А5 = 19;

Същото не е валидно за останалите изводи А6 и А7.

Всъщност, идеята да тествам работата на аналоговите входове на Arduino като цифрови, съвсем не беше случайна. Тестът е свързан с факта, че Wi-Fi модула nRF24L01 използва пет цифрови извода, с което количеството им спада почти наполовина, а за моите проекти са ми необходими колкото се може повече. От друга страна, както знаете, цифровите изходи с ШИМ за Arduino UNO и Nano са 3, 5, 6, 9, 10, 11 и очевидно nRF24L01 "унищожава" 9, 10, и 11. За да се справя с този проблем и увелича полезните изводи с ШИМ програмирам свързването на модула чрез изводи 7, 8, 11, 12 и 13, като по този начин освобождавам още два изхода с ШИМ, които замествам със 7 и 8. Но губя тях.

Е, то угодия няма, нали? И тогава се оказа, че мога да допълня количеството на цифровите изходи като взема от аналоговите, които не са ми необходими.

Надявам се тази статия да ви е полезна. Накрая искам да добавя, че описания принцип на предаване на команди може да се използва и за други несложни механизми, в противен случай ще ви се наложи това да стане с масиви от данни, което не е обект на този материал. Аз, самият, не съм достигнал до това ниво.

А сега ще ви покажа с няколко снимки как изглежда "опитната постановка", както поотделно на двете части от нея, така и заедно при изключено и включено състояние. За улеснение съм запоил светодиодите и последователните на тях резистори от 220 Ω директно към платката. Конструкцията, както може би забелязахте е с две платки Arduino Nano V3. Едната е монтирана за предавател на елементарна печатна платка, а другата като приемник на шийлд за Arduino Nano.

Ето заедно:

Със следващите няколко снимки ще илюстрирам работата на описания (комплект) програмен код.

И все пак, силно препоръчвам да изпробвате работата на този код. Ще останете доволни.
 

Архив с Arduino .ino файлове:

one_button_plus_led.zip [zip,ino][2kb]
three_buttons_plus_leds.zip [zip,ino][2kb]
four_buttons_plus_leds.zip
[zip,ino][2kb]

Подаването на командите с бутони е плавно, меко, няма присветвания или моментни резки промени на състоянията включено/изключено. Аз, лично, тествам всеки код, който ми се струва интересен. Една част от тях не "тръгват" от първия път, но с малко мислене, внимателно вникване в чуждата идея успявам да възстановя тяхната работа.

А ето сега в няколко последователни снимки може да видите визуалния ефект от включване и изключван на светодиодите в приемника в зависимост от подадената от предавателя команда:

Благодаря на Александр за основата на кода (http://sadeb.ru/).


Литература:
1. Wiring the NRF24L01 2.4GHz Radio as Remote Switching
2. Wireless remote using 2.4 GHz nRF24L01: Simple tutorial using of nRF24L01 & Aarduino
3. Arduino Wireless Remote with 2.5GHz NRF24L01
4. Wireless remote using 2.4 GHz nRF24L01: Simple tutorial using of nRF24L01 & Aarduino

5. Arduino Nano v3.0 pinout

Валери Терзиев
20 септември 2018 година