Перейти к содержимому


Фотография

Наземная FPV станция на Arduino

наземная станция arduino

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 15

#1 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 28 Сентябрь 2013 - 14:00

Всем привет! Начал работу над проектом наземной станции для 2 приемников 5.8Ghz на Arduino UNO.
У меня есть 2 антенны Cloverleaf и Helix для 5.8Ghz, приемник пока один, второй закажу на днях.
В электронике я не шибко силен, но кое-что могу.

Цели:
1, Сделать переключатель видео в зависимости от RSSI с возможностью подключать до 5 приемников.
2. Сделать трэккер антены, который будет корректировать антенну по GPS данным полученым по аудио-каналу


RSSI пин в приемниках RC-305:
http://www.youtube.com/watch?v=gbHtsmiHX3A

Сейчас 1я цель завершена на 70%.
По железу осталось приобрести 2й приемник, приобрести мультиплексор и Arduino Mini, нарисовать и вытравить монтажную плату.
По программированию осталось: дописать калибровку, пищать при RSSI < определенного процента, и посылать команду на переключение мультиплексору.
Все будет в дребезги, а пульт останется....

#2 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 28 Сентябрь 2013 - 14:50

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


Все будет в дребезги, а пульт останется....

#3 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 28 Сентябрь 2013 - 15:00

Кому интересно вот код:

