Praktyczny projekt FPV. Sterownik głowicy z modelarskiego odbiornika video. Czasem można kupić tanio porządny odbiornik, ale sterowany potencjometrem, nie do końca wiadomo na jaką dokładnie częstotliwość jest dostrojony. Można go w stosunkowo prosty sposób przerobić na wersję sterowaną bardziej "cyfrowo" - głowice video sterowane są z cyfrowo, po interfejsie i2c.
Na tym kodzie sterowałem głowicą 1.2 GHz z odbiornika Lawmate. Można podłączyć więcej niż jedną głowicę (piękno i2c) i sterować kilkoma odbiornikami na raz. A stąd już bardzo blisko do zbudowania diversity - potrzebny tylko jakaś kostka do kluczowania video i algorytm obsługi RSSI.
Żeby było śmieszniej, w dokładnie taki sam sposób można sterować nadajnikiem video (kwestia adresacji). Więc w bardzo prosty sposób można by zbudować zestaw video sterowany np potencjometrem z nadajnika - taki zestaw byłby stosunkowo odporny na zajęcie naszej częstotliwości video na lotnisku.
Potrzeba:
- odbiornik video
- arduino pro mini
- wyświetlacz i2c 20x4
- dwa przyciski
- trochę kabelków
Program zapamiętuje w eeprom zadaną częstotliwość, więc po uruchomieniu jest ostatnia zadana częstotliwość.
Możliwe do ustawienia częstotliwości w zakresie 980 - 1380 MHz z krokiem 1, 10 lub 100 MHz, w zależności od czasu wciśnięcia przycisku.
Kod:
#include <Button.h>
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
/*
create a Button object at pin 12
connect button between pin 12 and GND
*/
#define EEPROM_FREQ_ADDR_L 0
#define EEPROM_FREQ_ADDR_H 1
#define FREQ_LIMIT_LOW 980
#define FREQ_LIMIT_HIGH 1380
#define HEAD_ADDRESS 0x61
Button bPlus = Button(12, PULLUP);
int bPlusPressed = 0;
unsigned long bPlusStartTime = 0;
unsigned long bPlusTime = 0;
Button bMinus = Button(11, PULLUP);
int bMinusPressed = 0;
unsigned long bMinusStartTime = 0;
unsigned long bMinusTime = 0;
unsigned int freqL = 0;
unsigned int freqH = 0;
int current_freq = 0;
int current_freq_last_set = 0;
int current_freq_last_saved = 0;
int freq_delta = 0;
int freq_changed = 0;
unsigned long bWriteStartTime = 0;
unsigned long alarmTime = 0;
LiquidCrystal_I2C lcd(0x27,20,4);
void setup()
{
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Custom 1.2 GHz Rx");
lcd.setCursor(0,1);
lcd.print("driver by szymon");
delay(1000);
lcd.clear();
readFreqFromEEPROM();
}
void readFreqFromEEPROM()
{
freqL = EEPROM.read(EEPROM_FREQ_ADDR_L);
freqH = EEPROM.read(EEPROM_FREQ_ADDR_H);
if(freqL == 255 && freqH == 255)
{
EEPROM.write(EEPROM_FREQ_ADDR_L, 1120 & 0b11111111);
EEPROM.write(EEPROM_FREQ_ADDR_H, 1120>>8 & 0b11111111);
freqL = EEPROM.read(EEPROM_FREQ_ADDR_L);
freqH = EEPROM.read(EEPROM_FREQ_ADDR_H);
}
current_freq = freqL+(freqH<<8);
lcd.setCursor(0,1);
lcd.print(current_freq);
lcd.print(" MHz ");
current_freq_last_saved = current_freq;
setFrequencyOnHead(HEAD_ADDRESS, current_freq);
}
void setFrequencyOnHead(int address, int frequency)
{
int frequencyBase = frequency * 8 + 3840;
int frequencyH = frequencyBase >> 8;
int frequencyL = frequencyBase & 0xFF;
/* Wire.beginTransmission(address);
Wire.write(frequencyH);
Wire.write(frequencyL);
Wire.write(0xCE);
Wire.write(0x00);
Wire.endTransmission(); */
}
void loop()
{
if(bPlus.isPressed())
{
if(bPlusPressed == 0)
bPlusStartTime = millis();
bPlusPressed = 1;
}
else
{
if(bPlusPressed == 1)
{
bPlusPressed = 0;
bPlusTime = millis() - bPlusStartTime;
if(bPlusTime > 80)
{
if(bPlusTime < 500)
{
freq_delta = 1;
}
else if(bPlusTime < 1000)
{
freq_delta = 10;
}
else
{
freq_delta = 100;
}
}
}
}
if(bMinus.isPressed())
{
if(bMinusPressed == 0)
bMinusStartTime = millis();
bMinusPressed = 1;
}
else
{
if(bMinusPressed == 1)
{
bMinusPressed = 0;
bMinusTime = millis() - bMinusStartTime;
if(bMinusTime > 80)
{
if(bMinusTime < 500)
{
freq_delta = -1;
}
else if(bMinusTime < 1000)
{
freq_delta = -10;
}
else
{
freq_delta = -100;
}
}
}
}
if(alarmTime > 0 && millis() - alarmTime > 2000)
{
lcd.setCursor(0,3);
lcd.print(" ");
alarmTime = 0;
}
if(freq_delta != 0)
{
if(current_freq + freq_delta > FREQ_LIMIT_HIGH)
{
lcd.setCursor(0,3);
lcd.print("High freq limit! ");
alarmTime = millis();
current_freq = FREQ_LIMIT_HIGH;
}
else if(current_freq + freq_delta < FREQ_LIMIT_LOW)
{
lcd.setCursor(0,3);
lcd.print("Low freq limit! ");
alarmTime = millis();
current_freq = FREQ_LIMIT_LOW;
}
else
{
current_freq += freq_delta;
}
if(current_freq != current_freq_last_set)
{
setFrequencyOnHead(HEAD_ADDRESS, current_freq);
current_freq_last_set = current_freq;
}
lcd.setCursor(0,1);
lcd.print(current_freq);
lcd.print(" MHz ");
freq_delta = 0;
freq_changed = 1;
bWriteStartTime = millis();
}
if(freq_changed == 1)
{
if(millis() - bWriteStartTime > 5000)
{
freq_changed = 0;
if(current_freq != current_freq_last_saved)
{
EEPROM.write(EEPROM_FREQ_ADDR_L, current_freq & 0b11111111);
EEPROM.write(EEPROM_FREQ_ADDR_H, current_freq>>8 & 0b11111111);
current_freq_last_saved = current_freq;
}
}
}
}
Miałem kiedyś film jak to działało, ale niestety usunąłem
