Nachbau: X-Aircraft Pilot Lamp (Signal-Auswertung)

maker7

Erfahrener Benutzer
#1
Hallo Zusammen,
Da im Pilot-Lamp-Signal, welches MultiWii bereitstellt, alle für mich relevanten Zustände des Controllers enthalten sind, würde ich gerne dieses Signal extern auswerten. Beziehungsweise eine eigene "Pilot Lamp" (in Form von LED Bars an den Armen) bauen.

Kann mir irgendwie nicht vorstellen, dass da noch niemand etwas vergleichbares umgesetzt hat. Nach umfangreicher Recherche konnte ich dennoch nichts finden, bis auf ein Video, allerdings ohne tiefgründigere Dokumentation.

Gibt es unter euch jemanden der in dieser Richtung schon mal experimentiert hat oder gar ein solches Projekt schon abgeschlossen hat?
Würde mich über jegliche Informationen freuen.



Bekannt sind mir bis dato die verschiedenen Frequenzen welche die Pilot Lamp erwartet:

Code:
#define RED_LED_ON  1000                                                      //
#define RED_LED_OFF  850                                                      //
#define BLU_LED_ON  1600                                                      //
#define BLU_LED_OFF 1300                                                      //
#define GRN_LED_ON  4500                                                      //
#define GRN_LED_OFF 2600                                                      //
#define BUZZER_ON    725                                                      //
#define BUZZER_OFF   625                                                      //
Sobald die Pilot Lamp drei Perioden der entsprechenden Frequenz empfängt schaltet die zugehörige LED bzw. der Buzzer. Soll nichts geschalten werden kann das Signal low (0V-Pegel) sein.


Grüße
Elias
 
#2
Ich habs letzt mal fix auf nem Brushless-Regler implementiert, wie mein ESCLight auch.
http://der-frickler.net/modellbau/avr/esclight

kommt hinten auf meinen Gofly -Travel
http://der-frickler.net/modellbau/planes/gofly_travel

Kann halt nur die 3 Farben, keinen Buzzer da kein Pin frei. Finde die Blinksequenzen im Multiwii nur nicht soo aussagekräftig.

/*****************************************************************************
*
* Copyright (c) 2012 Johannes Hermen 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
*
*****************************************************************************
*
* ESC Light Module
* Uses an Hobbyking 6A UBEC Brushless ESC as light switch.
* switches the different lights on dependent to the stick position .
*
* PINOUT: Servo Signal IN: INT0 (PD2)
* OUT1 RED WIRE
* OUT2 BLUE WIRE
* OUT3 BLACK Wire
*
*****************************************************************************/


#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define IN PD2

#define PL_GRN_ON 120 // 100us
#define PL_GRN_OFF 220 // 200us
#define PL_BLU_ON 320 // 300us
#define PL_BLU_OFF 420 // 400us
#define PL_RED_ON 520 // 500us
#define PL_RED_OFF 620 // 600us
#define PL_BZR_ON 720 // 700us
#define PL_BZR_OFF 820 // 800us
#define PL_IDLE 1020 // 1000us

static void setupPorts(void) {
DDRB = 255; // portb as output
PORTB = 0; // portb to 0
DDRC = 255; // portc as output
PORTC = 0; // portc to 0
DDRD = 48; // portd as output, int0 as input
PORTD = 0; // portd to 0
}

// for PFET = switched VCC
//static void out1_on(void) { PORTD |= (1 << 4); }
//static void out1_off(void) { PORTD &= ~(1 << 4); }
//static void out2_on(void) { PORTC |= (1 << 5); }
//static void out2_off(void) { PORTC &= ~(1 << 5); }
//static void out3_on(void) { PORTC |= (1 << 3); }
//static void out3_off(void) { PORTC &= ~(1 << 3); }

// // for NFET = switched GND
static void out1_on(void) { PORTD |= (1 << 5); }
static void out1_off(void) { PORTD &= ~(1 << 5); }
static void out2_on(void) { PORTC |= (1 << 4); }
static void out2_off(void) { PORTC &= ~(1 << 4); }
static void out3_on(void) { PORTB |= (1 << 0); }
static void out3_off(void) { PORTB &= ~(1 << 0); }

uint16_t ppm = 0; // measures PPM frame length
uint8_t i = 0;