/*
RSSI SWITCHER FOR 5.8Ghz VIDEO RECIVERS
Coded by ShadoW (c) 2013
*/
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
float main_DSP = false;
// Входы RSSI
const int rssi_in[] = {A0, A1, A2, A3, A4};
int in_count = 5;
// Переменные RSSI
int rssi[]	 = {0, 0, 0, 0, 0};
int rssiMin[]  = {0, 0, 0, 0, 0};
int rssiMax[]  = {0, 0, 0, 0, 0};
int current_RX = 0;
int low_RSSI   = 0;
// Пищалка
const int buz_pin = 13;
// Кнопка
const int btn_pin = 12;
// Подсветка
const int backlight_pin = 11;
int backlight_state = LOW;
// Дебаг
const boolean debug = true;
// ИНИАЦИАЛИЗАЦИЯ
void setup()
{
  // Конфигурируем выходы
  pinMode(buz_pin, OUTPUT);
  pinMode(btn_pin, INPUT);
  digitalWrite(btn_pin, HIGH); // подтягивающие к +5в внутренний резистор
  pinMode(backlight_pin, OUTPUT);
  digitalWrite(backlight_pin, backlight_state);

  // Создаем serial подключение
  if (debug) Serial.begin(9600);

  // Настраиваем дисплей
  lcd.begin(16, 2);
  // Загрузить данные из EEPROM
  loadData();

  // Проверяем данные
  if (in_count > 5) in_count = 5;
  for(int i=0; i < 5; i++)
  {
	rssiMin[i] = constrain(rssiMin[i], 0, 1023);
	rssiMax[i] = constrain(rssiMax[i], 0, 1023);
  }

  // Стартуем
  if (debug) Serial.println("Starting...");
  lcd.print("Starting");
  for (int i=0; i < 8; i++)
  {
	lcd.print(".");
	delay(150);
  
	// Калибровка ?
	if (digitalRead(btn_pin) == LOW)
	{
	  Calibration();
	  break;
	}
  }
  beep(70, 3);
  // Очищаем дисплей
  lcd.clear();
}
// ОСНОВНОЙ ЦИКЛ
void loop()
{
  // Таймер синхронизцаии
  // unsigned long current_timer = millis();

  getRSSI();		   // Читаем и высчитываем RSSI
  int best_RX = getBestRX();
  //selectRX(bestRX); // Переключаемся на лучший

  showRSSI(best_RX);
  // Небольшая задержка
  delay(1000);
}
// Загрузка данных с EEPROM
void loadData()
{
   // Дебаг
  if (debug)
  {
	Serial.println("Reading EEPROM...");
	lcd.clear();
	lcd.print("Read EEPROM");
	delay(2000);
	lcd.clear();
  }

  // EEPROM адрес
  int addr = 0;

  // Количество портов
  in_count = EEPROM.read(addr);
  addr++;

  // Минимальные RSSI
  for (int i=0; i < 5; i++)
  {
	rssiMin[i] = EEPROM.read(addr);
	addr++;
	rssiMin[i] = rssiMin[i] + (EEPROM.read(addr)*255);
	addr++;
  }

  // Максимальные RSSI
  for (int i=0; i < 5; i++)
  {
	rssiMax[i] = EEPROM.read(addr);
	addr++;
	rssiMax[i] = rssiMax[i] + (EEPROM.read(addr)*255);
	addr++;
  }
}
// Сохранение в EEPORM
void saveData()
{
  // Дебаг
  if (debug)
  {
	Serial.println("Saving data to EEPROM...");
	lcd.clear();
	lcd.print("Save to EEPROM");
	delay(2000);
	lcd.clear();
  }

  // EEPROM адрес
  int addr = 0;

  // Количество портов
  EEPROM.write(addr, in_count);
  addr++;

  // Минимальные RSSI
  for (int i=0; i < 5; i++)
  {
	EEPROM.write(addr, lowByte(rssiMin[i]));
	addr++;
	EEPROM.write(addr, highByte(rssiMin[i]));
	addr++;
  }

  // Максимальные RSSI
  for (int i=0; i < 5; i++)
  {
	EEPROM.write(addr, lowByte(rssiMax[i]));
	addr++;
	EEPROM.write(addr, highByte(rssiMax[i]));
	addr++;
  }
}
// Пищание
void beep(int length, int count)
{
  for(int i=0; i < count; i++)
  {
	digitalWrite(buz_pin, HIGH);
	delay(length);
	digitalWrite(buz_pin, LOW);
	if (i < (count-1)) delay(length);
  }
}
// Получение RSSI и вычисление в процентах
void getRSSI()
{
  for (int i=0; i < in_count; i++)
  {
	rssi[i] = analogRead(i);
  
	// Приемник отключился
	if (rssi[i] < rssiMin[i]) rssi[i] = rssiMin[i];

	// Подгоняем под лимиты
	rssi[i] = constrain(rssi[i], rssiMin[i], rssiMax[i]);
  
	// Преобразуем в процениты
	rssi[i] = constrain(map(rssi[i], rssiMin[i], rssiMax[i], 0, 100), 0, 100);
  
	// Дебаг
	if (debug) Serial.println(String("RSSI "+String((i + 1), DEC)+": "+String(rssi[i])+"%"));

	// Небольшая задержка для analogRead
	delay(50);
  }
}
// Вычисление максимального RSSI
int getBestRX()
{
  int tmp_best_RSSI	= 0;
  int tmp_best_RX	  = 0;
  for (int i=0; i < in_count; i++)
  {
	if (rssi[i] > tmp_best_RSSI)
	{
	  tmp_best_RSSI = rssi[i];
	  tmp_best_RX   = i;
	}
  }

  return tmp_best_RX;
}
// Выбор приемника
void selectRX(int RX)
{
  if (debug)
  {
	lcd.clear();
	if (RX != current_RX) lcd.print(String("Switching RX: "+String(RX, DEC)));
	else lcd.print(String("RX not changed: "+String(current_RX, DEC)));
  }

  // Переключение приемника
  if (RX != current_RX)
  {
	// Тут код мультиплексора
  
	// Пикаем
	beep(70, RX);
  }
}
// Вывод данных на дисплей
void showRSSI(int RX)
{
  // Дебаг
  if (debug) Serial.println(String("Best RSSI: "+String(rssi[RX], DEC)+"% on RX: "+String((RX + 1), DEC)+"\n-----------------------------"));

  // Экран не очищался
  if (!main_DSP)
  {
	main_DSP = true;
  
	lcd.clear();
	lcd.print(String("Best RSSI: "+String(rssi[RX], DEC)+"%   "));
	lcd.setCursor(0, 1);
	lcd.print(String("RX: "+String((RX + 1), DEC)));
  }
  else
  {
	lcd.setCursor(11, 0);
	lcd.print(String(String(rssi[RX], DEC)+"%   "));
	lcd.setCursor(4, 1);
	lcd.print(String((RX + 1)));
  }
}
// Калибровка
void Calibration()
{
  // Дебаг
  if (debug) Serial.println("[ CALIBRATION ]");

  // Калибровка минимальных значений
  beep(70, 1);
  if (debug) Serial.println("Switch off TX and press button");
  lcd.clear();
  lcd.print("Switch off TX");
  lcd.setCursor(0, 1);
  lcd.print("and press button");
  delay(2000);
  while(digitalRead(btn_pin) == HIGH);
  beep(70, 1);
  if (debug) Serial.println("Scaning low RSSI values...");
  lcd.clear();
  lcd.print("Scaning low RSSI");
  lcd.setCursor(0, 1);
  lcd.print("Please wait...");
  for(int n=0; n < 50; n++)
  {
	for(int i=0; i < 5; i++)
	{
	  int tmpRSSI = analogRead(i);
	  if (tmpRSSI < rssiMin[i]) rssiMin[i] = tmpRSSI;
	  delay(150);
	}
  }
  // Дебаг
  if (debug)
  {
	for (int i=0; i < 5; i++) Serial.println(String("Min RSSI "+String((i + 1), DEC)+": "+String(rssiMin[i], DEC)+" [raw]"));
  }

  // Калибровка максимальных значений
  beep(70, 2);
  if (debug) Serial.println("Switch on TX and press button");
  lcd.clear();
  lcd.print("Switch on TX");
  lcd.setCursor(0, 1);
  lcd.print("and press button");
  delay(2000);
  while(digitalRead(btn_pin) == HIGH);
  beep(70, 1);
  if (debug) Serial.println("Scaning high RSSI values...");
  lcd.clear();
  lcd.print("Scaning hig RSSI");
  lcd.setCursor(0, 1);
  lcd.print("Please wait...");
  for(int n=0; n < 50; n++)
  {
	for(int i=0; i < 5; i++)
	{
	  int tmpRSSI = analogRead(i);
	  if (tmpRSSI > rssiMax[i]) rssiMax[i] = tmpRSSI;
	  delay(150);
	}
  }
  // Дебаг
  if (debug)
  {
	for (int i=0; i < 5; i++) Serial.println(String("Max RSSI "+String((i + 1), DEC)+": "+String(rssiMax[i], DEC)+" [raw]"));
  }

  // Вычеслить на каких портах есть RSSI а на каких нет

  // Сохраняем всё в EEPORM
  saveData();
}

