Go Down

Topic: Proyecto Cuadricoptero UAV: Problema con receptor de emisora RC (Read 11425 times) previous topic - next topic

adrib

Hola a todos,
estoy construyendo un cuadricoptero UAV para ello quiero poner el Arduino UNO entre el receptor de la emisora RC y los ESC con los motores. El problema que tengo es que los pines analogicos de entrada del Arduino no me detectan las señales del receptor de RC. Se que no las detecta ya que hice un sketch que mostraba en por el serial los valores del pin analogico y no variaban a medida que movia el interruptor de la emisora sino que marca siempre 0 y de vez encuando un valor aleatorio. La transmisión entre emisora y receptor RC se que es correcta por que con un tester media el señal del receptor y los valores si que varian a la vez que muevo el interruptor, el voltaje del señal varia entre 0.17V y 0.33V

PD: mi emisora de RC es la HK6DF.

Saludops y gracias de antemano.

LuisAntonio

Si que varia la señal pero con el arduino por el puerto serie no lo puedes ver?  pon el código del arduino así igual es mas fácil ayudarte!


Un saludo.


Algunas personas sueñan con grandes logros, mientras que otros no duermen cumpliéndolos.

http://diagnostican.blogspot.com

aero_yo


chiva

Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

Cheyenne

Las emisoras suelen transmitir en PPM (creo que es analógico) y el receptor transforma la señal PPM en las salidas PWM de cada uno de los canales.

Para leer la emisora están las dos posibilidades, leer la señal PPM o las PWM de cada canal. Para leer las PPM hay que acceder al interior del receptor y buscar en el circuito dónde se intercepta esta señal. Por la red hay explicaciones de cómo hacerlo en los modelos más comunes de emisoras.

Si no se quiere tener que acceder al interior del receptor se puede leer la señal PWM de cada canal.

Para leer PPM creo que hay que utilizar una entrada analógica y para PWM una entrada digital para cada canal que quiere ser leído.

adrib, no he mirado detenidamente tu emisora pero yo diría que es PPM. ¿Qué señal es la que estás interceptando, la PPM o las PWM? ¿Dónde las estás tomando?
http://cuadricopterodiyarduino.blogspot.com/

SrDonGato

Ambas se leen en digital. en PPM se utiliza solo un pin , en PWM un pin por cada canal.

buscate el proyecto de multiwii copter, es el que hice yo. el código te permite leer los datos del receptor en ambos casos. echale un vistazo al codigo y puedes hacerte una idea de como hacerlo .

Un saludo ¡

adrib

Por lo que he leido en vuestras respuestas diria que estoy leyendo PWM ya que tengo un cable de señal por cada canal y ya que segun decis se leen en pin digital he probado con el codigo:
Code: [Select]

void setup() {
  Serial.begin(9600);
  pinMode(9,INPUT);
}
void loop() {
  int sensorValue =analogRead(9); // He probado tanto analogRead como digitalRead;
  Serial.println(sensorValue);
  delay(1000);
}


Pero lo único que me muestra por el serial son valores aleatorio =(

SrDonGato

no te has mirado lo que te he dicho ....

mírate el código para ver de que manera obtiene los valores de cada uno de los canales.

Os lo tenemos que dar todo mascao...

el codigo viene comentado, vienen las dos formas de obtener los datos

un saludo

pd: hay una version 7 de este codigo pero actualiza otras cosas, buscala de todas formas y le echas un vistazo
tambien tiene un software con el cual puedes ver el valor de los sensores , acelerometros, posicion de los sticks etc .

un saludo



SrDonGato

una pista ...



// ******************
// rc functions
// ******************

adrib

Si, he estado mirando el codigo SrDonGato pero nose que tengo que sacar de ahi ya que si  el arduino me diera valores proporcionales al potenciometro de la emisora ya sabria que codigo ponerle, el problema es que el arduino ni se inmuta a los cambios de la emisora simplemente me devuelve 0.

SrDonGato

La forma que tienes de ver el estado del pin es si está a 0 o 1 en un determinado momento.

Te has fijado como son las señales PWM y PPM ?, debes fijarte primero que es lo que queires leer por esa patilla.

aqui tienes un codigo que saque de no me acuerdo donde para leer una señal PPM, normalmente tienes que abrir el receptor para obtener la señal del pin de un chip que tiene interno, que es el que decodifica de PPM a PWM a cada canal. la ventaja del PPM es que con 1 entrada digital obtienes los valores de todos los canales. con PWM obtienes el valor de 1 solo canal por lo que necesitas tantas entradas digitales como canales tenga tu radio .

Code: [Select]
#define channumber 6 //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[i]=pulseIn(4, HIGH);
    }
    for(int i = 0; i <= channumber-1; i++) //Promedia los pulsos/Average the pulses
    {
if((channel[i] > 2000) || (channel[i] <100))//Si se pasa del rango envia ultimo pulso/ If channel > max range, chage the value to the last pulse
{
channel[i]= lastReadChannel[i];
}
else
{
channel[i]=(lastReadChannel[i]+channel[i])/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[i]);
  lastReadChannel[i]=channel[i];
}
if(channel[4] > 1000) //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.
    }
  }


