Kincony KC868-A4: ультимативный гайд. Часть 2. Программирование компонентов / Хабр

Kincony KC868-A4: ультимативный гайд. Часть 2. Программирование компонентов / Хабр Лодки

Характеристики видеопередатчика, как выбрать и на что следует обращать внимание

Любой электронный компонент обладает рядом технических характеристик, на которые следует обращать внимание при выборе, это относится и к видеопередатчикам.

Далее мы рассмотрим 13 пунктов, которые учитывается при выборе этого важного компонента FPV системы квадрокоптера.

▍ buzzer и tone

Как я уже отметил ранее, плата Kincony KC868-A4 снабжена приятным дополнением в виде пьезоэлектрического излучателя. Он может помочь вам сделать удобное звуковое оповещение о различных состояниях (авария, какие-то события и т. д.) контроллера. Вот простой пример работы с пищалкой.

/*
  Kincony KC868-A4
  Buzzer example
*/

#define BUZZER_PIN 18

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 Buzzer example..."));
    
  pinMode(BUZZER_PIN, OUTPUT);
}

void loop() {
  digitalWrite(BUZZER_PIN, HIGH); delay(500);
  digitalWrite(BUZZER_PIN, LOW);  delay(500);
}

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

/*
  Kincony KC868-A4
  Buzzer Tone example
*/

#define BUZZER_PIN 18
const int TONE_PWM_CHANNEL = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 Buzzer Tone example..."));
  
  ledcAttachPin(BUZZER_PIN, TONE_PWM_CHANNEL);
}

void loop() {
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_C, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_D, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_E, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_F, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_G, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_A, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_B, 4); delay(500);
  ledcWriteNote(TONE_PWM_CHANNEL, NOTE_C, 5); delay(500);
}

▍ dac

Kincony KC868-A4 снабжён двумя цифро-аналоговыми преобразователями (DAC), которые могут формировать напряжение в диапазоне от 0 до 10 вольт. Это может пригодиться для управления различным оборудованием. Ниже приведён пример генерации постоянного напряжения 5 вольт на выходе DAC1 контроллера.

/*
  Kincony KC868-A4
  DAC example
*/

#define DAC1 26
#define DAC2 25

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 DAC example..."));
  
  int value = 127; // 255 = 10V
  dacWrite(DAC1, value);
}

void loop() {

}

Понятно, что генерация постоянного напряжения — это только небольшая область применения DAC, в основном востребована динамическая генерация (периодических) сигналов. Далее вы можете видеть пример кода для генерации пилообразного сигнала на выходе DAC1.

/*
  Kincony KC868-A4
  DAC Saw example
*/

#define DAC1 26
#define DAC2 25

byte value = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 DAC Saw example..."));
}

void saw() {
  value  ;
}

void loop() {
  dacWrite(DAC1, value);
  saw();
}

Небольшой модификацией этого кода вы можете добиться генерации сигналов контроллером Kincony KC868-A4 практически любой формы.

▍ аналоговые входы

Kincony KC868-A4 имеет 4 «аналоговых» входа, которые подключены на

GPIO 32333435

. Как уже было отмечено в первой статье, формированием уровней для сигналов 0–5 В и 4-20 мА занимаются входные каскады, которые формируют 2 входа для напряжения (GPIO 32 и 33) и 2 входа для тока (GPI 34 и 35). В коде работа с обоими типами входных сигналов не различается, она осуществляется функцией analogRead() с разрешением 4096.

/*
  Kincony KC868-A4
  Analog Input example
*/

#define ANALOG_PIN1 32 // INA1 0-5V
#define ANALOG_PIN2 33 // INA2 0-5V
#define ANALOG_PIN3 34 // INA3 4-20 mA
#define ANALOG_PIN4 35 // INA4 4-20 mA

int value1 = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 Analog Input example..."));
  pinMode(ANALOG_PIN1, INPUT);
}

void loop() {
  value1 = analogRead(ANALOG_PIN1); // 0-4096
  delay(1000);
  Serial.printf("Value on pin %d = %dn", ANALOG_PIN1, value1);
}