Все будет в дребезги, а пульт останется....

#4 Necromant

Necromant

    Опытный пилот

  • Администраторы
  • 573 сообщений
  • ГородАлматы

Отправлено 29 Сентябрь 2013 - 22:50

Это ты хорошо придумал тут выложить, дело полезное :-)
Fly over the clouds...

#5 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 30 Сентябрь 2013 - 02:55

Arduino может многое! Систему хочу дополнить цветным дисплеем 1.8 дюйма SPI и microSD рид/врайтером для логов (в дальнейшем пригодится если до трэкера дело дойдет).
Вот присмотрел на ебэе: http://www.ebay.com/...=item1e6c0f0000
Меньше проводов, а то текущий дисплей занимает очень много портов, которые можно использовать для других нужд.
В качестве переключателя видео хочу заюзать мультиплексор 74HC4051 т.к. MAX микрухи для видео-свитчинга очень дорогие.
Все будет в дребезги, а пульт останется....

#6 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 30 Сентябрь 2013 - 03:14

Насчет второй цели есть идея:
Для телеметрии можно использовать двухстороннюю связь FrSky.
Причем как вариант коплекта: ArduPilot (или Crius AIO 1/2) + MinimOSD + Arduino Nano (как декодер Mavlink протокола и вытаскиватель данных GPS) + FrSky (в качестве телметрии) + кабель от FrSky к ардуино станции (или 2 блютуз модуля дороже но без проводов но тут как вариант небольшие помехи т.к. FrSky и блютуз на одной частоте 2.4 работают)
Можно еще круче. Сделать мост PPM модуль FrSky будет тоже на наземной станции подключен к головному ардуино проводом а передачу на него организовать спомощь комплекта OrangeLRS и PPMSUM. )))) Бредово немного т.к. в любом случае пилот будет рядом с наземкой )
Минус данной системы в том что обратня связь с FrSky работает хуже если использовать бустер.
Все будет в дребезги, а пульт останется....

#7 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 18 Ноябрь 2013 - 11:07

Вобщем идея подключить цветной дисплей с SD была не удачной, функционал занимает очень много памяти в ATmega 328.
Отложил цветной для другого проекта на Arduino Mega 2560.
Решил остаться на монохромном дисплее, только заказал 20x4 (4х-строчный) дисплей, т.к. реализовал диверсити на 4 ресивера.

Цветной LCD 1.8'
arduino_with_lcd.jpg

Переношу на монтажку.
arduino_diversity.jpg
Все будет в дребезги, а пульт останется....

#8 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 19 Ноябрь 2013 - 20:42

Вот такая штука получилась :)

IMAG0084_1.jpg IMAG0086_1.jpg

Дисплей как прийдет подключю через I2C, для этого сделал специальные коннекторы на A4,A5 и +5v,GND

Beta-версия кода:

/*
RSSI SWITCHER FOR 5.8Ghz VIDEO RECIVERS
Coded by ShadoW (c) 2013
*/
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// DEBUG
#define debug true
// Connecting LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Button
#define btnPin 2
// Buzzer
#define buzPin 3
// Analog RSSI inputs
#define rssi_in {A0, A1, A2, A3}
#define in_count 2 // Receivers 2-4
// RSSI values
int rssi[]	 = {0, 0, 0, 0};
int rssiMin[]  = {0, 0, 0, 0};
int rssiMax[]  = {0, 0, 0, 0};
int current_RX = 0;
int best_RX	= 0;
#define low_RSSI  40
#define min_range 100
// SETIUP
void setup()
{
  // Configure inputs
  pinMode(buzPin, OUTPUT);
  pinMode(btnPin, INPUT_PULLUP); // internal pullup  +5
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);

  // Serial for debug
  if (debug) Serial.begin(9600);

  // Load last data from EEPROM
  if (debug) Serial.println("Loading data from EEPROM");
  loadData();

  // Parse EEPROM data
  for(int i=0; i<in_count; i++)
  {
	if (debug) Serial.println(String("EEPROM RX"+String((i+1), DEC)+": "+String(rssiMin[i], DEC)+" - "+String(rssiMax[i], DEC)));
	rssiMin[i] = constrain(rssiMin[i], 0, 1023);
	rssiMax[i] = constrain(rssiMax[i], 0, 1023);
  }

  // TEST PORTS
  /*for(int n=1; n<=1000; n++)
  {
	for(int i=0; i<in_count; i++)
	{
	   Serial.println(String("TEST RX"+String((i+1), DEC)+": "+String(analogRead(i), DEC)));
	   delay(150);
	}
	Serial.println("------------------");
	delay(1000);
  }*/

  // Start LCD
  lcd.begin();

  // Starting...
  lcd.clear();
  lcd.print("Starting");
  if (debug) Serial.print("Starting");
  for (int i=0; i<5; i++)
  {
	lcd.print(".");
	if (debug) Serial.print(".");
	delay(300);
  
	// Calibration?
	if (digitalRead(btnPin) == LOW)
	{
	  Calibration();
	  break;
	}
  }
  // Clear display
  lcd.clear();
  if (debug) Serial.println();

  beep(500,1);
}
// LOOP
void loop()
{
  // Getting current RSSI values
  getRSSI();		  
  // Selecting RX with best signal
  setBestRX();
  // Show on LCD
  drawRSSI();

  // Small delay
  delay(500);
}
// Beep function
void beep(int length, int count)
{
  for(int i=0; i < count; i++)
  {
	digitalWrite(buzPin, HIGH);
	delay(length);
	digitalWrite(buzPin, LOW);
	if (i < (count-1)) delay(length);
  }
}
// Get RSSI values in percents
void getRSSI()
{
  for (int i=0; i<in_count; i++)
  {
	rssi[i] = analogRead(i);
  
	// Reciver disconected
	if (rssi[i] < rssiMin[i]) rssi[i] = rssiMin[i];

	// Constraining values
	rssi[i] = constrain(rssi[i], rssiMin[i], rssiMax[i]);
  
	// Convert to percents
	rssi[i] = constrain(map(rssi[i], rssiMin[i], rssiMax[i], 0, 100), 0, 100);
  }
}
// Selecting best RX
void setBestRX()
{
  int tmp_best_RSSI	= 0;
  int tmp_best_RX	  = 0;
  for (int i=0; i<in_count; i++)
  {
	if (rssi[i] > tmp_best_RSSI)
	{
	  tmp_best_RSSI = rssi[i];
	  tmp_best_RX   = i;
	}
  }

  // LOW RSSI percent BEEP for INFORM
  //if (tmp_best_RSSI < low_RSSI) beep(1000, 2);

  best_RX = tmp_best_RX;

  // Switching
  if (best_RX != current_RX)
  {
	if (debug) Serial.println(String("Switching to RX-"+String((best_RX + 1), DEC)));
  
	// Send address to multiplexor
	switch(best_RX)
	{
	  // RX-1
	  case 0:  
	   digitalWrite(6, LOW);
	   digitalWrite(5, HIGH);
	   digitalWrite(4, LOW);
	  break;
	
	  // RX-2
	  case 1:
	   digitalWrite(6, LOW);
	   digitalWrite(5, LOW);
	   digitalWrite(4, HIGH);
	  break;
	
	  // RX-3
	  case 2:
	   digitalWrite(6, LOW);
	   digitalWrite(5, HIGH);
	   digitalWrite(4, HIGH);
	  break;
	
	  // RX-4
	  case 3:
	   digitalWrite(6, LOW);
	   digitalWrite(5, LOW);
	   digitalWrite(4, LOW);
	  break;
	}
  
	// Saving to current RX
	current_RX = best_RX;
  
	// Beeps count of current RX
	beep(70, (best_RX+1));
  
	// Small delay
	delay(500);
  }
}
// Show data on display
void drawRSSI()
{
  lcd.setCursor(0,0);
  for (int i=0; i<in_count; i++)
  {
	lcd.print(String("RX"+String((i+1), DEC)+": "+String(rssi[1], DEC)+"%  "));
	if (debug) Serial.println(String("RX"+String((i+1), DEC)+": "+String(rssi[1], DEC)+"%"));
  }
  if (debug) Serial.println("-------------");
}
// CALIBRATION
void Calibration()
{
  // Clearing values
  for(int i=0; i<in_count; i++)
  {
	rssiMin[i] = 0;
	rssiMax[i] = 0;
  }

  // Calibration of min values
  beep(70,1);
  lcd.clear();
  lcd.print("Switch off TX");
  lcd.setCursor(1,0);
  lcd.print("then press button");
  if (debug) Serial.println("Swith OFF transmitter then press button...");
  delay(1000);
  while(digitalRead(btnPin) == HIGH);
  beep(70, 1);
  lcd.clear();
  lcd.print("Scaning low RSSI\nPlease wait..");
  if (debug) Serial.println("Scaning low RSSI values. Please wait...");
  for(int n=0; n<10; n++)
  {
	for(int i=0; i<in_count; i++)
	{
	  int tmpRSSI = analogRead(i);
	  if (tmpRSSI < rssiMin[i]) rssiMin[i] = tmpRSSI;
	  delay(150);
	}
  }

  // Calibration of max values
  beep(70, 2);
  lcd.clear();
  lcd.print("Switch on TX");
  lcd.setCursor(1,0);
  lcd.print("then press button");
  if (debug) Serial.println("Swith ON transmitter then press button...");
  delay(1000);
  while(digitalRead(btnPin) == HIGH);
  beep(70, 1);
  lcd.clear();
  lcd.print("Scaning high RSSI\nPlease wait..");
  if (debug) Serial.println("Scaning high RSSI values. Please wait...");
  for(int n=0; n<10; n++)
  {
	for(int i=0; i<in_count; i++)
	{
	  int tmpRSSI = analogRead(i);
	  if (tmpRSSI > rssiMax[i]) rssiMax[i] = tmpRSSI;
	  delay(150);
	}
  }
  beep(70, 3);
  // Show results
  lcd.clear();
  for(int i=0; i<in_count; i++)
  {
	 int rx = i+1;
	 if ((rssiMax[i] - rssiMin[i]) >= min_range)
	 {
	   lcd.println(String("RX"+String(rx, DEC)+": "+String(rssiMin[i], DEC)+"-"+String(rssiMax[i], DEC)));
	   if (debug) Serial.println(String("RX"+String(rx, DEC)+": "+String(rssiMin[i], DEC)+" - "+String(rssiMax[i], DEC)));
	 }
	 else
	 {
	   rssiMax[i] = rssiMin[i] = 0;
	   lcd.println(String("RX"+String(rx, DEC)+": NC!"));
	   if (debug) Serial.println(String("RX"+String(rx, DEC)+": NOT CONNECTED!"));
	 }
  }

  // Saving to EEPROM
  if (debug) Serial.println("Saving data to EEPROM...");
  saveData();

  while(digitalRead(btnPin) == HIGH);
}
// Load data from EEPROM
void loadData()
{
  int addr = 0;

  // Min RSSI
  for (int i=0; i<in_count; i++)
  {
	rssiMin[i] = EEPROM.read(addr);
	addr++;
	rssiMin[i] = rssiMin[i] + (EEPROM.read(addr)*255);
	addr++;
  }

  // Max RSSI
  for (int i=0; i<in_count; i++)
  {
	rssiMax[i] = EEPROM.read(addr);
	addr++;
	rssiMax[i] = rssiMax[i] + (EEPROM.read(addr)*255);
	addr++;
  }
}
// Save data to EEPROM
void saveData()
{
  int addr = 0;
  // Min RSSI
  for (int i=0; i<5; i++)
  {
	EEPROM.write(addr, lowByte(rssiMin[i]));
	addr++;
	EEPROM.write(addr, highByte(rssiMin[i]));
	addr++;
  }

  // Max RSSI
  for (int i=0; i<5; i++)
  {
	EEPROM.write(addr, lowByte(rssiMax[i]));
	addr++;
	EEPROM.write(addr, highByte(rssiMax[i]));
	addr++;
  }
}