a ver si te encuentro lo otro ...

SrDonGato

Code: [Select]

// ******************
// rc functions
// ******************
#define MINCHECK 1100
#define MAXCHECK 1900

static uint8_t pinRcChannel[8] = {ROLLPIN, PITCHPIN, YAWPIN, THROTTLEPIN, AUX1PIN,AUX2PIN,CAM1PIN,CAM2PIN};
volatile uint16_t rcPinValue[8] = {1500,1500,1500,1500,1500,1500,1500,1500}; // interval [1000;2000]
static int16_t rcData[8] ; // interval [1000;2000]
static int16_t rcCommand[4] ; // interval [1000;2000] for THROTTLE and [-500;+500] for ROLL/PITCH/YAW
static int16_t rcHysteresis[8] ;
static int16_t rcData4Values[8][4];

static uint8_t rcRate8;
static uint8_t rcExpo8;
static float rcFactor1;
static float rcFactor2;

// ***PPM SUM SIGNAL***
#ifdef SERIAL_SUM_PPM
static uint8_t rcChannel[8] = {SERIAL_SUM_PPM};
#endif
volatile uint16_t rcValue[8] = {1500,1500,1500,1500,1500,1500,1500,1500}; // interval [1000;2000]

// Configure each rc pin for PCINT
void configureReceiver() {
  #ifndef SERIAL_SUM_PPM
    for (uint8_t chan = 0; chan < 8; chan++)
      for (uint8_t a = 0; a < 4; a++)
        rcData4Values[chan][a] = 1500; //we initiate the default value of each channel. If there is no RC receiver connected, we will see those values
    #if defined(PROMINI)
      // PCINT activated only for specific pin inside [D0-D7]  , [D2 D4 D5 D6 D7] for this multicopter
      PORTD   = (1<<2) | (1<<4) | (1<<5) | (1<<6) | (1<<7); //enable internal pull ups on the PINs of PORTD (no high impedence PINs)
      PCMSK2 |= (1<<2) | (1<<4) | (1<<5) | (1<<6) | (1<<7);
      PCICR   = 1<<2; // PCINT activated only for the port dealing with [D0-D7] PINs
    #endif
    #if defined(MEGA)
      // PCINT activated only for specific pin inside [A8-A15]
      DDRK = 0;  // defined PORTK as a digital port ([A8-A15] are consired as digital PINs and not analogical)
      PORTK   = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7); //enable internal pull ups on the PINs of PORTK
      PCMSK2 |= (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7);
      PCICR   = 1<<2; // PCINT activated only for PORTK dealing with [A8-A15] PINs
    #endif
  #else
    PPM_PIN_INTERRUPT
  #endif
}

