Статьи

Бездротовий вимикач на базі СС13хх

  1. Найпростіша автоматизація - бездротової вимикач
  2. Розробка програмного забезпечення для вузлів
  3. структура rfWakeOnRadioRx
  4. структура rfWakeOnRadioTx
  5. Реалізація сенсорної кнопки на SensorController
  6. Інтеграція сенсорної кнопки проект в rfWakeOnRadioTx
  7. Наближення до реальності
  8. Висновок

Будь-які рішення інтернету речей немислимі без пристроїв, що забезпечують безпосередню взаємодію з користувачем за допомогою вимикачів і реле Будь-які рішення інтернету речей немислимі без пристроїв, що забезпечують безпосередню взаємодію з користувачем за допомогою вимикачів і реле. Давайте розглянемо процес розробки макета адресується бездротового вимикача на основі базових програмних проектів для серії CC13xx від TI.

Автоматизація будівель і територій будь-якого призначення (житлових будинків, комерційної нерухомості, виробничих площ) завжди була однією з цікавих завдань, що не мають загального рішення. У переважній більшості випадків системи типу розумний будинок і інтелектуальне середовище розробляються з урахуванням вимог і реалій кінцевого споживача. Бездротові технології відіграють в таких системах не останню роль, а в багатьох випадках вони є стрижнем всієї системи.

Основними завданнями бездротових пристроїв є збір інформації та передача команд управління на виконавчі вузли. У найпростішому випадку це - сигналізація, вимикачі, реле та інше. Досить часто реалізація бездротового каналу кінцевих пристроїв є односпрямованої, тобто з метою економії вузол оснащується простим приймачем (ресивером). Не можна сказати, що таке рішення є поганим, але іноді з'являється необхідність в зворотному каналі для моніторингу стану вузла або підтвердження отримання команди. У сучасних умовах більш правильним рішенням для кінцевого бездротового вузла буде все-таки оснащення його повноцінним приемопередатчиком, благо через конкуренцію їх вартість є цілком прийнятною. З урахуванням того, що кінцевий вузол повинен буде виконувати будь-які функції, а також брати участь в роботі мережі, з метою зниження розмірів, кількості компонентів (BOM) і енергоспоживання бездротова система-на-кристалі (СНК, або простіше - бездротової мікроконтролер) - цілком очікуваний вибір.

Звичайні критерії при виборі бездротового РНК - можливі частотні діапазони, підтримувані стандарти, енергоспоживання, набір периферійних пристроїв. Якщо розглядати РНК виробництва компанії Texas Instruments, то на поточний момент для систем автоматизації дуже привабливі контролери розвивається серії CC13xx сімейства SimpleLink.

Однією з перших (а можливо і перша) компанія TI застосувала в бездротових РНК многоядерную технологію. Серія CC13xx пропонує розробнику два доступних для програмування ядра - високопродуктивне 32-розрядний Cortex-M3 і малопотребляющее 16-розрядний RISC.

Типовим поділом завдань для ядер є обслуговування стека протоколів і взаємодія з користувачем для 32-розрядної ядра і робота з периферійними пристроями - для 16-розрядної. Другим плюсом пристроїв серії CC1350 є малий струм споживання і родючості, і мікроконтролерних ядер, а також - малі струми в режимі очікування.

Найпростіша автоматизація - бездротової вимикач

Розглянемо побудову простого каналу управління кінцевим пристроєм на базі мікросхем CC1350. За базу для бездротових вузлів будуть використані модулі MBee-DUAL-3.3-UFL-SOLDER-1350-UFL, вибір модулів пояснюється досить просто: вони компактні, з достатньою кількістю висновків, не вимагають додаткових компонентів.

Функціональність передбачимо наступну. Нехай в нашій системі присутній вузол з кнопкою включення / вимикання (вимикач) і вузол, керуючий навантаженням за допомогою твердотільного реле. Також для вузла-кнопки передбачимо варіант підключення сенсорної кнопки. Для обслуговування сенсорної кнопки задіємо 16-бітове RICK-ядро SensorController, це дозволить, з одного боку, не сильно змінювати вихідний код прикладу, з іншого - дасть лише невеликий приріст споживаного струму в порівнянні з реалізацією кнопки на основному ядрі.