Все будет в дребезги, а пульт останется....

#9 Necromant

Necromant

    Опытный пилот

  • Администраторы
  • 573 сообщений
  • ГородАлматы

Отправлено 29 Декабрь 2013 - 18:27

Плавное допиливание к лету? :-))
Fly over the clouds...

#10 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 29 Декабрь 2013 - 18:49

Плавное допиливание к лету? :-))

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

#11 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 28 Февраль 2014 - 01:22

Свежая версия прошивки (кода):
/*
RSSI SWITCHER FOR 5.8Ghz VIDEO RECIVERS v.1.2
Coded by ShadoW (c) 2014
*/
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// DEBUG
#define debug true

// Connecting LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Buzzer pin
#define buzPin 3
#define buzzer true

// Button pin
#define btnPin 2

// Multiplexor pins
const int multiplexor[] = {9, 8, 7};

// Analog RSSI inputs
const int rssi_in[] = {A0, A1, A2, A3};

// Receivers 2-4 (change for faster work)
#define in_count 4

// RSSI and RX values
int rssi[]	 = {0, 0, 0, 0};
int rssiMin[]  = {0, 0, 0, 0};
int rssiMax[]  = {0, 0, 0, 0};
int current_RX = 0;

// Minimal value of analog input
#define low_RSSI  43

