Go Down

Topic: Conversor de RF a CC y control de servos. (Read 1 time) previous topic - next topic

surbyte

Repito son dos antenas.. Una busca la mejor sintonia y ese dato se lo pasa a la segunda.
Luego me pondre con un código que tenga dos servos y posicione como una antena parabolica que gira en la base y en azimuth

Maniaquera

Le he estado intentando hacer funcionar toda la mañana y la verdad que no se si estaré haciendo algo mal pero no me funciona.  El sketch se carga bien y el pineado es correcto, las lecturas de voltaje las hace bien y la conversión también pero ninguno de los servos continua haciendo el seguimiento solo se ponen a 0 y 90 y hay termina. Muevo el potenciometro y nada. Si pongo
Code: [Select]
  for (i=0; i=179; i = i + direccion) {         // ciclo de barrida corresponde a los pasos del servo (180 grados)
      servoScan.write(i);                       // Posiciono el servo
      delay(50);                                // Espero a que se posicione
Serial.println (i);

pone que "i" vale 179  cuando tendría que valer la primera vez 1 ¿no?

surbyte

#17
Oct 13, 2017, 02:39 pm Last Edit: Oct 13, 2017, 02:41 pm by surbyte
Hasta ahora me doy cuenta con tu comentario.
Como pretendes que una lectura que polar o sea depende del ángulo sea simulada con un potenciometro que te da una respuesta constante en cada ángulo donde la interrogas?

Por lo visto no tienes idea de cómo funciona!!
Esto es asi... supongamos que tu Radio Control esta justo a los 90 grados.
Tu conversor RF dará respuesas muy bajas  a ambos lados de esa posición de 90 y a medida que se aproxime a 90 imagina esto:
 


Esta es la antena que emite y se ve el lóbulo que es lo que buscas. Pero solo veras ese lóbulo cuando estes apuntando al emisor. Mientras recibes ruido o nada.

Entonces un potenciómetro no sirve para simularlo.

surbyte

Tengo una pregunta. Que servos estas usando, necesito saber la respuesta que tienen a una orden. O sea cuanto demoran en posicionarse.
Se me ocurre un modo de hacerlo basado en tiempos y tareas. Lo estoy concibiendo a ver que resulta.
Esto hecho con dos Servos como te dije originalmente, uno mueve horizontal y el otro vertical.

Maniaquera

Los servos:

0.3 segundos/60 grados



El tema del potenciometro:

El converso tendrá conectada una antena direccional y el transmisor (avión) una omni.

Cuando apunte la antena del conversor al avión directamente me dará un voltaje, imaginemos 2V, que va conectado a la entrada analógica. Si muevo la antena este bajara tanto como disminuya la potencia de la señal y subirá al volver a apuntar a al avión. Como el avión esta en movimiento el valor nunca sera fijo.

Por tanto, si uso un potenciometro conectado a la entrada analógica y aumento o disminuyo el valor continuamente  se varia el voltaje, que es el valor por el cual tengo mayor o menor potencia simulada o no de señal. Los servos se deberían mover para intentar llegar siempre a obtener el mayor voltaje aunque no estén apuntando a nada ya que no hace falta. Todo esto es para testar.

Pienso que debería valer.

surbyte

#20
Oct 13, 2017, 05:03 pm Last Edit: Oct 13, 2017, 05:06 pm by surbyte
Bien, gracias por las respuestas.
Vamos de nuevo, a ver si estamos sintonizados del mismo modo

Primero pon una imagen de como tienes dispuestos los servos.
No quiero ponerme a hacer algo para que luego me digas, mis servos no estan dispuestos de ese modo.

Yo hablo de algo asi, un servo muevo horizontal, si es posible 360 grados pero en nuestro caso 180 son suficientes. Y el otro se mueve en altura 0 a 90

Ejemplo de posicionador Antena

Maniaquera


surbyte

Bien que mas vas a usar?
Solo posicionar la antena, es importante esto para considearlo

Maniaquera

#23
Oct 14, 2017, 11:22 am Last Edit: Oct 14, 2017, 10:03 pm by surbyte
Adjunto fotos de la antena y soporte.




surbyte

Ya he terminado el programa. Verifico y lo subo.

surbyte

#25
Oct 14, 2017, 10:59 pm Last Edit: Oct 14, 2017, 11:01 pm by surbyte
Ya he terminado el programa. Verifico y lo subo.

El programa compila. Lo he probado levemente con un simulador y creo que deberia funcionar.

Code: [Select]
#include <Servo.h>

#define verticalServoPin      8
#define horizontalServoPin    9
#define numeroDeMuestrasRSSI 10

#define verticalServo         0
#define horizontalServo       1

// Tracking variables
const unsigned int verticalMin   = 0;     // modificar según criterio
const unsigned int verticalMax   = 90;    // modificar según criterio
const unsigned int verticalMed   = (verticalMin + verticalMax) / 2;

const unsigned int horizontalMin = 10;    // modificar según criterio
const unsigned int horizontalMax = 170;   // modificar según criterio
const unsigned int horizontalMed = (horizontalMin + horizontalMax) / 2;

const int rssiTrackPin           = A0;
byte rssiDelta            = 0;

const byte toleranciaHorizontal  = 2;
const byte valorUmbral           = 80;
const byte minValorTracking      = 60;

const byte longVector            = 15;
const byte rssiIndice            = 0;
const byte verticalIndice        = 1;
const byte horizontalIndice      = 2;
byte rssiTrackingMatriz[longVector][horizontalIndice + 1];
byte rssiTrackingContador        = 0;
bool isRSSITrackingParado               = false;

byte i                           = horizontalMed;
byte y                           = verticalMed;

byte direccionHorizontal         = 0;   // pensado para uso en monitor serie o LCD
byte direccionVertical           = 0;   // pensado para uso en monitor serie o LCD
byte rssiTrack                   = 0;
byte rssiTrackOld                = 0;
int calibrateTrack               = 0;
int calibrateFix                 = 0;

byte comandosServo[2]            = { verticalMed, horizontalMed };
byte comandosServoAnterior[2]    = { 0, 0 };

Servo VerticalServo;
Servo HorizontalServo;

// Variables principales
byte frameContador               = 0;
unsigned long TiempoAnterior     = 0;
unsigned long TiempoActual       = 0;
unsigned long variacionDeTiempo  = 0;

#define Tarea_50HZ   2
#define Tarea_10HZ   10
#define Tarea_5HZ    20
#define Tarea_1HZ    100

void calculateRSSIDiff() {
  rssiDelta = rssiTrack - rssiTrackOld;

  if (rssiDelta < 0) {
      rssiDelta *= -1;
  }
}

void trackHorizontal() {
  if (rssiTrack > rssiTrackOld) {
      if (direccionHorizontal == 'L') {
          i += 10;
          direccionHorizontal = 'L';
      }
      else {
          i -= 10;
          direccionHorizontal = 'R';
      }
  }
  else {
    if (direccionHorizontal == 'R') {
        i += 10;
        direccionHorizontal = 'L';
    }
    else {
        i -= 10;
        direccionHorizontal = 'R';
    }
  }

  if (i <= horizontalMin || i >= horizontalMax) {
      i = horizontalMed;
      ejecutoComandoServo(horizontalServo, horizontalMed);
      ejecutoComandoServo(verticalServo, verticalMed);
      return;
  }
  ejecutoComandoServo(horizontalServo, i);
}

void trackVertical() {
  if (rssiTrack > rssiTrackOld) {
      if (direccionVertical == 'O') {
          y = y - 5;
          direccionVertical = 'O';
      }
      else {
          y = y + 5;
          direccionVertical = 'U';
      }
  }
  else {
    if (direccionVertical == 'U') {
        y = y - 5;
        direccionVertical = 'O';
    }
    else {
        y = y + 5;
        direccionVertical = 'U';
    }
  }

  if (y <= verticalMin || y >= verticalMax) {
      y = verticalMed;
      ejecutoComandoServo(horizontalServo, horizontalMed);
      ejecutoComandoServo(verticalServo, verticalMed);
      return;
  }

  ejecutoComandoServo(verticalServo, y);
}


void calibrateRSSI() {
  for (byte Contador = 0; Contador < numeroDeMuestrasRSSI; Contador++) {
      calibrateTrack += analogRead(rssiTrackPin);
      delay(50);
  }
  calibrateTrack /= numeroDeMuestrasRSSI;
}


void procesoTracking() {
    if (!isRSSITrackingParado && rssiTrackingContador >= longVector) {
        // Busco el valor RSSI mas alto dentro de los pasados 5 seg y muevo servos a la posicion correspondiente
        byte maxValueIndice = 0;
        byte maxValue = 0;

        for (byte i = 0; i < longVector; i++) {
          if (rssiTrackingMatriz[i][rssiIndice] > maxValue) {
            maxValue = rssiTrackingMatriz[i][rssiIndice];
            maxValueIndice = i;
          }
        }

        ejecutoComandoServo(verticalServo, rssiTrackingMatriz[maxValueIndice][verticalIndice]);
        ejecutoComandoServo(horizontalServo, rssiTrackingMatriz[maxValueIndice][horizontalIndice]);
        isRSSITrackingParado = true;
    }
    else if (!isRSSITrackingParado && rssiTrack <= valorUmbral) {
        calculateRSSIDiff();

        if (rssiDelta <= toleranciaHorizontal) {   // diferencia rssi es menor que la tolerancia?
            if (rssiTrack <= 45) {
                ejecutoComandoServo(verticalServo, verticalMed);

                if (i >= horizontalMed) {
                    i -= 30;
                    direccionHorizontal = 'L';
                }
                else {
                    i += 30;
                    direccionHorizontal = 'R';
                }
            }
            else
                trackVertical();
        }
        else
            trackHorizontal();

        if (rssiTrack <= minValorTracking) {
            // Almaceno el valor RSSI y la posicion correspondiente del servo
            rssiTrackingMatriz[rssiTrackingContador][rssiIndice] = rssiTrack;
            rssiTrackingMatriz[rssiTrackingContador][verticalIndice] = comandosServo[verticalServo];
            rssiTrackingMatriz[rssiTrackingContador][horizontalIndice] = comandosServo[horizontalServo];
            rssiTrackingContador++;
        }
    }
    if (rssiTrack > minValorTracking) {
        // Resetoe el Contador de Seguimiento o rssiTrackingContador y inicio Tracking
        rssiTrackingContador = 0;
        isRSSITrackingParado = false;
    }
}

void ejecutoComandoServo(int servo, unsigned int value) {
  if (servo > horizontalServo) return;

  if (servo == verticalServo) {
    value = constrain(value, verticalMin, verticalMax);
  }
  else if (servo == horizontalServo) {
    value = constrain(value, horizontalMin, horizontalMax);
  }

  comandosServoAnterior[servo] = comandosServo[servo];
  comandosServo[servo] = value;
}

void writeServos() {
  if (comandosServoAnterior[verticalServo] != comandosServo[verticalServo]) {
      VerticalServo.write(comandosServo[verticalServo]);
      comandosServoAnterior[verticalServo] = comandosServo[verticalServo];
  }

  if (comandosServoAnterior[horizontalServo] != comandosServo[horizontalServo]) {
      HorizontalServo.write(comandosServo[horizontalServo]);
      comandosServoAnterior[horizontalServo] = comandosServo[horizontalServo];
  }
}

void readRSSI() {
  rssiTrackOld = rssiTrack;

  rssiTrack = map(analogRead(rssiTrackPin), 0, calibrateTrack, 0, 100);
  rssiTrack = constrain(rssiTrack, 0, 100);                             // limito lectura a 0-100
}

void procesoTarea50Hz() {
  writeServos();
}

void procesoTarea5Hz() {
  readRSSI();
  procesoTracking();
}

//void proceso1HzTarea() {
//  
//}

void setup() {
  VerticalServo.attach(verticalServoPin);
  HorizontalServo.attach(horizontalServoPin);
  writeServos();                          // muevo los servos a posiciones medias en el arranque
  calibrateRSSI();
}

void loop() {
  TiempoActual = micros();
  variacionDeTiempo = TiempoActual - TiempoAnterior;

  if (variacionDeTiempo >= 10000) {
      frameContador++;

      if (frameContador % Tarea_50HZ == 0) {
          procesoTarea50Hz();   // ajusta servos cada 20 mseg
      }

      if (frameContador % Tarea_5HZ == 0) {  
          procesoTarea5Hz();    // calcula RSSI cada 200 mseg
      }

      TiempoAnterior = TiempoActual;
  }

  if (frameContador >= 100) {
      frameContador = 0;
  }
}


Luego te doy una explicación si hace falta pero cuando tengas todo me gustaria que lo pruebes a ver como se comporta.

Te repito, si usas un potenciometro simulando la antena no va a funcionar a menos que restrigieras a ese pote para que de un valor de salida en un angulo determinado.

Maniaquera

Lo probare en unos días e iré comentado los resultados.

Muchas gracias por el esfuerzo.

Maniaquera

#27
Oct 17, 2017, 11:35 pm Last Edit: Oct 17, 2017, 11:46 pm by Maniaquera
Hola.

Ante todo pedir disculpas a surbyte por hacerle perder el tiempo por mi incompetencia.

He hecho una prueba preliminar y a sido un fracaso, pero no porque el sketch estuviera mal, sino por mi culpa, el conversor no funciona como indique.

Este comienza con una tensión de 2.2v para indicar una potencia de -65dbm y va decreciendo a medida que la potencia que recibe aumenta, hasta llegar a 0.5v, que indica 15dbm. Adjunto gráfica:




Al verla pensé que las lineas separadas indicaban la curva pero eran las que van juntas.

Voy a adjuntar el link del data sheet completo por si la estoy liando otra vez.
http://www.analog.com/media/en/technical-documentation/data-sheets/AD8318.pdf

Después de darme cuenta de este fallo he supuesto que el sketch iba a funcionar al revés.

¿Alguna solución?

surbyte

No hay problema, hasta que no se prueban las cosas no se puede ajustar los controles.

El problema es 0.5 a 2.2V un rango limitado, apenas 2.2-0.5= 1.7V de un rango de medicion de 0-5V

Una de dos, o bien mejoramos eso o vemos como mejoramos eso o pruebas que al menos funciona y luego te pones a mejorarlo.

La mejora sería usar un amplificador operacional que le quite 0.5 con lo qu elo llevamos a 0V y una ganancia de 5/1.7 = 2.9 con lo cual tendremos 5V cuando el conversor entregue 2.2V

Luego compatibilizamos todo.

x ahora con lo que esta, hagamos este cambio


El problema esta aca

Code: [Select]
rssiTrack = map(analogRead(rssiTrackPin), 0, calibrateTrack, 0, 100);

calibrateTrack va a tomar entonces el valor de 2.2V
y en lugar de 0 tendria que ser 0.5V
no con estos valores porque estamos con valores del ADC.

Dejame pensarlo. Estoy haciendo otra cosa ahora y no puedo concentrarme en esto.

Go Up