Схематично структура найпростішого пристрою управління навантаженням представлена ​​на малюнку 1:

  • вузол-вимикач з двома кнопками - простий і сенсорної;
  • вузол виконавець з твердотілим реле, до якого можна підключити навантаження, що працює від постійного або від змінного струму.

Передбачається, що обидва вузла мають автономне батарейне харчування.

Передбачається, що обидва вузла мають автономне батарейне харчування

Мал. 1. Схематичне уявлення бездротового вимикача і виконавчого пристрою

Розробка програмного забезпечення для вузлів

Розглянувши і протестувавши можливі варіанти серед прикладів, пропонованих TI з вхідних в SDK для СС13ХХ (зокрема - EasylinkRX, EasylinkTX, EasylinkNP, rfWakeOnRadioRX, rfWakeOnRadioTx, sensor1350lp), був зупинений вибір на парі rfWakeOnRadioRX + rfWakeOnRadioTx.

Вибір зв'язки прикладів rfWakeOnRadioRx + rfWakeOnRadioTx для налагоджування плати CC1350 LaunchPad обумовлений ще й тим, що вона практично повністю реалізує функціонал бездротового вимикача. Крім того, дана зв'язка дозволяє використовувати один і той же код і для вузлів з автономним живленням, і для вузлів, що мають стаціонарне харчування.

rfWakeOnRadioRx переводить радіомодуль СС1350 в режим Wake-On-Radio, що має суттєві переваги в споживанні струму в порівнянні з просто режимом прийому - середній струм споживання знижується в кілька разів. Модуль автоматично переходить в режим прийому при виявленні приходить пакета.

З апаратних пристроїв отладочной плати задіяна пара світлодіодів:

  • Board_PIN_LED0 (червоний діод) загоряється в той час, коли трансивер знаходиться в режимі прийому, решту часу блимає, показуючи фонову активність трансивера в режимі Wake-On-Radio;
  • Board_PIN_LED1 (зелений) - змінює свій стан після кожного успішного прийому пакета, на початку роботи програми не світиться.

rfWakeOnRadioTx працює в парі з rfWakeOnRadioRx - після натискання кнопки він передає пакет спеціального формату (в порівнянні зі звичайним збільшена довжина преамбули) і перемикає стан світлодіода після кожної передачі пакету.

Задіюються наступні ресурси плати LaunchPad:

  • Board_PIN_LED1 (зелений) - перемикається після кожної передачі пакету;
  • Board_PIN_BUTTON0 - ініціює процедуру передачі пакета.

Також видаються повідомлення про хід виконання програми по інтерфейсу UART і оновлюється інформація на модулі LCD, якщо він підключений.

На малюнку 2 представлена ​​схема підключення світлодіодів і кнопок до модуля MBee-DUAL-3.3-UFL-SOLDER-1350-UFL, що дозволяє запускати і спостерігати виконання прикладів rfWakeOnRadioTx / Rx.


Мал. 2. Схема підключення світлодіодів і кнопок до модуля MBee-DUAL-3.3-UFL-SOLDER-1350-UFL, що дозволяє запускати і спостерігати виконання прикладів rfWakeOnRadioTx / Rx

структура rfWakeOnRadioRx

Структура програмного проекту rfWakeOnRadioRx досить проста. У ньому всього одне завдання rxTask і кілька call-back функцій.

Функція main (файл rfWakeOnRadioRx.c):

/ * * ======== main ======== * / int main (void) {/ * Загальна ініціалізація плати і драйверів * / Board_initGeneral (); / * Налаштування ліній для управління світлодіодами * / ledPinHandle = PIN_open (& ledPinState, pinTable); Assert_isTrue (ledPinHandle! = NULL, NULL); / * Ініціалізація завдання rxTask * / rxTaskInit (); / * Запуск операційної системи * / BIOS_start (); return (0); }