▍ датчики температуры и влажности


Kincony KC868-A4 имеет колодку

3VSGND

для подключения датчика температуры DS18B20. К этой колодке можно также подключить сеть из нескольких датчиков DS18B20, датчик влажности или любой другой датчик, подходящий по типу подключения. Нужно только помнить, что на плате уже установлена подтяжка линии данных к напряжению питания.

Для работы с датчиками температуры DS18B20 требуются библиотеки DS18B20 и OneWire. Ниже приведён код для одного датчика DS18B20, подключённого к плате KC868-A4.

/*
  Kincony KC868-A4
  DS18B20 example
*/

#include <DS18B20.h>

#define  LOW_ALARM 30
#define HIGH_ALARM 40

DS18B20 ds(13);

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 DS18B20 example..."));
  
  ds.doConversion();
  while (ds.selectNext()) {
    ds.setAlarms(LOW_ALARM, HIGH_ALARM);
  }
}

void loop() {
  ds.doConversion();

  while (ds.selectNextAlarm()) {
    Serial.print("Alarm Low: ");   Serial.print(ds.getAlarmLow());  Serial.println(" °C");
    Serial.print("Alarm High: ");  Serial.print(ds.getAlarmHigh()); Serial.println(" °C");
    Serial.print("Temperature: "); Serial.print(ds.getTempC());     Serial.println(" °Cn");
  }

  delay(2000);
}

В коде выставляются пороги срабатывания и, в случае выхода контролируемой температуры за определённые значения, в Serial выводится соответствующее сообщение.

Библиотека DS18B20 содержит множество примеров использования датчиков температуры DS18B20 на все случаи жизни — вы легко можете использовать их для своих проектов.

▍ инфракрасные (ir) приёмник и передатчик