// Minimal range between low and hight values of analog input
#define min_range 100

// SETUP
void setup()
{  
  // Configure pins
  pinMode(buzPin, OUTPUT);
  pinMode(btnPin, INPUT_PULLUP); // internal pullup  +5 (for no resistor button)
  for (int i=0; i<2; i++) pinMode(multiplexor[i], OUTPUT);
  for (int i=0; i<4; i++) pinMode(rssi_in[i], INPUT);
 
  // Serial for debuging
  if (debug) Serial.begin(9600);
 
  // Load last data from EEPROM
  if (debug) Serial.println("Loading last data from EEPROM...");
  loadData();

  // Switch to current RX
  switchTo(current_RX);

  // Start LCD
  lcd.init();
  lcd.backlight();
  lcd.print("    RSSI SWITCHER");
  lcd.setCursor(0,1);
  lcd.print("	   v.1.2");
  lcd.setCursor(0,3);
  lcd.print(" By ShadoW (c) 2014");
  delay(2000);
  lcd.clear();
 
  // Starting...
  lcd.print("Starting");
  if (debug) Serial.print("Starting");
  for (int i=0; i<5; i++)
  {
    lcd.print(".");
    if (debug) Serial.print(".");
    delay(300);
    
    // Calibration?
    if (digitalRead(btnPin) == LOW)
    {
	  Calibration();
	  break;
    }
  }

  // Clear display and start main LOOP
  lcd.clear();
  if (debug) Serial.println();
  if (buzzer) beep(500,1);
}

// MAIN LOOP
void loop()
{
  // Getting RSSI values
  getRSSI();		   

  // Selecting RX with best signal
  selectBestRX();

  // Inform on LCD
  drawRSSI();
 
  // Small delay
  delay(500);
}

// Get RSSI values in percents
void getRSSI()
{
  for (int i=0; i<in_count; i++)
  {
    rssi[i] = analogRead(rssi_in[i]);
    
    // Reciver disconected
    if (rssi[i] < rssiMin[i]) rssi[i] = rssiMin[i];

    // Converting to percents
    rssi[i] = map(constrain(rssi[i], rssiMin[i], rssiMax[i]), rssiMin[i], rssiMax[i], 0, 100);
    
    // Delay for read
    delay(300);
  }
}

// Selecting best RX
void selectBestRX()
{
  int best_RSSI    = 0;
  int best_RX	  = 0;

  // Searching best RSSI
  for (int i=0; i<in_count; i++)
  {
    if (rssi[i] > best_RSSI)
    {
	  best_RSSI = rssi[i];
	  best_RX   = i;
    }
  }
 
  // LOW RSSI percent BEEP for INFORM
  //if (best_RSSI < low_RSSI) beep(1000, 2);
 
  // Switching if need
  if (best_RX != current_RX)
  {
    if (debug) Serial.println(String("Switching from "+String((current_RX+1), DEC)+" to RX-"+String((best_RX+1), DEC)));
 
    // Switch multiplexor
    switchTo(best_RX);
    
    // Saving to current RX
    current_RX = best_RX;
    
    // Beeps indicate current RX nubmer
    if (buzzer) beep(70, (best_RX + 1));
  }
}