// on timer1 overflow
ISR (TIMER1_OVF_vect)
{
ppm = 1000;
}

// on INT0 / PD2 pinchange
ISR (INT0_vect)
{
if ((PIND & 4)==4) // check 3th bit of PORTD (pin 4) got HIGH
{
TCCR1B = 0; // stop timer1
TCNT1 = 0; // reset timer1
TCCR1B = 1; // start 16bit timer1 - no prescale
}
else if ((PIND & 4)==0 )
{ // check 3th bit of PORTD (pin 4) got LOW
TCCR1B = 0; // stop timer1
uint16_t value = TCNT1; // get Timer Value
// map measured value ms
ppm = ((value) / 16);
}
}

int main (void)
{
setupPorts();

MCUCR = 1; // External Interrupt on PinChange
GICR = 64; // enable Int0

// Timer 1 - measures input signal
TCCR1A = 0; // 16-Bit Normal Mode
TIMSK |= (1<<TOIE1); // Timer Overflow-Interrupt an
TCCR1B = 0; // stop 16-Bit Timer
TCNT1 = 0; // reset timer1

sei(); // Interrupts on.

TCCR1B = 1; // start timer1

out1_off();
out2_off();
out3_off();

while(1)
{


if (ppm < PL_GRN_ON) {
out3_on();
} else if (ppm < PL_GRN_OFF) {
out3_off();
} else if (ppm < PL_BLU_ON) {
out2_on();
} else if (ppm < PL_BLU_OFF) {
out2_off();
} else if (ppm < PL_RED_ON) {
out1_on();
} else if (ppm < PL_RED_OFF) {
out1_off();
} else if (ppm < PL_IDLE) { //long idle turns all off.

i++;
if (i == 100) {
out1_off();
out2_off();
out3_off();
i = 0;
}
}

_delay_ms(10 );

}

}
 

JUERGEN_

Generation 60++
#3
....
Kann halt nur die 3 Farben, keinen Buzzer da kein Pin frei.
Finde die Blinksequenzen im Multiwii nur nicht soo aussagekräftig.
naja,
wenn man es weiter treiben wollte,
bestünde ja die Möglichkeit, die P-FET runter zu löten ?

und die Treibertransistoren der P-FET noch mal als Schalter zu verwenden?

:)
 

maker7

Erfahrener Benutzer
#4
Hallo Frickler,

Interessanter Lösungsweg, ist so sicherlich üblich bei der Auswertung von (Servo-)PPM-Signalen?
Ich dachte an das Input Capture Interrupt-Event, was die Controllerauswahl natürlich reduziert...

EDIT
Soweit mein Code, bzw. das Resultat nach einem Nachmittag im Schwimmbad - oder was macht man sonst auf den Liegestühlen welche da überall rum stehen? ;)
Soweit ich es ohne Hardware testen konnte scheint alles zu laufen.
Code:
////////////////////////////////////////////////////////////////////////////////
// Receive and process a "X-Aircraft Pilot Lamp" signal                       //
//  (thus, the program simulates an "X Aircraft Pilot Lamp")                  //
//                                                                            //
//         Ruemmler, Elias                                                    //
//         RC-Art Solutions - Eisenach 2013                                   //
//                                                                            //
//         Modulversion: 00.001.0003d (non tested code preview)               //
//                                                                            //
//                                                                            //
// The signal must connected to the ICP1 pin.                                 //
//                                                                            //
//                                                                            //
// Info below found on http://www.multiwii.com/forum/viewtopic.php?f=6&t=1794 //
// posted by "mr.rc-cam" in post #3                                           //
//                                                                            //
// ************************************************************************** //
// *The control waveform should be symmetrical and it can be idle when not  * //
// *writing/changing new states, but at least three complete waveform cycles* //
// *are needed for each LED or Buzzer update. The control frequencies are as* //
// *follows (all defines in Hz):                                            * //
// ************************************************************************** //
//                                                                            //
#define RED_LED_ON  1000                                                      //
#define RED_LED_OFF  850                                                      //
#define BLU_LED_ON  1600                                                      //
#define BLU_LED_OFF 1300                                                      //
#define GRN_LED_ON  4500                                                      //
#define GRN_LED_OFF 2600                                                      //
#define BUZZER_ON    725                                                      //
#define BUZZER_OFF   625                                                      //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// define cpu clock speed and baud-rates