Завершим мы обзор программных модулей Kincony KC868-A4 примером работы с приёмником (

GPIO 23

, IRD) и излучателем (

GPIO 22

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

Для работы с инфракрасными приёмником и передатчиком используется библиотека Arduino-IRremote. Рассмотрим пример, созданный на её основе. В этом тестовом скетче мы будем принимать инфракрасный сигнал от бытового пульта управления, идентифицировать этот сигнал (производителя оборудования, частоту сигнала, протокол управления, и код нажатой клавиши), а также посылать в эфир записанный сигнал, нажимая на функциональную клавишу контроллера Kincony KC868-A4.

Исходные данные:

Полный код скетча содержит 2 файла: основной (ir_example.ino) и файл с настройками (PinDefinitionsAndMore.h). В файле PinDefinitionsAndMore.h нужно изменить номера GPIO в соответствии с распиновкой контроллера Kincony KC868-A4 (строки с настройками помечены тремя восклицательными знаками).

#define LED_BUILTIN 12 // !!!
#define IR_RECEIVE_PIN       23  // !!!
#define IR_SEND_PIN          22  // !!!
#define APPLICATION_PIN      0   // !!!
Полный код файла PinDefinitionsAndMore.h

/*
 *  PinDefinitionsAndMore.h
 *
 *  Contains pin definitions for IRremote examples for various platforms
 *  as well as definitions for feedback LED and tone() and includes
 *
 *  Copyright (C) 2021  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 *  Arduino-IRremote is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

/*
 * Pin mapping table for different platforms
 *
 * Platform     IR input    IR output   Tone
 * -----------------------------------------
 * DEFAULT/AVR  2           3           4
 * ATtinyX5     0           4           3
 * ATtiny167    9           8           5 // Digispark pro number schema
 * ATtiny167    3           2           7
 * ATtiny3217   10          11          3 // TinyCore schema
 * ATtiny1604   2           PA5/3       %
 * SAMD21       3           4           5
 * ESP8266      14 // D5    12 // D6    %
 * ESP32        15          4           27
 * BluePill     PA6         PA7         PA3
 * APOLLO3      11          12          5
 */

#define LED_BUILTIN 12 // !!!
 
//#define _IR_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN          14 // D5
#define IR_RECEIVE_PIN_STRING   "D5"
#define IR_SEND_PIN             12 // D6 - D4/pin 2 is internal LED
#define IR_SEND_PIN_STRING      "D6"
#define _IR_TIMING_TEST_PIN     13 // D7
#define APPLICATION_PIN          0 // D3

#define tone(...) void()      // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN                42 // Dummy for examples using it


#elif defined(ESP32)
#include <Arduino.h>
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t _pin, unsigned int frequency){
    ledcAttachPin(_pin, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, frequency);
}
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration){
    ledcAttachPin(_pin, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, frequency);
    delay(duration);
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t _pin){
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#define IR_RECEIVE_PIN       23  // !!!
#define IR_SEND_PIN          22  // !!!
#define TONE_PIN                27  // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN      0   // !!!


#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN          PA6
#define IR_RECEIVE_PIN_STRING   "PA6"
#define IR_SEND_PIN             PA7
#define IR_SEND_PIN_STRING      "PA7"
#define TONE_PIN                PA3
#define _IR_TIMING_TEST_PIN      PA5
#define APPLICATION_PIN         PA2

#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program space and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN  0
#define IR_SEND_PIN     4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB  with pullup on Digispark board.
#define TONE_PIN        3
#define _IR_TIMING_TEST_PIN 3

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
#  if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IR_RECEIVE_PIN   9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN  14 // PB6 / INT0 is connected to USB  on DigisparkPro boards
#define IR_SEND_PIN      8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN         5 // PA7
#define _IR_TIMING_TEST_PIN 10 // PA4
#  else
#define IR_RECEIVE_PIN  3
#define IR_SEND_PIN     2
#define TONE_PIN        7
#  endif

#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program space
// Pin 6 is TX pin 7 is RX
#define IR_RECEIVE_PIN   3 // INT1
#define IR_SEND_PIN      4
#define TONE_PIN         9
#define _IR_TIMING_TEST_PIN 8

#elif defined(__AVR_ATtiny3217__)
#define IR_RECEIVE_PIN  10
#define IR_SEND_PIN     11
#define TONE_PIN         3
#define APPLICATION_PIN  5

#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN   2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN      3
#define APPLICATION_PIN  5

#define tone(...) void()      // Define as void, since TCB0_INT_vect is also used by tone()
#define noTone(a) void()
#define TONE_PIN        42 // Dummy for examples using it

#  elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) 
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) 
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) 
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) 
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) 
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) 
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) 
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN        13
#define TONE_PIN            4
#define APPLICATION_PIN     5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN  7

#elif defined(ARDUINO_ARCH_APOLLO3)
#define IR_RECEIVE_PIN  11
#define IR_SEND_PIN     12
#define TONE_PIN         5

#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN         3
#define TONE_PIN            4
#define APPLICATION_PIN     5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN  7

#elif defined(TEENSYDUINO)
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN         3
#define TONE_PIN            4
#define APPLICATION_PIN     5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN  7

#elif defined(__AVR__) // Default as for ATmega328 like on Uno, Nano etc.
#define IR_RECEIVE_PIN      2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN         3
#define TONE_PIN            4
#define APPLICATION_PIN     5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN  7

#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN         3
#define TONE_PIN            4
#define APPLICATION_PIN     5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN  7

// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB

// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are switched on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW

#elif defined (NRF51) // BBC micro:bit
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN         3
#define APPLICATION_PIN     1
#define _IR_TIMING_TEST_PIN  4

#define tone(...) void()    // no tone() available
#define noTone(a) void()
#define TONE_PIN           42 // Dummy for examples using it

#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN         3
#define TONE_PIN            4
#define APPLICATION_PIN     5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN  7
#endif // defined(ESP8266)

#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
/*
 * Helper macro for getting a macro definition as string
 */
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
Полный код файла ir_example.ino

/*
  Kincony KC868-A4
  IR example

 * ReceiveAndSend.cpp
 * 
 *
 * Record and play back last received IR signal at button press.
 * The logic is:
 * If the button is pressed, send the IR code.
 * If an IR code is received, record it.
 *
 * An example for simultaneous receiving and sending is in the UnitTest example.
 *
 * An IR detector/demodulator must be connected to the input IR_RECEIVE_PIN.
 *
 * A button must be connected between the input SEND_BUTTON_PIN and ground.
 * A visible LED can be connected to STATUS_PIN to provide status.
 *
 * Initially coded 2009 Ken Shirriff http://www.righto.com
 *
 *  This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 */