#ifndef SERIAL_SUM_PPM
ISR(PCINT2_vect) { //this ISR is common to every receiver channel, it is call everytime a change state occurs on a digital pin [D2-D7]
  uint8_t mask;
  uint8_t pin;
  uint16_t cTime,dTime;
  static uint16_t edgeTime[8];
  static uint8_t PCintLast;

  #if defined(PROMINI)
    pin = PIND;             // PIND indicates the state of each PIN for the arduino port dealing with [D0-D7] digital pins (8 bits variable)
  #endif
  #if defined(MEGA)
    pin = PINK;             // PINK indicates the state of each PIN for the arduino port dealing with [A8-A15] digital pins (8 bits variable)
  #endif
  mask = pin ^ PCintLast;   // doing a ^ between the current interruption and the last one indicates wich pin changed
  sei();                    // re enable other interrupts at this point, the rest of this interrupt is not so time critical and can be interrupted safely
  PCintLast = pin;          // we memorize the current state of all PINs [D0-D7]

  cTime = micros();         // micros() return a uint32_t, but it is not usefull to keep the whole bits => we keep only 16 bits
 
  // mask is pins [D0-D7] that have changed // the principle is the same on the MEGA for PORTK and [A8-A15] PINs
  // chan = pin sequence of the port. chan begins at D2 and ends at D7
  if (mask & 1<<2)           //indicates the bit 2 of the arduino port [D0-D7], that is to say digital pin 2, if 1 => this pin has just changed
    if (!(pin & 1<<2)) {     //indicates if the bit 2 of the arduino port [D0-D7] is not at a high state (so that we match here only descending PPM pulse)
      dTime = cTime-edgeTime[2]; if (900<dTime && dTime<2200) rcPinValue[2] = dTime; // just a verification: the value must be in the range [1000;2000] + some margin
    } else edgeTime[2] = cTime;    // if the bit 2 of the arduino port [D0-D7] is at a high state (ascending PPM pulse), we memorize the time
  if (mask & 1<<4)   //same principle for other channels   // avoiding a for() is more than twice faster, and it's important to minimize execution time in ISR
    if (!(pin & 1<<4)) {
      dTime = cTime-edgeTime[4]; if (900<dTime && dTime<2200) rcPinValue[4] = dTime;
    } else edgeTime[4] = cTime;
  if (mask & 1<<5)
    if (!(pin & 1<<5)) {
      dTime = cTime-edgeTime[5]; if (900<dTime && dTime<2200) rcPinValue[5] = dTime;
    } else edgeTime[5] = cTime;
  if (mask & 1<<6)
    if (!(pin & 1<<6)) {
      dTime = cTime-edgeTime[6]; if (900<dTime && dTime<2200) rcPinValue[6] = dTime;
    } else edgeTime[6] = cTime;
  if (mask & 1<<7)
    if (!(pin & 1<<7)) {
      dTime = cTime-edgeTime[7]; if (900<dTime && dTime<2200) rcPinValue[7] = dTime;
    } else edgeTime[7] = cTime;
  #if defined(MEGA)
    if (mask & 1<<0)   
      if (!(pin & 1<<0)) {
        dTime = cTime-edgeTime[0]; if (900<dTime && dTime<2200) rcPinValue[0] = dTime;
      } else edgeTime[0] = cTime;
    if (mask & 1<<1)     
      if (!(pin & 1<<1)) {
        dTime = cTime-edgeTime[1]; if (900<dTime && dTime<2200) rcPinValue[1] = dTime;
      } else edgeTime[1] = cTime;
    if (mask & 1<<3)
      if (!(pin & 1<<3)) {
        dTime = cTime-edgeTime[3]; if (900<dTime && dTime<2200) rcPinValue[3] = dTime;
      } else edgeTime[3] = cTime;
  #endif
}

#else
void rxInt() {
  uint16_t now,diff;
  static uint16_t last = 0;
  static uint8_t chan = 0;

  now = micros();
  diff = now - last;
  last = now;
  if(diff>5000) chan = 0;
  else {
    if(900<diff && diff<2200 && chan<8 ) rcValue[chan] = diff;
    chan++;
  }
}
#endif

uint16_t readRawRC(uint8_t chan) {
  uint16_t data;
  uint8_t oldSREG;
  oldSREG = SREG;
  cli(); // Let's disable interrupts
  #ifndef SERIAL_SUM_PPM
    data = rcPinValue[pinRcChannel[chan]]; // Let's copy the data Atomically
  #else
    data = rcValue[rcChannel[chan]];
  #endif
  SREG = oldSREG;
  sei();// Let's enable the interrupts
  return data; // We return the value correctly copied when the IRQ's where disabled
}
 