rxTaskInit налаштовує параметри завдання - розмір стека, пріоритет, функцію завдання. Основна робоча функція даного проекту - rxTaskFunction. У ній відбувається налаштування параметрів трансивера, створюється черга повідомлень, налаштовується прийом в режимі прослуховування (режим Wake-On-Radio) і в нескінченному циклі очікується прихід пакетів:

/ * RX task function. Executed in Task context by TI-RTOS when the scheduler starts. * / Static void rxTaskFunction (UArg arg0, UArg arg1) {/ * ініціалізувавши параметри приймача * / RF_Params rfParams; RF_Params_init (& rfParams); / * Висновок, підключений до LED1, налаштовується таким чином, щоб відображати активність трансивера в режимі прийому * / PINCC26XX_setMux (ledPinHandle, Board_PIN_LED0, PINCC26XX_MUX_RFC_GPO0); / * Створення черги повідомлень * / if (RFQueue_defineQueue (& dataQueue, rxDataEntryBuffer, sizeof (rxDataEntryBuffer), NUM_DATA_ENTRIES, MAX_LENGTH + NUM_APPENDED_BYTES)) {/ * Failed to allocate space for all data entries * / while (1); } / * Налаштування sniff-режиму на прийом * / initializeSniffCmdFromRxCmd (& RF_cmdPropRxSniff, & RF_cmdPropRx); / * Налаштування приймача * / RF_cmdPropRxSniff.pQueue = & dataQueue; RF_cmdPropRxSniff.pOutput = (uint8_t *) & rxStatistics; RF_cmdPropRxSniff.maxPktLen = MAX_LENGTH; / * Налаштування відкидання пакетів з помилкою контрольної суми з черги пакетів * / RF_cmdPropRxSniff.rxConf.bAutoFlushIgnored = 1; RF_cmdPropRxSniff.rxConf.bAutoFlushCrcErr = 1; / * Calculate datarate from prescaler and rate word * / uint32_t datarate = calculateSymbolRate (RF_cmdPropRadioDivSetup.symbolRate.preScale, RF_cmdPropRadioDivSetup.symbolRate.rateWord); / * Configure Sniff-mode part of the RX_SNIFF command * / configureSniffCmd (& RF_cmdPropRxSniff, WOR_MODE, datarate, WOR_WAKEUPS_PER_SECOND); / * Отримання доступу до трансивер, за фактом - ініціалізація роботи через драйвер * / rfHandle = RF_open (& rfObject, & RF_prop, (RF_RadioSetup *) & RF_cmdPropRadioDivSetup, & rfParams); / * Налаштування робочої частоти * / RF_runCmd (rfHandle, (RF_Op *) & RF_cmdFs, RF_PriorityNormal, & callback, 0); / * Зберігаємо для відліку таймінгу поточний системний час приймача * / RF_cmdPropRxSniff.startTime = RF_getCurrentTime (); / * Основний робочий цикл * / while (1) {/ * Задаємо інтервал для наступного пробудження * / RF_cmdPropRxSniff.startTime + = WOR_WAKE_UP_INTERVAL_RAT_TICKS (WOR_WAKEUPS_PER_SECOND); / * Перевіряємо прихід пакету в режимі прослуховування, в разі успішного прийняття буде виконана процедура callback * / RF_runCmd (rfHandle, (RF_Op *) & RF_cmdPropRxSniff, RF_PriorityNormal, & callback, RF_EventRxEntryDone); / * Фіксуємо результат прослуховування ефіру * / switch (RF_cmdPropRxSniff.status) {case PROP_DONE_IDLE: / * Idle based on RSSI * / worStatistics.doneIdle ++; break; case PROP_DONE_IDLETIMEOUT: / * Idle based on PQT * / worStatistics.doneIdleTimeout ++; break; case PROP_DONE_RXTIMEOUT: / * Got valid preamble on the air, but did not find sync word * / worStatistics.doneRxTimeout ++; break; case PROP_DONE_OK: / * Received packet * / worStatistics.doneOk ++; break; default: / * Unhandled status * / break; }; }}

В разі успішного прийняття пакету викликається процедура callback, в яка змінює стан зеленого світлодіода:

void callback (RF_Handle h, RF_CmdHandle ch, RF_EventMask e) {/ * Перевіряємо отримання пакета і його доступність для читання * / if (e & RF_EventRxEntryDone) {/ * Запускається цикл обробки пакетів по всіх пакетів, що знаходяться в черзі * / do {/ * Якщо пакет отриманий - перемикаємо світлодіод * / PIN_setOutputValue (ledPinHandle, Board_PIN_LED1,! PIN_getOutputValue (Board_PIN_LED1)); / * Отримуємо покажчик на поточний необроблений пакет * / currentDataEntry = RFQueue_getDataEntry (); / * Обробляємо пакет, розташований в черзі за адресою & currentDataEntry-> data: * - Length - перший байт містить поточну конфігурацію * - Data - дані пакета починаються з другого байта * / packetLength = * (uint8_t *) (& currentDataEntry-> data); packetDataPointer = (uint8_t *) (& currentDataEntry-> data + 1); / * Тут можна додавати свої процедури для обробки пакета, наприклад, фільтрацію адрес, розбір пакета та інше * / volatile uint8_t dummy; dummy = packetLength + packetDataPointer [0]; } While (RFQueue_nextEntry () == DATA_ENTRY_FINISHED); }}

Фактично, якщо виконавчий пристрій одне і в зоні радиовидимости приймального вузла немає інших передавачів - вузол з проектом rfWakeOnRadioRx може сміливо керувати навантаженням, досить підключити вхід твердотільного реле до висновку Board_PIN_LED1.

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

структура rfWakeOnRadioTx

Функція main в проекті передавача rfWakeOnRadioTx аналогічна прикладу з приймачем, це - ініціалізація драйверів, настройка висновків для кнопок і світлодіодів, ініціалізація завдання txTask і запуск операційної системи.

Центральна робоча функція в даному проекті - txTaskFunction ():