#include <Arduino.h>

/*
 * Define macros for input and output pin etc.
 */
#include "PinDefinitionsAndMore.h"

//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 900 bytes program space

#include <IRremote.hpp>

int SEND_BUTTON_PIN = APPLICATION_PIN;
int STATUS_PIN = LED_BUILTIN;

int DELAY_BETWEEN_REPEAT = 50;

// On the Zero and others we switch explicitly to SerialUSB
#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif

struct storedIRDataStruct { // Storage for the recorded code
  IRData receivedIRData;
  // extensions for sendRaw
  uint8_t rawCode[RAW_BUFFER_LENGTH]; // durations if raw
  uint8_t rawCodeLength;              // length of code
} sStoredIRData;

int lastButtonState;

void storeCode(IRData *aIRReceivedData);
void sendCode(storedIRDataStruct *aIRDataToSend);

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 IR example..."));
  
  // Just to know which program is running on my Arduino
  //Serial.println(F("START " __FILE__ " from " __DATE__ "rnUsing library version " VERSION_IRREMOTE));

  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver, enable feedback LED, take LED feedback pin from the internal boards definition
  IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin

  pinMode(STATUS_PIN, OUTPUT);

  /*
  Serial.print(F("Ready to receive IR signals of protocols: "));
  printActiveIRProtocols (&Serial);
  Serial.print(F("at pin "));
    
#if defined(ARDUINO_ARCH_STM32) || defined(ESP8266)
  Serial.println(IR_RECEIVE_PIN_STRING);
#else
  Serial.println(IR_RECEIVE_PIN);
#endif

  Serial.print(F("Ready to send IR signals at pin "));
#if defined(ARDUINO_ARCH_STM32) || defined(ESP8266)
  Serial.println(IR_SEND_PIN_STRING);
#else
  Serial.print(IR_SEND_PIN);
#endif
    
  Serial.print(F(" on press of button at pin "));
  Serial.println(SEND_BUTTON_PIN);

  Serial.print(F("LED_BUILTIN: ")); Serial.println(LED_BUILTIN);
  Serial.print(F("STATUS_PIN: ")); Serial.println(STATUS_PIN);
  Serial.print(F("TONE_PIN: ")); Serial.println(TONE_PIN);
  Serial.print(F("IR_RECEIVE_PIN: ")); Serial.println(IR_RECEIVE_PIN);
  Serial.print(F("IR_SEND_PIN: ")); Serial.println(IR_SEND_PIN);
  Serial.print(F("APPLICATION_PIN: ")); Serial.println(APPLICATION_PIN);
  */

} // setup

// Stores the code for later playback in sStoredIRData