void computeRC() {
  static uint8_t rc4ValuesIndex = 0;
  uint8_t chan,a;

  rc4ValuesIndex++;
  for (chan = 0; chan < 8; chan++) {
    rcData4Values[chan][rc4ValuesIndex%4] = readRawRC(chan);
    rcData[chan] = 0;
    for (a = 0; a < 4; a++)
      rcData[chan] += rcData4Values[chan][a];
    rcData[chan]= (rcData[chan]+2)/4;
    if ( rcData[chan] < rcHysteresis[chan] -4)  rcHysteresis[chan] = rcData[chan]+2;
    if ( rcData[chan] > rcHysteresis[chan] +4)  rcHysteresis[chan] = rcData[chan]-2;
  }
  #if defined(FORCE_LEVEL)
    rcData[AUX1] = 2000;
  #endif
}



los valores de los canales los guarda en rcData[chan] siendo chan el número de canal .


Si quieres hacer el quadcopter y no tienes mucha idea de programacion lo vas a tener complicado. mirate el wiicopter , funcina muy bien , los sensores son baratos ( los de la wii) y ya tienes el codigo hecho, ademas un software para ver el estado de los sensores y motores, posicion del aparato etc.

un saludo

adrib

Ya he conseguido leer un dato proporcional a la acción sobre la emisora, gracias por todo y disculpa las molestias SrDonGato la inforamación que me has dado me ha sido muy útil para solucionar el problema.

PD: Gracias también a los demás por vuestras aportaciones.

Cheyenne

SrDonGato, te veo puesto en el tema, cuando menos lo has usado y practicado. Aprovecho para hacerte unas consultas. Decirte que ahora estoy escribiendo desde un móvil y no veo las ventanas de código enteras (no me aparecen las barras de desplazamiento).

Entiendo que el primer código que has puesto lee PPM y el segundo no tengo claro si es el del proyecto wiicopter y por tanto está preparado para leer tanto PPM como PWM tal como decías más arriba.

Además de la diferencia de necesitar un sólo pin para PPM (ventaja para este método) pero no tener que acceder al interior del receptor y localizar la señal PPM en el caso de las PWM (ventaja para este otro método), ¿sabes o has notado si uno u otro método tiene más precisión, fiabilidad, o menor exigencia del arduino?

Sobre el proyecto del wiicopter comentas que lo hiciste. Una duda. ¿Todos los cálculos se realizan sobre una sóla tarjeta arduino? Entiendo que en este proyecto hacen todo, el IMU con los acelerómetros y gyros aplicando no sé si filtro Kalman o sistema de cosenos directores, lectura de canales RC y cálculos PID. No sé si me dejo algún otro cálculo que exija en gran medida a arduino.
http://cuadricopterodiyarduino.blogspot.com/

SrDonGato


disculpa las molestias SrDonGato



No son mmolestias atrib ¡¡ mas que ponemos soluciones y no las miráis, estamos para ayudar :) para cuando querais

Cheyenne, la placa de arduino hace todo, lee la radio, lee los sensores a traves de I2C, los acelerometros, giroscopos, sensores barométricos etc etc.

el codigo tiene la particularidad de que es configurable para cualquier modelo, activas y desactivas opciones al principio del codigo segun lo tengas construido, tiene en cuenta las tensiones de las celdas de las lipos, un pequeño zumbador etc.

solo la placa de aruino hace todo, todos los calculos y demas. hay muchos videos en youtube y puedes ver los resultados de como vuelan. yo aun no he conseguido poner bien los parametros pid bien, ademas lo tengo parado desde que se me rompieron las helices, estoy esperando un nuevo pedido porque solas me salen por un ojo la cara.

Sin saber mucho de programacion ( yo tampoco soy un gurú)  es fácil el montaje y la configuracion del mismo a traves el programa que hn hecho a tal efecto, y puedes ver los valores de las configuraciones, los valores de los sticks y los valores comandados a los motores.

se han currado mucho el codigo .

un saludo ¡

Go Up