/ * TX task function. Executed in Task context by TI-RTOS when the scheduler starts. * / Static void txTaskFunction (UArg arg0, UArg arg1) {/ * Завдання callback-функції для обробки натискання кнопки * / PIN_Status status = PIN_registerIntCb (buttonPinHandle, & buttonCallbackFunction); Assert_isTrue ((status == PIN_SUCCESS), NULL); / * Ініціалізація трансивера * / RF_Params rfParams; RF_Params_init (& rfParams); / * Ініціалізація режиму TX_ADV * / initializeTxAdvCmdFromTxCmd (& RF_cmdPropTxAdv, & RF_cmdPropTx); / * Завдання значень полів пакету * / RF_cmdPropTxAdv.pktLen = PAYLOAD_LENGTH +1; / * +1 for length byte * / RF_cmdPropTxAdv.pPkt = packet; RF_cmdPropTxAdv.preTrigger.triggerType = TRIG_REL_START; RF_cmdPropTxAdv.preTime = WOR_PREAMBLE_TIME_RAT_TICKS (WOR_WAKEUPS_PER_SECOND); / * Отримання доступу завдання до трансивер * / rfHandle = RF_open (& rfObject, & RF_prop, (RF_RadioSetup *) & RF_cmdPropRadioDivSetup, & rfParams); / * Налаштування робочої частоти * / RF_runCmd (rfHandle, (RF_Op *) & RF_cmdFs, RF_PriorityNormal, NULL, 0); / * Основний цикл завдання * / while (1) {RF_yield (rfHandle); // add / * Очікування натискання кнопки: обробник натискання кнопки посилає повідомлення в чергу завдання * / Semaphore_pend (txSemaphoreHandle, BIOS_WAIT_FOREVER); / * Створюється пакет з інкрементіруемим номером (буде збільшуватися після кожної транзакції), вміст пакету - випадкова послідовність * / packet [0] = PAYLOAD_LENGTH; packet [1] = (uint8_t) (seqNumber >> 8); packet [2] = (uint8_t) (seqNumber ++); uint8_t i; for (i = 3; i <PAYLOAD_LENGTH +1; i ++) {packet [i] = rand (); } / * Виклик команди для передачі пакета * / RF_runCmd (rfHandle, (RF_Op *) & RF_cmdPropTxAdv, RF_PriorityNormal, NULL, 0); / * Зміна стану світлодіода * / PIN_setOutputValue (ledPinHandle, Board_PIN_LED1,! PIN_getOutputValue (Board_PIN_LED1)); }}

Оброблювач натискання кнопки просто посилає повідомлення завданню передачі даних, а також забезпечує програмний антидребезга:

/ * Pin interrupt Callback function board buttons configured in the pinTable. * / Void buttonCallbackFunction (PIN_Handle handle, PIN_Id pinId) {/ * Ппростая реалізація антидребезга (пауза і перевірка, чи натиснута ще кнопка) * / CPUdelay ((uint32_t) ((48000000/3) * 0.050f)); if (! PIN_getInputValue (pinId)) {/ * Post TX semaphore to TX task * / Semaphore_post (txSemaphoreHandle); }}

Для роботи в умовах декількох вузлів даний приклад вимагає формування пакета заздалегідь визначеного формату, а також очікування підтвердження прийняття пакета від виконавчого вузла.

Реалізація сенсорної кнопки на SensorController

Розглянемо реалізацію сенсорної кнопки для вузла-вимикача. Основною перевагою ємнісних сенсорних кнопок є відсутність рухомих елементів і контактів, здатних окислюватися або зношуватися механічно. Однак за ці переваги доводиться платити необхідністю її обслуговування, тобто повинен бути або апаратний, або програмний компонент, який визначає момент доторку користувача до поверхні.

У випадку з CC13xx на допомогу приходить SensorController, що має всі необхідні периферійні пристрої для обслуговування ємнісний сенсорною кнопки без додаткових зовнішніх елементів - не потрібно навіть резисторів або конденсаторів.

Створюємо проект в SensorControllerStudio. Оскільки в подальшому передбачається інтеграція проекту rfWakeOnRadioTx - налаштовуємо збереження згенерованих початкових кодів в папку проекту, наприклад, C: / Users / 111 / workspace_v7 / rfWakeOnRadioTx_CC1350_LAUNCHXL_tirtos_ccs.

Приклад програмних сенсорних кнопок для SensorController можна подивитися в системі допомоги SensorControllerStudio в розділі Peripherals → ISRC (а також - Peripherals → TDC, але перший варіант краще).

Згідно з довідкою, ємнісна сенсорна кнопка може бути підключена до одного з висновків DIO23 ... DIO30. Задіюються вбудований джерело струму ISRC, компаратор COMPA, опорний джерело струму 2 мкА, вбудований резистор 400 кОм, TDC - перетворювач «час-код». На малюнку 3 показаний вибір необхідних бібліотек.

На малюнку 3 показаний вибір необхідних бібліотек

Мал. 3. Налаштування бібліотек в SensorControllerStudio для проекту сенсорної кнопки

Також в довідці наводиться приклад вихідного коду для опитування сенсорних кнопок. Алгоритм наступний:

  1. дозволяється робота компаратора і опорного джерела струму 2 мкА з резистором 400 кОм;
  2. запускається джерело струму;
  3. вибирається джерело тактирования для перетворювача «час-код»;
  4. запускається відлік перетворювача «час-код» з умовою зупинки після досягнення верхньої межі;
  5. Вичікують час паузи;
  6. висновок кнопки-сенсора перемикається на загальний (скидається заряд ємності кнопки);
  7. зчитуються показання перетворювача «час-код».

Малюнки 4 і 5 демонструють схему підключення сенсорної кнопки до модулю MBee Dual (До висновку DIO26) і настройки I / O Mapping в SensorControllerStudio відповідно.

Малюнки 4 і 5 демонструють схему підключення сенсорної кнопки до модулю   MBee Dual   (До висновку DIO26) і настройки I / O Mapping в SensorControllerStudio відповідно

Мал. 4. Схема підключення сенсорної кнопки до модуля MBee Dual

Мал. 5. Налаштування I / O Mapping в SensorControllerStudio

На практиці настройки джерела струму для пункту 2 алгоритму і час очікування в пункті 5 підбираються залежно від конфігурації, розмірів контактів сенсорної кнопки і товщини і матеріалу діелектричного шару.

Код проекту сенсорної кнопки містить дві непусті секції - Initialization Code і Execution Code. Код в них практично ідентичний, але через особливості формування програмного коду для SC доводиться його дублювати в обох секціях з незначними змінами.

Створюються такі змінні, доступні і для основного ядра:

  • cfg.tdch і cfg.tdcL - змінні, що зберігають час заряду ємнісний кнопки в ненажатом стані, значення в них записується при ініціалізації завдання в SC;
  • output.tdch і output.tdcL - змінні, що зберігають час заряду ємнісний кнопки в натиснутому стані;
  • output.touch - змінна-прапор, що показує факт спрацьовування сенсорної кнопки, яка встановлюється в 1 при виявленні натискання і скидається в 0 на початку кожного циклу опитування.

Нижче наведено код для опитування сенсорної кнопки в секції Execution Code з коментарями відмінностей від секції Initialization Code:

output.touch = 0; // Дозвіл роботи COMPA, включаючі джерело Струму 2 мкА з НАВАНТАЖЕННЯ у виде резистора 400 кОм з порогом 0,8 В від джерела опорного напруги compaEnableWithCapTouchRef (); // Запускається джерело Струму зі значенням віхідного Струму 1,0 мкА U16 current = BV_ISRC_CURR_1P0U; // * Підбірається вручну isrcEnable (current); // Вібірається джерело тактирования перетворювач «годину-код» tdcSetCntSource (TDC_CNTSRC_96M_RCOSC); // Запускається перетворювач «годину-код» зі спрацьовуванням за фактом заряду ємності контактів кнопки tdcSetTriggers (TDC_STARTTRIG_ISRC_RELEASE, TDC_STOPTRIG_COMPA_HIGH, 0); tdcEnable (); // Вібірається лінія Введення-Виведення з сенсорним контактом compaSelectGpioInput (AUXIO_AXD_CAP_SENS_BUTTON); // Готується перетворювач «годину-код» и запускається процес вимірювань tdcArm (TDC_START_ASYNC); isrcRelease (AUXIO_AXD_CAP_SENS_BUTTON); // Пауза Очікування в 100 мкс tdcWaitUs (100); // * Підбірається вручну // Сенсорний контакт перемікається на «землю» // примусових розряджається Ємність контактів isrcClamp (AUXIO_AXD_CAP_SENS_BUTTON); // Зчітується значення перетворювач «годину-код» tdcGetValue (output.tdcH, output.tdcL); // tdcGetValue (cfg.tdcH, cfg.tdcL); - для секції Initialization // Зупіняється робота COMPA, ISRC and TDC tdcDisable (); isrcDisable (); compaDisable (); // Задаємо поріг для віключення помилковості спрацьовування від перешкоду и Іншого U16 sens_level = cfg.tdcL + (cfg.tdcL >> 3); // нет в секції Initialization // Если поріг перевіщено - повідомляємо основне ядро ​​через ПОВІДОМЛЕННЯ ALERT // Alert application // нет в секції Initialization if (output.tdcL> sens_level) {// нет в секції Initialization output.touch = 1 ; // нет в секції Initialization fwGenAlertInterrupt (); // нет в секції Initialization} // нет в секції Initialization // Schedule execution next tick fwScheduleTask (1);

На малюнку 6 подань модельний варіант зв'язки сенсорної кнопки и модуля Mbee-DUAL. Малюнок 7 ілюструє роботу програми опитування ємнісний сенсорною кнопки: показаний фоновий рівень output.tdcL і піки його зростання в моменти дотику до сенсора. Спрацювання порога отраженно в графіку змінної output.touch: видно, що дрібні відхилення від фонового рівня успішно фільтруються.

touch: видно, що дрібні відхилення від фонового рівня успішно фільтруються

Мал. 6. Макетний варіант зв'язки сенсорної кнопки і модуля Mbee-DUAL

Макетний варіант зв'язки сенсорної кнопки і модуля Mbee-DUAL

Мал. 7. Тестування роботи сенсорної кнопки

Залишилося інтегрувати проект в rfWakeOnRadioTx.

Інтеграція сенсорної кнопки проект в rfWakeOnRadioTx

Включення в основний проект коду для SensorController досить просте завдання, яка займає всього кілька кроків. У SensorControllerStudio генеруємо набір вихідних файлів, який і буде внесено до проекту.

У файлі rfWakeOnRadioTx.c після підключення основних заголовків файлів (після рядки #include «smartrf_settings / smartrf_settings.h») додаємо підключення файлів SC і оголошуємо прототипи функцій обробників повідомлень від SC:

// +++++++++++++++ #include "scif.h" #define BV (n) (1 << (n)) #include "scif_framework.h" #include "scif_osal_tirtos. h "/ * +++ Prototypes ***** / static void ctrlReadyCallback (void); static void taskAlertCallback (void); // ++++++++++++++++++++++++++

Перед визначенням функції main додаємо функції-обробники повідомлень READY і ALERT від SensorController, а також функцію ініціалізації і запуску SensorController.

Оброблювач повідомлення READY буде порожнім, в даному проекті це повідомлення не генерується.

// ++++++++++ void scCtrlReadyCallback (void) {} ​​// scCtrlReadyCallback

Обробка повідомлення ALERT включає в себе зняття прапора переривання від SC, передачу повідомлення завданню txTask через семафор і повідомлення SC про успішну обробці його повідомлення:

void scTaskAlertCallback (void) {scifClearAlertIntSource (); Semaphore_post (txSemaphoreHandle); // Acknowledge the alert event scifAckAlertEvents (); }

Функція scTaskInit робить налаштування і запуск SC:

void scTaskInit () {// Ініціалізація SC // Налаштування оброблювачів scifOsalInit (); scifOsalRegisterCtrlReadyCallback (scCtrlReadyCallback); scifOsalRegisterTaskAlertCallback (scTaskAlertCallback); scifInit (& scifDriverSetup); // Налаштування частоти виклику функції опитування кнопки контролером SC // 0x00010000 відповідає 1 разу в секунду // Підбирається вручну для досягнення бажаної швидкості відгуку scifStartRtcTicksNow (0x00007000); scifStartTasksNbl (BV (SCIF_BUTTON_TASK_ID)); } // ++++++++++

У функцію main додається виклик функції ініціалізації SC:

... / * Initialize task * / txTaskInit (); // start SC task scTaskInit (); / * Start BIOS * / BIOS_start (); ...

Проект компілюється, і отриманий образ прошивається в вузол-вимикач. Тепер передачу пакета буде форматувати або дотик до сенсорної майданчику, або натискання кнопки. Середній струм споживання при цьому зріс лише на 17 ... 20 мкА.

Наближення до реальності

В якості найпростішого прикладу трохи модифікуємо основний код прикладів rfWakeOnRadioTx / Rx до мінімально корисної функціональності, такий як адресна передача і прийом пакетів і передача стану навантаження (викл / вкл). Для цього додамо в проекти змінні стану навантаження і її адресу.

Для цього в проекті rfWakeOnRadioTx поміщаємо перед визначеннями функції txTaskFunction оголошення наступних змінних:

uint8_t switch_state = 0; // Стан ключа: 0 - викл, що не 0 - вкл uint8_t addrL = 0x55; // Молодший байт адреси uint8_t addrH = 0x77; // Старший байт адреси #define Clock_tickPeriod ti_sysbios_knl_Clock_tickPeriod // Визначення для перекладу внутрішніх тиків в тимчасові інтервали

В основному робочому циклі функції txTaskFunction вводимо зміна і передачу змінної стану навантаження і замінюємо перемикання стану світлодіода індикації на його миготіння при відправці пакета:

... / * Enter main TX loop * / while (1) {// інвертовану стан змінної-ключа switch_state = ~ switch_state; RF_yield (rfHandle); // add / * Очікування натискання кнопки - обробник натискання кнопки посилає повідомлення в чергу завдання * / Semaphore_pend (txSemaphoreHandle, BIOS_WAIT_FOREVER); // Формуємо пакет даних packet [0] = PAYLOAD_LENGTH; // Довжина пакета packet [1] = (uint8_t) (seqNumber >> 8); // Порядковий номер packet [2] = (uint8_t) (seqNumber ++); packet [3] = addrL; // Молодший байт адреси packet [4] = addrH; // Старший байт адреси packet [5] = switch_state; // Стан ключа: початкове 0 - вимкнено / * Передаємо сформований пакет * / RF_runCmd (rfHandle, (RF_Op *) & RF_cmdPropTxAdv, RF_PriorityNormal, NULL, 0); // «блимати» світлодіодом індикації PIN_setOutputValue (ledPinHandle, Board_PIN_LED1, 1); // Запалюємо діод Task_sleep (50000 / Clock_tickPeriod); // Пауза 50 мс PIN_setOutputValue (ledPinHandle, Board_PIN_LED1, 0); // Гасимо діод // Повідомлення ядра SC про успішну обробці його переривання scifAckAlertEvents (); } ...

Аналогічні зміни проведемо і в проекті rfWakeOnRadioRx. Перед функцією rxTaskFunction визначимо змінні для зберігання стану навантаження / ключа, отриманого в пакеті адреси і адреси самого вузла:

uint8_t switch_state = 0; // Стан ключа uint8_t addrL = 0x55; // Молодший байт адреси вузла uint8_t addrH = 0x77; // Старший байт адреси вузла uint8_t RXaddrL = 0; // Молодший байт адреси, отриманого в пакеті uint8_t RXaddrH = 0; // Старший байт адреси, отриманого в пакеті

Весь аналіз пакету буде проводиться в функції callback, спричиненої в разі успішного прийняття пакету:

void callback (RF_Handle h, RF_CmdHandle ch, RF_EventMask e) {/ * Якщо пакет отриманий успішно і доступний для читання - переходимо до його аналізу * / if (e & RF_EventRxEntryDone) {do / * Беремо першу непрочитану запис з черги пакетів * / currentDataEntry = RFQueue_getDataEntry (); / * У даному прикладі обробляються тільки адреса одержувача і поточний бажаний стан ключа * / // Вважали молодшу і старшу частину адреси в прийнятому пакеті - відповідно 3-й і 4-й байти RXaddrL = * (uint8_t *) (& currentDataEntry-> data + 3); RXaddrH = * (uint8_t *) (& currentDataEntry-> data + 4); // Зчитується стан ключа switch_state = * (uint8_t *) (& currentDataEntry-> data + 5); // Проста перевірка на збіг адреси вузла і прийнятого адреси if ((RXaddrL == addrL) && (RXaddrH == addrH)) {// Зміна стану навантаження у відповідності з отриманим значенням PIN_setOutputValue (ledPinHandle, Board_PIN_LED1, switch_state); }; } While (RFQueue_nextEntry () == DATA_ENTRY_FINISHED); }}

Середній струм споживання вузла-вимикача складає близько 10 мкА, вузла-приймача 35 мкА. Звичайна ємність батарейки-таблетки 3 В розміру CR2032 - в районі 200 мА · год. При харчуванні наших вузлів від подібних батарейок отримаємо тривалість роботи 20000 (близько 2 років) і 5700 (8 місяців) годин для вузла-вимикача і вузла-приймача відповідно (при розрахунку не враховувався ток управління навантаженням в вузлі-приймачі).

Висновок

Бездротові РНК серії СС13хх є привабливими кандидатами для простих бездротових пристроїв з причини високої інтеграції різноманітних апаратних ресурсів і малого споживання. Додавання нового функціоналу в пристрої і системи на їх основі також реалізується досить просто завдяки можливості поділу завдань між ядрами, що входять до складу РНК.

Додатковою перевагою для серії СС1350 є можливість паралельно з роботою мережі управління транслювати стан вузлів в діапазоні 2400 МГц через широкомовні BLE-пакети, що дозволяє відображати ці дані на мобільних пристроях користувача - смартфонах, планшетах або ноутбуках.

Новости