void storeCode(IRData *aIRReceivedData) {
  if (aIRReceivedData->flags & IRDATA_FLAGS_IS_REPEAT)      {Serial.println(F("Ignore repeat")); return;}
  if (aIRReceivedData->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {Serial.println(F("Ignore autorepeat")); return;}
  if (aIRReceivedData->flags & IRDATA_FLAGS_PARITY_FAILED)  {Serial.println(F("Ignore parity error")); return;}

  sStoredIRData.receivedIRData = *aIRReceivedData; // Copy decoded data

  if (sStoredIRData.receivedIRData.protocol == UNKNOWN) {
    Serial.print(F("Received unknown code and store "));
    Serial.print(IrReceiver.decodedIRData.rawDataPtr->rawlen - 1);
    Serial.println(F(" timing entries as raw "));
    
    IrReceiver.printIRResultRawFormatted(&Serial, true); // output the results in RAW format
    
    sStoredIRData.rawCodeLength = IrReceiver.decodedIRData.rawDataPtr->rawlen - 1;
    IrReceiver.compensateAndStoreIRResultInArray(sStoredIRData.rawCode); // store current raw data in dedicated array for later usage
  } else {
    IrReceiver.printIRResultShort(&Serial);
    sStoredIRData.receivedIRData.flags = 0; // clear flags -esp. repeat- for later sending
    Serial.println();
  }
} // storeCode( )

void sendCode(storedIRDataStruct *aIRDataToSend) {
  if (aIRDataToSend->receivedIRData.protocol == UNKNOWN) { // raw
    IrSender.sendRaw(aIRDataToSend->rawCode, aIRDataToSend->rawCodeLength, 38); // 38 KHz
    Serial.print(F("Sent raw "));
    Serial.print(aIRDataToSend->rawCodeLength);
    Serial.println(F(" marks or spaces"));
  } else {
    IrSender.write(&aIRDataToSend->receivedIRData, NO_REPEATS); // write func switch for different protocols
    Serial.print(F("Sent: "));
    printIRResultShort(&Serial, &aIRDataToSend->receivedIRData);
  }
}

void loop() {
  int buttonState = digitalRead(SEND_BUTTON_PIN); // active LOW

  if (lastButtonState == LOW && buttonState == HIGH) {
    Serial.println(F("Button released"));
    IrReceiver.start(); // re-enable receiver
  }

  // Check for static button state

  if (buttonState == LOW) {
    IrReceiver.stop();
    
    // Button pressed send stored data or repeat
    Serial.println(F("Button pressed, now sending"));
    digitalWrite(STATUS_PIN, HIGH);
    if (lastButtonState == buttonState) {
      sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
    }
    sendCode(&sStoredIRData);
    digitalWrite(STATUS_PIN, LOW);
    delay(DELAY_BETWEEN_REPEAT); // Wait a bit between retransmissions
  } else if (IrReceiver.available()) { // Button is not pressed, check for incoming data
    storeCode(IrReceiver.read());
    IrReceiver.resume();
  }

  lastButtonState = buttonState;
} // loop

Смотрите про коптеры:  Кораблик для завоза прикормки: принцип действия, преимущества, топ-10 лучших корабликов для прикорма

▍ приёмник и передатчик на 433 мгц

Как вы уже знаете, в состав контроллера Kincony KC868-A4 входят модули приёмника и передатчика на 433 МГц. Эти модули могут быть использованы для управления различной техникой и приёма данных с датчиков, использующих диапазон 433 МГц для передачи своих сигналов.

Приёмник подключен на GPIO 19 контроллера, а передатчик на GPIO 21. Для работы с беспроводной передачей и приёмом данных используется популярная библиотека RC-Switch. Вот пример посылки данных и управляющих команд беспроводным модулем на 433 МГц контроллера Kincony KC868-A4.

/*
  Kincony KC868-A4
  433 Transmit example
 */

#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

#define DELAY_MS 500

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 433 Transmit example..."));
  
  mySwitch.enableTransmit(digitalPinToInterrupt(21));
}

void loop() {
  mySwitch.switchOn ("11111", "00010");      delay(DELAY_MS);
  mySwitch.switchOff("11111", "00010");      delay(DELAY_MS);
  mySwitch.send(5393, 24);                   delay(DELAY_MS);
  mySwitch.send("000000000001010100010001"); delay(DELAY_MS);
  mySwitch.sendTriState("00000FFF0F0F");     delay(DELAY_MS); 
}

Наглядная визуализация работы этого скетча в программе SDRSharp. Видны посылки в эфир данных контроллером каждые 500 миллисекунд.

Аналогичным образом вы можете использовать примеры приёма (GPIO 19) сигналов в диапазоне 433 МГц, идущие в составе библиотеки RC-Switch.

▍ программируем реле kc868-a4

Начнём мы конечно с управления реле, как с самого простого и востребованного функционала подобных контроллеров. Реле, как это видно на вышеприведённой схеме распиновки, подключены к

GPIO 21554

. Для примера управления реле контроллера Kincony KC868-A4 создадим скетч, который по очереди переключает реле, создавая эффект «бегущего огня».

/*
  Kincony KC868-A4
  Relays example
*/

byte pins[] = {2, 15, 5, 4};
byte pos = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 Relays example..."));

  pinMode(pins[0], OUTPUT);
  pinMode(pins[1], OUTPUT);
  pinMode(pins[2], OUTPUT);
  pinMode(pins[3], OUTPUT);
}

void clear() {
  digitalWrite(pins[0], LOW);
  digitalWrite(pins[1], LOW);
  digitalWrite(pins[2], LOW);
  digitalWrite(pins[3], LOW);
}

void change(byte n) {
  clear();
  digitalWrite(pins[n], HIGH);
}

void loop() {
  change(pos);
  Serial.print(F("ON Relay #")); Serial.println(pos);
  delay(10000);
  pos  ;
  if (pos > 3) {pos = 0;}
}

Этого примера вполне достаточно, чтобы вы на его основе могли реализовать любую логику управления реле контроллера Kincony KC868-A4. Вот результат вывода в Serial нашего тестового скетча:

Смотрите про коптеры:  Боремся с депрессией: 10 современных препаратов

▍ программная среда для kc868-a4

Программировать контроллер Kincony KC868-A4 можно в любой подходящей для этого среде — вы можете использовать для этого вашу любимую IDE, я же буду приводить примеры для среды Arduino 1.8.5. При этом предполагается, что вы обладаете необходимой квалификацией и знакомы с работой в Arduino IDE и умеете программировать микроконтроллер ESP32.

Для работы с Kincony KC868-A4, из всего списка поддерживаемых контроллеров вам нужно выбрать вариант «NodeMCU-32S». Это прозрачно намекает на то, что Kincony KC868-A4 является расширенной и дополненной различной периферией версией NodeMCU-32S.

Остальные настройки видны на скриншоте, вам нужно выставить у себя такие же (кроме номера порта, который у вас будет своим). Теперь переходим к разбору примеров программирования функциональных блоков контроллера Kincony KC868-A4.

▍ распиновка kc868-a4

Микроконтроллер ESP32 всем хорош, но есть у него один врождённый недостаток — крайне малое число свободных GPIO контактов. И каждый, кто хочет спроектировать контроллер на ESP32 или хотя бы просто применить его в своём более-менее развитом проекте, вынужден каким-то образом решать эту проблему.

Приходится либо применять расширители портов, либо пытаться как-то «вместить невмещаемое» и пытаться по крохам распределять имеющиеся GPIO и отказываться от тех или иных компонентов, которые могли бы быть установлены на плату.

Инженеры компании Kincony так и сделали — постарались подобрать набор из, на их взгляд, наиболее востребованных компонентов (функциональных блоков), куда вошли:

Этот набор забрал все свободные GPIO контроллера ESP32, больше не осталось ни одного контакта, к которому вы могли бы подключить что-то своё. Например, индикатор, который не помешал бы любому контроллеру.

Но глядя на то, что инженеры Kincony установили на плату KC868-A4, можно сказать, что у них получилось довольно сбалансированное решение для небольших проектов и целей обучения программированию микроконтроллеров.

Проблема заключается в том, что если вы захотите подключить какую-то свою деталь или модуль к KC868-A4, то без паяльника и соответствующей квалификации у вас ничего не получится — свободных для подключения GPIO просто нет.

С другой стороны, идеология подобных контроллеров и не предусматривает подобных вольностей со стороны пользователей — вы покупаете готовое решение и просто используете тот набор возможностей, которое оно предоставляет.

Итак, ниже представлено сочинение инженеров компании Kincony на тему «Как я распределил GPIO контакты ESP32», записанное мной в виде таблицы. В ближних к контроллеру столбцах указаны обозначения линий и подключений из принципиальной схемы (см. предыдущую статью), а в дальних — входы и выходы функциональных блоков контроллера KC868-A4.

В целом неплохо, основным достоинством такого расклада GPIO я бы назвал то, что всё это реально работает и не мешает друг другу.

Если бы проектированием Kincony KC868-A4 занимался я, то я бы в первую очередь избавился от подключения беспроводных модулей на 433 МГц, как архаичного, в пользу чего-нибудь более современного, типа nRF24 или LoRa, вывел бы контакты для подключения оборудования по I2C и SPI и повесил бы цифровые входы/выходы на расширители портов.

