ARDUINO Arduino SEGA game pad nrf24l01 для RC моделей.

Nick

✩✩✩✩✩✩✩
1 Авг 2018
38
5
Код машинки

C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9, 10);

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ (видны всей программе)
uint16_t rx_mask = 0;
uint32_t last_signal_time = 0;
bool light_state = false;                            // Хранит состояние света
bool x_was_pressed = false;                          // Хранит предыдущее состояние кнопки X
int gear = 5;                                        // По умолчанию максимальная скорость
int gear_speeds[] = { 0, 110, 145, 180, 215, 255 };  // Значения ШИМ для передач 0..5
bool c_was_pressed = false;

void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  radio.begin();
  radio.setChannel(102);  // Уходим на чистую частоту 2502 МГц
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MAX);
  // Настройки подтверждения (делаем ДО startListening)
  radio.setAutoAck(true);
  radio.setRetries(5, 15);
  radio.enableDynamicPayloads();  // Помогает при помехах
  radio.openReadingPipe(1, 0x0123456789LL);
  radio.startListening();  // Включаем приём в самом конце
}

void loop() {

  // 1. ПРОВЕРКА ПАКЕТОВ (Максимально быстро)
  if (radio.available()) {
    radio.read(&rx_mask, sizeof(rx_mask));
    last_signal_time = millis();
  }

  // 2. ПОТЕРЯ СИГНАЛА
  if (millis() - last_signal_time > 500) {
    rx_mask = 0;
    if (!light_state) {  // Если свет был выключен, включаем как аварийку
      light_state = true;
      digitalWrite(7, HIGH);
    }
  }

  // 3. ИСПОЛНЕНИЕ КОМАНД
  bool c_now_pressed = (rx_mask & (1 << 5));  // Кнопка C (бит 5)
  if (c_now_pressed && !c_was_pressed) {
    gear++;
    if (gear > 5) gear = 0;  // Сбрасываем на 0 передачу (стоп) после 5-й
  }
  c_was_pressed = c_now_pressed;

  // Текущая скорость из массива в зависимости от передачи
  int current_speed = gear_speeds[gear];

  // ИСПОЛНЕНИЕ КОМАНД С ШИМ (Пины 5 и 6)
  // Движение НАЗАД (Пин 6)
  if (rx_mask & (1 << 6)) {  // Нажата А
    digitalWrite(5, LOW);
    analogWrite(6, current_speed);
  }
  // Движение ВПЕРЁД (Пин 5)
  else if (rx_mask & (1 << 4)) {  // Нажата B
    digitalWrite(6, LOW);
    analogWrite(5, current_speed);
  }
  // Если ничего не нажато — стоп
  else {
    analogWrite(5, 0);
    analogWrite(6, 0);
  }
  // прямые команды
  digitalWrite(3, (rx_mask & (1 << 2)) ? HIGH : LOW);  // LEFT
  digitalWrite(2, (rx_mask & (1 << 3)) ? HIGH : LOW);  // RIGHT

  // 4. ЛОГИКА СВЕТА
  bool x_now_pressed = (rx_mask & (1 << 8));
  if (x_now_pressed && !x_was_pressed) {
    light_state = !light_state;
    digitalWrite(7, light_state ? HIGH : LOW);
  }
  x_was_pressed = x_now_pressed;
  // 5. ОТЛАДКА (Выводим только при реальных изменениях, чтобы не забивать шину)
  static uint16_t prev_rx_mask = 0;
}