#define F_CPU 8000000


// standard adjusts and includes

#include <avr/io.h>

#define setBits(port,mask)	do{ (port) |=  (mask); }while(0)
#define clrBits(port,mask)	do{ (port) &= ~(mask); }while(0)
#define tstBits(port,mask)	((port) & (mask))

#define TRUE	1
#define FALSE	0


// libraries and includes

#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>


// specific defines

#define TOL_RANGE_LOW   35            // tolerance range input frequency
#define TOL_RANGE_HIGH  70            // tolerance range input frequency


// hardware configuration

static void	red_on(void)     { clrBits( PORTC, ( 1<<PC3 )); }
static void	red_off(void)    { setBits( PORTC, ( 1<<PC3 )); }
static void	blu_on(void)     { setBits( PORTB, ( 1<<PB0 )); }
static void	blu_off(void)    { clrBits( PORTB, ( 1<<PB0 )); }
static void	grn_on(void)     { setBits( PORTB, ( 1<<PB6 )); }
static void	grn_off(void)    { clrBits( PORTB, ( 1<<PB6 )); }
static void	buz_on(void)     { setBits( PORTB, ( 1<<PB7 )); }
static void	buz_off(void)    { clrBits( PORTB, ( 1<<PB7 )); }


// hardware init

int port_init(void)
{
  DDRB	|=	( 1<<DDB0 ) | ( 1<<DDB3 ) | ( 1<<DDB6 ) | ( 1<<DDB7 );    // PB0, 3, 6, 7 output
  PORTB	&=	~(( 1<<PB0 ) | ( 1<<PB3 )| ( 1<<PB6 ) | ( 1<<PB7 ));      // PB0, 3, 6, 7 low
}

// define global variables

volatile unsigned char cntOvrFlw;     // counter overflows during measurement
volatile unsigned int  sTime = 0;     // timer @ first flag
volatile unsigned int  eTime = 0;     // timer @ second flag
volatile unsigned char rdy;           // process ready


ISR( TIMER1_CAPT_vect )
{
  static unsigned char firstFlag = TRUE;

  if( rdy )            // mainloop not ready
    return;

  if( firstFlag )      // first measurement
  {
    sTime = ICR1;      // save the current timer value
    cntOvrFlw = 0;     // reset overflow counter
    firstFlag = FALSE;
  }

  else                 // second measurement
  {
    eTime = ICR1;      // save the current timer value
    firstFlag = TRUE;
	rdy = TRUE;        // ready for process
  }
}


ISR( TIMER1_OVF_vect )
{
  cntOvrFlw++;         // clock speed?!
}

int main()
{
  uint16_t measRes = 0;

  TCCR1B = ( 1<<ICES1 )  | ( 1<<CS10 );   // input capture edge; non precaling
  TIMSK = ( 1<<TICIE1 ) | ( 1<<TOIE1 );   // activate interrupts: capture; overflow

  sei();
  
  while( 1 )
  {
    if( rdy )          // measurement ready?
    {
      measRes = ( cntOvrFlw * 65536 ) + eTime - sTime;

      measRes = F_CPU / measRes;      // f = 1 / t
      
      switch (measRes)                // attention "case ranges" only available in GCC!
      {
        case  ( BUZZER_OFF - TOL_RANGE_LOW ) ... ( BUZZER_OFF + TOL_RANGE_LOW ):
          // buzzer off
          buz_off();
          break;
        case  ( BUZZER_ON - TOL_RANGE_LOW ) ... ( BUZZER_ON + TOL_RANGE_LOW ):
          // buzzer on
          buz_on();
          break;
        case  ( RED_LED_OFF - TOL_RANGE_LOW ) ... ( RED_LED_OFF + TOL_RANGE_LOW ):
          // red led off
          red_off();
          break;
        case  ( RED_LED_ON - TOL_RANGE_LOW ) ... ( RED_LED_ON + TOL_RANGE_LOW ):
          // red led on
          red_on();
          break;
        case  ( BLU_LED_OFF - TOL_RANGE_HIGH ) ... ( BLU_LED_OFF + TOL_RANGE_HIGH ):
          // blue led off
          blu_off();
          break;
        case  ( BLU_LED_ON - TOL_RANGE_HIGH ) ... ( BLU_LED_ON + TOL_RANGE_HIGH ):
          // blue led on
          blu_on();
          break;
        case  ( GRN_LED_OFF - TOL_RANGE_HIGH ) ... ( GRN_LED_OFF + TOL_RANGE_HIGH ):
          // green led off
          grn_off();
          break;
        case  ( GRN_LED_ON - TOL_RANGE_HIGH ) ... ( GRN_LED_ON + TOL_RANGE_HIGH ):
          // green led on
          grn_on();
          break;
	  }      
      
      rdy = FALSE;       // start next measurement
    }                    // end; if( rdy ) 
  }                      // end; while( 1 )
}