С распределением GPIO контактов ESP32 всё более-менее понятно и теперь, вооружившись этой информацией, давайте приступим к собственно программированию отдельных функциональных блоков Kincony KC868-A4 и начнём мы с программной среды.

▍ цифровые входы

Контроллер Kincony KC868-A4 имеет 4 опторазвязанных цифровых входа «сухой контакт», которые подключены на

GPIO 36392714

. Обслуживание этих входов предельно просто и осуществляется практически одной функцией digitalRead() — вы получаете текущее состояние любого из входов контроллера и далее используете его в коде по своему усмотрению.

/*
  Kincony KC868-A4
  Digital Input example
*/

#define INPUT_PIN1 36
#define INPUT_PIN2 39
#define INPUT_PIN3 27
#define INPUT_PIN4 14

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start Kincony KC868-A4 Digital Input example..."));
  pinMode(INPUT_PIN1, INPUT);
}

void loop() {
  Serial.println(digitalRead(INPUT_PIN1));
  delay(10);
}

Pit mode (режим)

Используется в основном на соревнованиях. При активации мощность видеопередатчика снижается до 0.5mW, с целью поменять канал и не мешать своим эфиром другим пилотам. Очень нужна функция. Вам придется держать очки или шлем близко к квадркоптеру. После смены канала, PIT режим отключается и мощность восстанавливается.

Смотрите про коптеры:  Регистрация новых устройств - StarLine E96

Встроенный микрофон

На многих видеопередатчиках стали устанавливать микрофоны, они используются для того, чтобы слышать звук работы двигателей. Профессиональные пилоты говорят, что это помогает лучше контролировать квадрокоптер.

Для любителей и начинающих не считаю нужным тратить лишние деньги на микрофон.

Выходная мощность

Выходная мощность — это определение, сколько энергии излучает видеопередатчик в процессе работы. Большая мощность означает бОльшую дальность, но сопровождается «побочными эффектами» — создаются помехи другим пилотам, который будут летать с вами.

Большинство видеопередатчиков имеют мощность:

25mW — это идеальная мощность для полетов в помещении и для гонок. При хорошей настройке и правильной установке антенны, такая мощность будет достаточной для полетов на любой гоночной трассе FPV.

200mW — это золотая середина. На этой мощности значительно увеличивается дальность полета и вы сможете высоко взлетать и отлетать на значительные расстояния.

400mW — Довольно большая мощность, используется для дальних полетов.

600mW — это уже слишком много и создает помехи другим устройствам, не рекомендуется использовать такую мощность.

Все современные видеопередатчики имеют возможность регулировать выходную мощность сигнала, это позволяет удобно использовать дрон в помещении, выставив ему мощность в 25mW и на улице на дальние дистанции на 200 или 400mW. Стоит учитывать, что чем выше мощность, тем быстрее разряжается аккумулятор, так как возрастает электропотребление.

Читатели нашего сайта со всего мира, поэтому есть один нюанс насчет мощности видеопередатчиков — в Европе запрещено использовать мощность более 25mW, а в России как таковых надзорных органов нет, за исключением полетов около аэропортов и режимных объектов. В США требуется получить лицензию HAM.

Где используются частоты 1.3mhz, 900mhz и 433mhz?

Такие частоты используются для использования квадрокоптеров и самолетов дальнего радиуса действия и используются специальные устройства, например, TBS Crossfire. Благодаря использованию низких частот, значительно увеличивается диапазон, так как сигнал с длинными волнами хорошо проходит через препятствия, такие как деревья, постройки и так далее.

Видео, которое передается по такой частоте, значительно хуже по качестве, чем более в более высоких частота — это обусловленно тем, что такая частота несет в себе меньше данных.

Как подключить видеопередатчик для квадрокоптера к fpv камере

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

Такая схема позволит минимизировать появления помех от работы контроллера и передатчика.

Если же ваш видеопередатчик квадратного форм-фактора, то достаточно будет просто скрутить провода спиралью.