// Show data on display
void drawRSSI()
{
  for (int i=0; i<in_count; i++)
  {
    lcd.setCursor(0,i);
    String str = String("RX-"+String((i+1), DEC)+" RSSI: "+(rssi[i] > 0 ? String(rssi[i], DEC)+"%  " : String("NC    ")));
    lcd.print(str);
    if (debug) Serial.println(str);
  }

  if (debug) Serial.println("-------------");
}

// Switch to RX (sends address to multiplexor)
void switchTo(int RX)
{
  switch(RX)
  {
    // RX-1 (a2 on IC)
    case 0:    
	  digitalWrite(multiplexor[0], LOW);
	  digitalWrite(multiplexor[1], HIGH);
	  digitalWrite(multiplexor[2], HIGH);
    break;
	  
    // RX-2 (a1 on IC)
    case 1:
	  digitalWrite(multiplexor[0], LOW);
	  digitalWrite(multiplexor[1], LOW);
	  digitalWrite(multiplexor[2], LOW);
    break;
	  
    // RX-3 (a0 on IC)
    case 2:
	  digitalWrite(multiplexor[0], LOW);
	  digitalWrite(multiplexor[1], LOW);
	  digitalWrite(multiplexor[2], HIGH);
    break;
	  
    // RX-4 (a3 on IC)
    case 3:
	  digitalWrite(multiplexor[0], LOW);
	  digitalWrite(multiplexor[1], HIGH);
	  digitalWrite(multiplexor[2], LOW);
    break;
  }
}

// CALIBRATION
void Calibration()
{  
  // Clearing values
  for(int i=0; i<in_count; i++) rssiMin[i] = rssiMax[i] = 0;
  current_RX = 0;
 
  // STEP 1: Calibration of min values
  if (buzzer) beep(100,1);
  lcd.clear();
  lcd.print("Switch off TX");
  lcd.setCursor(0,1);
  lcd.print("then press button...");
  if (debug) Serial.println("Swith OFF transmitter then press button...");
  delay(500);
  while(digitalRead(btnPin) == HIGH);
  if (buzzer) beep(70,1);
  lcd.clear();
  lcd.print("Scaning MIN RSSI");
  lcd.setCursor(0,1);
  lcd.print("Please wait...");
  if (debug) Serial.println("Scaning MINIMAL RSSI values. Please wait...");
  for(int n=0; n<10; n++)
  {
    for(int i=0; i<in_count; i++)
    {
	  int tmpRSSI = analogRead(rssi_in[i]);
	  if (tmpRSSI < rssiMin[i]) rssiMin[i] = tmpRSSI;
	  delay(300);
    }
  }
 
  // STEP 2: Calibration of max values
  if (buzzer) beep(100,2);
  lcd.clear();
  lcd.print("Switch on TX");
  lcd.setCursor(0,1);
  lcd.print("then press button...");
  if (debug) Serial.println("Swith ON transmitter then press button...");
  delay(500);
  while(digitalRead(btnPin) == HIGH);
  if (buzzer) beep(70,1);
  lcd.clear();
  lcd.print("Scaning MAX RSSI");
  lcd.setCursor(0,1);
  lcd.print("Please wait...");
  if (debug) Serial.println("Scaning MAXIMAL RSSI values. Please wait...");
  for(int n=0; n<10; n++)
  {
    for(int i=0; i<in_count; i++)
    {
	  int tmpRSSI = analogRead(rssi_in[i]);
	  if (tmpRSSI > rssiMax[i]) rssiMax[i] = tmpRSSI;
	  delay(300);
    }
  }
 
  // STEP 3: Show results
  if (buzzer) beep(100,3);
  lcd.clear();
  int connected_RX = 0;
  for(int i=0; i<in_count; i++)
  {
	 int rx = i+1;
	 lcd.setCursor(0,i);
     
	 if ((rssiMax[i] - rssiMin[i]) >= min_range)
	 {
	   String str = String("RX"+String(rx, DEC)+": "+String(rssiMin[i], DEC)+"-"+String(rssiMax[i], DEC));
	   lcd.print(str);
	   if (debug) Serial.println(str);
	   connected_RX++;
	 }
	 else
	 {
	   rssiMax[i] = rssiMin[i] = 0;
	   String str = String("RX"+String(rx, DEC)+": NOT CONNECTED");
	   lcd.print(str);
	   if (debug) Serial.println(str);
	 }
  }
 
  // Press button to exit setup
  while(digitalRead(btnPin) == HIGH);
 
  // Connected 2 or more RX
  if (connected_RX >= 2)
  {
    // Saving to EEPROM
    if (debug) Serial.println("Saving data to EEPROM...");
    saveData();
  }
  // Else PORTS DEBUGING
  else
  {
	 while(true)
	 {
		 for(int i=0; i<in_count; i++)
		 {
		   String str = String("TEST RX"+String((i+1), DEC)+" RSSI: "+String(analogRead(i), DEC)+"   ");
		   
		   lcd.setCursor(0,i);
		   lcd.print(str);
		   if (debug) Serial.println(str);
	    }
	    
	    if (debug) Serial.println("------------------");
	 }
  }
}