Werde das heute Abend mal auf einem ATmega8 testen.

Vielen Dank schon mal für die Infos. Dein GoFly gefällt mir auch sehr gut :)

Grüße
Elias
 
Zuletzt bearbeitet:

franko_

Erfahrener Benutzer
#5
Das heisst man greift das PPM Signal ab und der Atmega8 schaltet dementsprechend die LED´s an?

Das würde ich gerne mit dem APM bei RTL schalten können.. oder gibt es schon sowas für´s APM.
Die externen Led´s kenne ich, aber für die Flightmodes habe ich noch nix gefunden.. (RTL)

Das Signal müsste dann von Kanal 5 ausgewertet werden. Wie sieht sowas im Arduino aus?
 
Zuletzt bearbeitet:

franko_

Erfahrener Benutzer
#6
Hm, ich habe da was gefunden und es auf Kanal 5 abgeändert...
Quelle:
http://forum.arduino.cc/index.php/topic,7167.0.html

#define channumber 8 //Cuantos canales tiene tu radio???????/How many channels have your radio???
#define filter 10 // Filtro anti salto/ Glitch Filter
int channel[channumber]; //Valores de canales leidos/ readed Channel values
int lastReadChannel[channumber]; //Ultima lectura obtenida/ Last values readed
int conta=0; //Contador/couter


void setup()
{
Serial.begin(9600); //Iniciamos com serial/ Serial Begin
pinMode(4, INPUT); //Patita 4 como entrada / Pin 4 as input
pinMode(13, OUTPUT); // Led pin 13
}

void loop()
{

if(pulseIn(4, HIGH) > 3000) //Si el pulso del pin 4 es > 3000 usegundos continua /If pulse > 3000 useconds, continues
{
for(int i = 0; i <= channumber-1; i++) //lee los pulsos de los canales / Read the pulses of the channels
{
channel=pulseIn(4, HIGH);
}
for(int i = 0; i <= channumber-1; i++) //Promedia los pulsos/Average the pulses
{
if((channel > 2000) || (channel <100))//Si se pasa del rango envia ultimo pulso/ If channel > max range, chage the value to the last pulse
{
channel= lastReadChannel;
}
else
{
channel=(lastReadChannel+channel)/2; //Promedio el pulso pasado con el nuevo pulso/Average the last pulse eith the current pulse
conta++; //Incrementa el contador/ increment counter
}
}

}
if(conta > filter)//Si el contador es mayor al filtro imprime valores/ If counter is > than filter, then prints values
{
for(int i = 0; i <= channumber-1; i++) //Ciclo para imprimir valores/Cycle to print values
{
Serial.print("CH"); //Canal/Channel
Serial.print(i+1); // Numero del canal / Channel number
Serial.print(": "); // que te importa
Serial.println(channel);
lastReadChannel=channel;
}
if(channel[4] > 1300) //si el canal 5 tiene un rango mayor a 500 enciende el LED/ If channel 5 is > than 500 turn on the led
{
digitalWrite(13, HIGH);
}
else
{
digitalWrite(13, LOW);//Si no lo apaga/If not turn it off
}
delay(400); //Delay
conta=0;//Reinicia el contador/ Restart couter.
}
}


Zumindest leuchtet eine LED wenn ich RTL einschalte, die restlichen Flightmodes können dann theoretisch auch noch belegt werden.
Was mir hierbei nicht gefällt ist das aufsplitten des PPM Signals ..
 

wareck

Neuer Benutzer
#7
Hi maker 7
Can you help me to convert your programm to attiny85 ?
(I made conversion in arduino, but not working very well, I'm not very self confident with interrupts...)

Olivier
 
FPV1

Banggood

Oben Unten