Корпус

Большинство видеопередатчиков просто обтянуты термоусадкой и ничем не защищены, потому что обычно расположены внутри корпуса рамы. Если вам нужна дополнительная защита, то продаются видеопередатчики в алюминиевом или пластиковом корпусах, но они тяжелее.

Механизм переключения каналов

Есть 4 механизма переключения между каналов:

  • DIP (механическая крутилка);
  • Кнопка с дисплеем;
  • Инфракрасным пультом;
  • Через OSD.

DIP уже устарел и используется только в старых видеопередатчиках.

Кнопка с дисплеем — сейчас самый популярный вариант, просто нажимаете в определенном порядке кнопку и на дисплее будет меняться канал, например, 2-B, 3-A и так далее. Нельзя использовать на соревнованиях, так как идет перебор всех каналов и вы можете перехватить канал другого пилота или он ваш канал.

Инфракрасный пульт — очень удобная штука и используется на соревнованиях, так как можно выбрать сразу нужный канал, без перебора.

OSD (SmartAudio, Tramp Telemetry) — канал тоже выбирается сразу без необходимости перебора. Выбор производится через меню на дисплее очков или шлема. Функция крутая и набирает популярность.

Напряжение

Некоторые видеопередатчики требуют определенный диапазон напряжения, поэтому при выборе учитывайте этот параметр. Например, многие видеопередатчики имеют большой диапазон входного напряжения — от 7 до 24V, поэтому можно не беспокоиться и использовать в качестве источника питания прямое соединение к аккумулятору LiPo 2-6S.

На плате разводки питания есть контакты с 5V, но на 5V работать видеопередатчик FPV не будет, так как это очень ресурсоемкий компонент, требующий большого напряжения.

Для микро-квадрокоптеров продаются специальные видеопередатчики с низким напряжением, менее 7V.

Поддержка каналов

Все современные видеопередатчики поддерживают каналы, обычно их 40.

Что такое канал видеопередатчика? Это часть одной и той же частоты, но поделенная на равные промежутки этой частоты, чтобы была возможность использовать их другим пилотам, в итоге на гонках могут летать сразу 40 и более пилотов, при этом, каждый будет использовать частоту 5.8G, но у каждого будет свой «кусок» сигнала. Канал в большинстве видеопередатчиков отображается на маленьком экране.

Размер и вес

Размер определяется наличием свободного места в раме, как это написано выше и часто производители делают не очень компактные видеопередатчики, поэтому сравнивайте размеры с местом, которое есть в вашей раме.

Вес тоже имеет значение и чем он меньше, тем лучше. Сравните 2-3-4-5 похожих видеопередатчика и купите самый легкий.

Разъем для антенны

Разъемов для антенн много, но самые популярные это:

Совместимость

Хитрые продавцы и производители видеопередатчиков могут писать что-то вроде «совместим с FatShark», не ведитесь на это, так как совместимость определяется только частотой, на которой вещает видеопередатчик FPV, а это всего лишь уловка.

Форм-фактор. размер

Современные видеопередатчики имеют такую же форму, как и приемники, но сейчас чаще стали продаваться видеопередатчики квадратной формы и устанавливаются над полетным контроллером башней. Какой лучше выбрать? Это зависит от рамы, если рама вашего дрона длинная, то берите обычный, а если высокая и короткая — то лучше взять квадратный форм-фактор (30*30).

▍ заключение

Во второй статье цикла мы рассмотрели «атомарные» примеры программирования различных функциональных блоков контроллера Kincony KC868-A4. Используя эту информацию, вы можете легко начать программировать контроллер под свои задачи — всё расписано «от и до»: фото, схемы, распиновка, примеры кода, ссылки на библиотеки, скриншоты, пояснения и т. д.

В следующей статье мы рассмотрим более сложные примеры работы с KC868-A4, такие, как работа с беспроводной Wi-Fi частью и удалённое управление контроллером через интернет при помощи мессенджеров Telegram и/или Whatsapp.

Оцените статью
Радиокоптер.ру
Добавить комментарий

Adblock
detector