// Beep function
void beep(int length, int count)
{
  for(int i=0; i < count; i++)
  {
    digitalWrite(buzPin, HIGH);
    delay(length);
    digitalWrite(buzPin, LOW);
    if (i < (count-1)) delay(length);
  }  
}

// Load data from EEPROM
void loadData()
{
  int addr = 0;
 
  // Min RSSI
  for (int i=0; i<in_count; i++)
  {
    rssiMin[i] = EEPROM.read(addr);
    addr++;
    rssiMin[i] = constrain((rssiMin[i] + (EEPROM.read(addr)*255)), 0, 1023);
    addr++;
  }
 
  // Max RSSI
  for (int i=0; i<in_count; i++)
  {
    rssiMax[i] = EEPROM.read(addr);
    addr++;
    rssiMax[i] = constrain((rssiMax[i] + (EEPROM.read(addr)*255)), 0, 1023);
    addr++;
  }
 
  // Сurrent RX
  current_RX = constrain(EEPROM.read(addr), 0, 3);
 
  // Debug EEPROM data
  if (debug)
  {
    for(int i=0; i<in_count; i++) Serial.println(String("EEPROM RX"+String((i+1), DEC)+": "+String(rssiMin[i], DEC)+" - "+String(rssiMax[i], DEC)));
    
    Serial.println(String("EEPROM Current RX: "+String((current_RX + 1), DEC)));
  }
}

// Save data to EEPROM
void saveData()
{
  int addr = 0;

  // Min RSSI
  for (int i=0; i<in_count; i++)
  {
    EEPROM.write(addr, lowByte(rssiMin[i]));
    addr++;
    EEPROM.write(addr, highByte(rssiMin[i]));
    addr++;
  }
 
  // Max RSSI
  for (int i=0; i<5; i++)
  {
    EEPROM.write(addr, lowByte(rssiMax[i]));
    addr++;
    EEPROM.write(addr, highByte(rssiMax[i]));
    addr++;
  }
 
  // Сurrent RX
  EEPROM.write(addr, current_RX);
}

Все будет в дребезги, а пульт останется....

#12 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 28 Февраль 2014 - 01:30

Наконец доделал нормальные разъемы RCA

RSSI_SWITCHER_RCA.jpg
Все будет в дребезги, а пульт останется....

#13 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 28 Февраль 2014 - 12:45

Проверка работы:


Все будет в дребезги, а пульт останется....

#14 UWRTEY

UWRTEY

    Новичок

  • Пилоты
  • Pip
  • 2 сообщений

Отправлено 12 Июль 2015 - 18:06

Привет, как обстоят дела с проектом наземной станции?

Я сейчас пытаюсь над таким-же проектом поработать.

Не могу расковырять протокол MAVlink. ( Хочется готовую библиотеку поюзать )

Пишу немного на асме под AVR.

 



#15 ShadoW

ShadoW

    Админ форума

  • Администраторы
  • 458 сообщений
  • ГородАлматы

Отправлено 13 Июль 2015 - 10:15

Привет, я хочу из АПМ 2.6 сделать антенна-трекер. Нужен грамотный PAN/TILT.


Все будет в дребезги, а пульт останется....

#16 UWRTEY

UWRTEY

    Новичок

  • Пилоты
  • Pip
  • 2 сообщений

Отправлено 13 Июль 2015 - 14:45

А как ты хочешь организовать прием данных на наземную станцию?

Через видеоприемник или через LRS ?

Я думаю, что лучше будет пользоваться обратным каналом LRS, для лублирования данных телеметрии.

остается выдернуть GPS данные с протокола MAVlink и обработать их

Прикрепленные изображения

  • blockshema.gif






Темы с аналогичным тегами наземная станция, arduino

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных