Sucher Unterstützung bei einfacher Fernsteuerung für Gimbal mit arduino & FrSky DHT
Hallo,
Ich lese schon länger hier im Forum mit und habe mich nun entschlossen mich zu registrieren. Kurz zu mir: Ich bin 25 Jahre alt und wohne am wunderschönen ( ) Jurasüdhang in der Schweiz. Ich betrieb bis vor ca. 4 Jahren sehr aktiv Modellflug (Grossmodelle, Hangflug und Helikopter). Mittlerweile haben ich und ein Kollege uns vermehrt für Multicopter resp. die damit machbaren Video- und Fotoaufnahmen interessiert. Im Moment fliege ich einen T960 mit A2 und dem DYS Eagle Eye Gimbal 5D (Nikon D7100 / resp. D5300).
Für den Betrieb des Gimbals planen wir nun einen Groundstation Koffer. Darin befinden sich 2 Monitore (5.8GHZ / DJI IOSD und A/V Out der Camera), sowie ein IPad (DJI Groundstation). Nun wollten wir die Gimbalsteuerung ebenfalls in diesem Koffer unterbringen. Dazu habe ich mir ein FrSky DHT Modul inkl. 8 Kanal Empfänger, sowie ein Arduino Mega bestellt. Ziel ist eine 8 Kanal Fernbedienung: 4 analoge Kanäle (Pitch, Roll, Yaw und Focus) sowie Blende, Belichtungszeit, ISO, Shutter und Video als digitale Kanäle (Drei- / Zweistufenschalter). Der Empfänger soll die 8 Kanäle über die normalen Ausgänge (ich glaube das nennt sich PWM, d. h. 1-8) an das Alexmos Board und die CamRemote 2a ausgeben.
Leider bin ich ein absoluter Arduino und programmier Noob. Ich habe auf der Seite von Frickler den Simu TX Sketch heruntergeladen und versucht zu verändern. Leider komme ich nicht weiter.
(Wahrscheinilich ist nicht alles falsche bzw. inkomplette mit ?? vershen )
Der Sketch lässt sich kompilieren ist jedoch sicher nicht funktionsfähig. Ich weiss nicht welche Namen ich wann für welche Ausgänge vergeben darf. Für etwas Hilfe wäre ich sehr dankbar. Ich werde dann vermutlich einen günstigen 3 Achs Industriejoystick (ink. Shutter Taster) zur Steuerung, einen "Fader" zum Fokussieren, sowie Zwei und Dreistufenschalter einsetzen.
Ich möchte hier niemanden "missbrauchen" mir eine Pfannenfertige Lösung zu präsentieren - würde mich jedoch über Hilfestellungen, Links etc. sehr freuen.
Vielen Dank!
Florian
Hallo,
Ich lese schon länger hier im Forum mit und habe mich nun entschlossen mich zu registrieren. Kurz zu mir: Ich bin 25 Jahre alt und wohne am wunderschönen ( ) Jurasüdhang in der Schweiz. Ich betrieb bis vor ca. 4 Jahren sehr aktiv Modellflug (Grossmodelle, Hangflug und Helikopter). Mittlerweile haben ich und ein Kollege uns vermehrt für Multicopter resp. die damit machbaren Video- und Fotoaufnahmen interessiert. Im Moment fliege ich einen T960 mit A2 und dem DYS Eagle Eye Gimbal 5D (Nikon D7100 / resp. D5300).
Für den Betrieb des Gimbals planen wir nun einen Groundstation Koffer. Darin befinden sich 2 Monitore (5.8GHZ / DJI IOSD und A/V Out der Camera), sowie ein IPad (DJI Groundstation). Nun wollten wir die Gimbalsteuerung ebenfalls in diesem Koffer unterbringen. Dazu habe ich mir ein FrSky DHT Modul inkl. 8 Kanal Empfänger, sowie ein Arduino Mega bestellt. Ziel ist eine 8 Kanal Fernbedienung: 4 analoge Kanäle (Pitch, Roll, Yaw und Focus) sowie Blende, Belichtungszeit, ISO, Shutter und Video als digitale Kanäle (Drei- / Zweistufenschalter). Der Empfänger soll die 8 Kanäle über die normalen Ausgänge (ich glaube das nennt sich PWM, d. h. 1-8) an das Alexmos Board und die CamRemote 2a ausgeben.
Leider bin ich ein absoluter Arduino und programmier Noob. Ich habe auf der Seite von Frickler den Simu TX Sketch heruntergeladen und versucht zu verändern. Leider komme ich nicht weiter.
Code:
/*****************************************************************************
*
* Copyright (c) 2013 www.der-frickler.net
*
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*****************************************************************************
*
* SimuTX.ino
* Kleiner RC Sender mit Frsky Akku Telemetrie
*
* Based on the ArduinoRCLib transmitter example.
* Website: http://sourceforge.net/p/arduinorclib/
*
*****************************************************************************/
#include <AIPin.h>
#include <BiStateSwitch.h>
#include <TriStateSwitch.h>
#include <AnalogSwitch.h>
#include <Channel.h>
#include <DualRates.h>
#include <Expo.h>
#include <InputToOutputPipe.h>
#include <PPMOut.h>
#include <ThrottleHold.h>
#include <Timer1.h>
#include <util.h>
#include <Buzzer.h>
#include <Timer2.h>
#define LIPO_CELL_OK 39
#define LIPO_CELL_ORANGE 36
#define LIPO_CELL_RED 33
#define MAX_VOLT_A 132
#define MAX_VOLT_B 132
#define MAX_VOLT_TX 150
#define TX_VOLT_PIN A4
#define EXPO_1 0
#define EXPO_2 0
#define EXPO_3 0
#define DR_1 0
#define DR_2 0
#define DR_3 0
int txCells = 3;
int rxCells = 3;
enum
{
ChannelCount = 8
};
// input related variables
rc::AIPin g_aPins[4] =
{
rc::AIPin(A0, rc::Input_AIL), // we have to specify an input pint
rc::AIPin(A1, rc::Input_ELE), // and we can optionally specify an index in the centralized
rc::AIPin(A2, rc::Input_THR), // input buffer where results should be written to
rc::AIPin(A3, rc::Input_RUD)
};
// throttle hold
//rc::BiStateSwitch g_tHold(3, rc::Switch_A, false, false);
//rc::ThrottleHold g_throttleHold(-256, rc::Switch_A); // Default throttle level is -256, default in/output is THR, set switch to Switch_A
// ch 5 + DR/Expo
rc::TriStateSwitch g_ch5In(4, 5, rc::Switch_B, true);
rc::AnalogSwitch g_ch5Switch(rc::Switch_B, rc::Input_FLP);
// ch 6
rc::TriStateSwitch g_ch6In(6, 7, rc::Switch_C, true);
rc::AnalogSwitch g_ch6Switch(rc::Switch_C, rc::Input_BRK);
// ch 7
rc::TriStateSwitch g_ch7In(8, 9, rc::Switch_D, true);
rc::AnalogSwitch g_ch7Switch(rc::Switch_D, rc::Input_BRK); // ??
// ch 8
rc::TriStateSwitch g_ch8In(10, 11, rc::Switch_E, true);
rc::AnalogSwitch g_ch8Switch(rc::Switch_E, rc::Input_BRK); // ?
// Expo/DR, we use one expo and one dr per control and per flightmode
//rc::Expo g_ailExpo[3] = {rc::Expo(EXPO_1, rc::Input_AIL), rc::Expo(EXPO_2, rc::Input_AIL), rc::Expo(EXPO_3, rc::Input_AIL)}; // also specify what index of the input
//rc::Expo g_eleExpo[3] = {rc::Expo(EXPO_1, rc::Input_ELE), rc::Expo(EXPO_2, rc::Input_ELE), rc::Expo(EXPO_3, rc::Input_ELE)}; // buffer the expo should work on (optionally)
//rc::Expo g_rudExpo[3] = {rc::Expo(EXPO_1, rc::Input_RUD), rc::Expo(EXPO_2, rc::Input_RUD), rc::Expo(EXPO_3, rc::Input_RUD)};
//rc::DualRates g_ailDR[3] = {rc::DualRates(DR_1, rc::Input_AIL), rc::DualRates(DR_2, rc::Input_AIL), rc::DualRates(DR_3, rc::Input_AIL)}; // also specify what index of the input
//rc::DualRates g_eleDR[3] = {rc::DualRates(DR_1, rc::Input_ELE), rc::DualRates(DR_2, rc::Input_ELE), rc::DualRates(DR_3, rc::Input_ELE)}; // buffer the dual rates
//rc::DualRates g_rudDR[3] = {rc::DualRates(DR_1, rc::Input_RUD), rc::DualRates(DR_2, rc::Input_RUD), rc::DualRates(DR_3, rc::Input_RUD)}; // should work on (optionally)
rc::Channel g_channels[ChannelCount] =
{
rc::Channel(rc::Output_AIL1, rc::OutputChannel_1),
rc::Channel(rc::Output_ELE1, rc::OutputChannel_2),
rc::Channel(rc::Output_THR1, rc::OutputChannel_3),
rc::Channel(rc::Output_RUD1, rc::OutputChannel_4),
rc::Channel(rc::Output_FLP1, rc::OutputChannel_5),
rc::Channel(rc::Output_BRK1, rc::OutputChannel_6),
rc::Channel(rc::Output_BRK1, rc::OutputChannel_7), // ?
rc::Channel(rc::Output_BRK1, rc::OutputChannel_8) // ?
};
// PPM related variables
rc::PPMOut g_PPMOut(ChannelCount);
// Set up pipes for direct input to output copying
rc::InputToOutputPipe g_aileron(rc::Input_AIL, rc::Output_AIL1);
rc::InputToOutputPipe g_elevator(rc::Input_ELE, rc::Output_ELE1);
rc::InputToOutputPipe g_throttle(rc::Input_THR, rc::Output_THR1);
rc::InputToOutputPipe g_rudder(rc::Input_RUD, rc::Output_RUD1);
rc::InputToOutputPipe g_aux1(rc::Input_FLP, rc::Output_FLP1);
rc::InputToOutputPipe g_aux2(rc::Input_BRK, rc::Output_BRK1); // ?
rc::InputToOutputPipe g_aux3(rc::Input_BRK, rc::Output_BRK1); // ?
rc::InputToOutputPipe g_aux4(rc::Input_BRK, rc::Output_BRK1); // ?
//--------------------------------------------------------------------------------------------
// FrSky stuff
#define FRAMESIZE 11
int Data[FRAMESIZE];
int counter=0, state=0;
boolean validFrame=0, stuffFlag;
int voltageTX=120, voltageA=120, voltageB=120, rssi=0;
//--------------------------------------------------------------------------------------------
unsigned long last = 0;
void setup()
{
Serial.begin(9600);
// Initialize timer
rc::Timer1::init();
rc::Timer2::init();
rc::g_Buzzer.setPin(8);
rc::g_Buzzer.beep(600, 0, 0);
digitalWrite(12, HIGH); // sets the LED on
// set calibration values, these depend on hardware configurations
g_aPins[0].setCalibration(35, 502, 948); // Right horizontal, aileron
g_aPins[1].setCalibration(41, 522, 962); // Right vertical, elevator
g_aPins[2].setCalibration(60, 479, 971); // Left vertical, throttle
g_aPins[3].setCalibration(49, 516, 940); // Left horizontal, rudder
g_aPins[0].setReverse(false); // potentiometer mounted upside down?
g_aPins[1].setReverse(false);
g_aPins[2].setReverse(false);
g_aPins[3].setReverse(true);
// set up normalized -> microseconds conversion
rc::setCenter(1500); // servo center point
rc::setTravel(700); // max servo travel from center point
// our output signal will lie between 920 and 2120 microseconds (1520 +/- 600)
// fill channel values buffer with sane values, all centered
rc::setOutputChannel(rc::OutputChannel_1, rc::normalizedToMicros(0));
rc::setOutputChannel(rc::OutputChannel_2, rc::normalizedToMicros(0));
rc::setOutputChannel(rc::OutputChannel_3, rc::normalizedToMicros(0)); // Throttle channel, MUST BE AT 0 THROTTLE!
rc::setOutputChannel(rc::OutputChannel_4, rc::normalizedToMicros(0));
rc::setOutputChannel(rc::OutputChannel_5, rc::normalizedToMicros(0));
rc::setOutputChannel(rc::OutputChannel_6, rc::normalizedToMicros(0));
rc::setOutputChannel(rc::OutputChannel_7, rc::normalizedToMicros(0));
rc::setOutputChannel(rc::OutputChannel_8, rc::normalizedToMicros(0));
// set up PPM
g_PPMOut.setPulseLength(400); // default pulse length used by FrSky hardware
g_PPMOut.setPauseLength(20000); // default frame length used by FrSky hardware
g_PPMOut.start(9); // use pin 9, which is preferred as it's faster
delay(1000);
rc::g_Buzzer.beep(10, 0, 0);
delay(1000);
}
void loop()
{
long now = millis();
// Serial.println(now-last);
last = now;
// Read RAW Data from FrSky
while (Serial.available()) {
byte b = Serial.read();
processFrSkyByte(b);
}
if ((now % 3000) == 0) {
voltageTX = map(analogRead(TX_VOLT_PIN), 0, 1100, 0, MAX_VOLT_TX);
//Serial.println(voltageTX);
if (voltageTX < (txCells*LIPO_CELL_RED)) {
rc::g_Buzzer.beep(30);
}
}
if ((now % 1000) == 0) {
//Serial.println(voltageA);
if (voltageA < (rxCells*LIPO_CELL_RED)) {
rc::g_Buzzer.beep(10, 10, 2);
} else if (voltageA < (rxCells*LIPO_CELL_ORANGE)) {
rc::g_Buzzer.beep(10, 10, 1);
}
}
g_ch5In.read();
g_ch5Switch.update();
//rc::SwitchState fSwitchState = rc::getSwitchState(rc::Switch_B);
//int flightmode = 0;
//if (fSwitchState == rc::SwitchState_Down) {
// flightmode = 0;
//} else if (fSwitchState == rc::SwitchState_Center) {
// flightmode = 1;
//} else if (fSwitchState == rc::SwitchState_Up) {
// flightmode = 2;
// }
//Serial.println(flightmode);
g_ch6In.read();
g_ch6Switch.update();
g_ch7In.read();
g_ch7Switch.update();
g_ch8In.read();
g_ch8Switch.update();
// read analog values, these write to the input system (AIL, ELE, THR and RUD)
g_aPins[0].read(); // aileron
g_aPins[1].read(); // elevator
g_aPins[2].read(); // throttle
g_aPins[3].read(); // rudder
//g_tHold.read();
//g_throttleHold.apply();
// apply expo and dual rates to input, these read from and write to input system
//g_ailExpo[flightmode].apply();
//g_ailDR[flightmode].apply();
//g_eleExpo[flightmode].apply();
//g_eleDR[flightmode].apply();
//g_rudExpo[flightmode].apply();
//g_rudDR[flightmode].apply();
g_aileron.apply();
g_elevator.apply();
g_rudder.apply();
g_throttle.apply();
g_aux1.apply();
g_aux2.apply();
g_aux2.apply(); // ?
g_aux2.apply(); //
// END OF OUTPUT HANDLING
// Now we've filled all the parts of the output system we need (AIL1, ELE1, THR1, RUD1, GYR1 and PIT1)
// now we can start using the output to generate a signal or data packet
// Well, almost. Channel does perform some transformations, but these aren't written back into the output system
// since more than one channel may use the same output as source.
// perform channel transformations and set channel values
for (uint8_t i = 0; i < ChannelCount; ++i)
{
g_channels[i].apply();
}
// Tell PPMOut that new values are ready
g_PPMOut.update();
}
void processFrSkyByte(byte b) {
/* 0xFD USERDATA */ /* 0xFE RSSI */
if (b == 0x7E && counter == FRAMESIZE-1 && Data[0] == 0x7E && Data[1] == 0xFE ) {
validFrame = 1;
}
else if (b == 0x7D) { // Byte stuffing!
stuffFlag = true;
// only stuffing byte - not use
//return;
}
else if (b == 0x7E) {
counter = 0; // Start of Frames.
}
if (stuffFlag) { // Byte stuffing!
b ^= 0x20;
stuffFlag = false;
}
Data[counter++] = b;
if(validFrame==1) {
// process data in current frame.
voltageA = map(Data[2], 0, 254, 0, MAX_VOLT_A);
voltageB = map(Data[3], 0, 254, 0, MAX_VOLT_B);
rssi = Data[4];
validFrame=0;
}
}
Der Sketch lässt sich kompilieren ist jedoch sicher nicht funktionsfähig. Ich weiss nicht welche Namen ich wann für welche Ausgänge vergeben darf. Für etwas Hilfe wäre ich sehr dankbar. Ich werde dann vermutlich einen günstigen 3 Achs Industriejoystick (ink. Shutter Taster) zur Steuerung, einen "Fader" zum Fokussieren, sowie Zwei und Dreistufenschalter einsetzen.
Ich möchte hier niemanden "missbrauchen" mir eine Pfannenfertige Lösung zu präsentieren - würde mich jedoch über Hilfestellungen, Links etc. sehr freuen.
Vielen Dank!
Florian