Go Down

Topic: Secuenciador de transmisión (Read 2173 times) previous topic - next topic

EA1RJ

Hola,

Soy Ricardo, Radioaficionado (EA1RJ) y charreador nato :)

Anteriormente he hecho bastantes circuitos con pics pero sin programar nada, ahora con arduino y entorno en C me defiendo un poco, pero muy poco.

Mi intención es hacer un secuenciador de transmisión que active y desactive varios componentes de una estación de radioaficionado cuando el PC de la orden de transmisión.

Este circuito lo tengo hecho con un LM724 con 4 operacionales pero quiero hacerlo mas versátil con arduino, os adjunto el enlace de un vídeo del secuenciador que tengo en funcionamiento para ver como funciona:

http://www.youtube.com/watch?v=DvugGlLEB0w

La cuestión es que he intentado programar el arduino con varios códigos, empece con estructuras if-else, después con switch, después con arrays pero no doy con ello para que una vez que empezamos la secuencia, si deja de estar activada la entrada que dispara la secuencia, vuelva para atrás en orden inverso. Os agradecería mucho cualquier ayuda.

Antes de poner el código, el funcionamiento del secuenciador es que cuando se da la orden de transmisión, el transmisor no empieza a transmitir directamente, sino que desactiva un amplificador de antena, cambia el estado de unos reles, activa el amplificador de potencia y finalmente pone el equipo en transmisión.

Gracias,
Ricardo EA1RJ


int ledPins[] = { 2, 3, 4, 5 };       // an array of pin numbers to which LEDs are attached
int pinCount = 4;           // the number of pins (i.e. the length of the array)
int LNAPin = 2;
int RELAYPin = 3;
int PAPin = 4;
int PTTPin = 5;
int PCPin = 11;
int wait=0;
int retrasoTX=0;
int retrasoRX=0;

void setup() {
  // the array elements are numbered from 0 to (pinCount - 1).
  // use a for loop to initialize each pin as an output:
  for (int thisPin = 0; thisPin < pinCount; thisPin++)  {
    pinMode(ledPins[thisPin], OUTPUT);     
  }
  pinMode(LNAPin, OUTPUT);   
  pinMode(RELAYPin, OUTPUT);   
  pinMode(PAPin, OUTPUT);     
  pinMode(PTTPin, OUTPUT);
  pinMode(PCPin, INPUT);   
  setstate(LOW, HIGH, HIGH, HIGH);
  wait=LOW;
}

void loop()
{
  retrasoTX=300;
  retrasoRX=150;

  if (digitalRead(PCPin) == LOW && wait == LOW)
  { 
    for (int thisPin = 0; thisPin < pinCount; thisPin++) {
      digitalWrite(ledPins[thisPin], HIGH);
      delay(retrasoTX);
      // ¿llamar a una función que compruebe que PCPin sigue en LOW para pasar al siguiente pin y sino volver para atras?     
      wait=HIGH;
    }
  }
 
  if (digitalRead(PCPin) == LOW && wait == HIGH)
  {
     setstate(HIGH, LOW, LOW, LOW);
  }
     
  if (digitalRead(PCPin) == HIGH && wait == HIGH)
  { 
    for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) {
      digitalWrite(ledPins[thisPin], LOW);
      delay(retrasoRX);
      wait=LOW;
    }
  }

  if (digitalRead(PCPin) == HIGH && wait == LOW)
  {
     setstate(LOW, HIGH, HIGH, HIGH);
  }
}


void setstate(int LNA, int RELAY, int PA, int PTT)
{
  digitalWrite(LNAPin, LNA);
  digitalWrite(RELAYPin, RELAY);
  digitalWrite(PAPin, PA);
  digitalWrite(PTTPin, PTT);
}

Por que las tijeras no solo sirven para cortar!!  :*

Si tu código es como creo que es, con un break dentro del for() sales del bucle, posiblemente tengas que hacer algún retoque más al código para que funcione como quieres pero lo puedes conseguir.

Marcial

Buenas Ricardo, no acabo de entender lo que quieres hacer, pero si me lo explicas mejor intento echarte una mano.

EA1RJ

Hola, feliz año y gracias por vuestras respuestas,

Intentare explicar mejor lo que quiero hacer:

Con un pin como input se arranca una secuencia de encendido de por ejemplo 4 leds pero una vez encendido uno y antes de encender el siguiente led, hay que comprobar que la señal que inicial la secuencia (input) sigue activada, y en el caso de que ya no esté activada, no se enciende el siguiente led y los que se han encendido se van apagando retrocediendo en la secuencia.

por ejemplo, se activa la secuencia y no se desactiva en un tiempo, entonces se encienden, led1,led2,led3 y led4, cuando se desactiva el input, se empiezan a apagar los led, primero led4, luego led3,led2,led1.

del mismo modo si la señal que activa la secuencia, cesa antes de que se complete, pues hace lo mismo pero desde el led al que llego la secuencia, ejemplo:

input en high, enciende led1, led 2 y si el imput va a LOW, apaga 2, apaga 1.

Este sketch lo hace pero no interrumpe la secuencia:

// Secuenciador

int LNAPin = 2;
int RELAYPin = 3;
int PAPin = 4;
int PTTPin = 5;
int PCPin = 12;
//int CWPin = 11;
//int MICPin = 12;
int retrasoTX=0;
int retrasoRX=0;
int wait=LOW;
 
void setup()                   
{
  pinMode(LNAPin, OUTPUT);   
  pinMode(RELAYPin, OUTPUT);   
  pinMode(PAPin, OUTPUT);     
  pinMode(PTTPin, OUTPUT);
  pinMode(PCPin, INPUT);   
  //pinMode(CWPin, INPUT);   
  //pinMode(MICPin, INPUT);
  setstate(LOW, HIGH, HIGH, HIGH);
}

void loop()                   
{
  retrasoTX=500;
  retrasoRX=250;
 
  if (digitalRead(PCPin) == LOW)
  {
     if (wait == LOW)
     {
     setstate(HIGH, LOW, HIGH, HIGH);
     delay(retrasoTX);
     setstate(HIGH, LOW, LOW, HIGH);
     delay(retrasoTX);
     setstate(HIGH, LOW, LOW, LOW);
     delay(retrasoTX);
     wait=HIGH;
     }
     else if (wait == HIGH)
     {
     setstate(HIGH, LOW, LOW, LOW);
     } 
  }
  else if (digitalRead(PCPin) == HIGH)
  {
    if (wait == HIGH)
    {
      setstate(HIGH, LOW, LOW, HIGH);
      delay(retrasoRX);
      setstate(HIGH, LOW, HIGH, HIGH);
      delay(retrasoRX);
      setstate(LOW, HIGH, HIGH, HIGH);
      delay(retrasoRX);
      wait=LOW;
    }
    else if (wait == LOW)
    {
      setstate(LOW, HIGH, HIGH, HIGH);
    }
  }
}


void setstate(int LNA, int RELAY, int PA, int PTT)
{
  digitalWrite(LNAPin, LNA);
  digitalWrite(RELAYPin, RELAY);
  digitalWrite(PAPin, PA);
  digitalWrite(PTTPin, PTT);
}

En uno de mis primeros intentos, hice un código con estructuras IF que comprobaban que se podía pasar al siguiente paso y en caso contrario GOTO  pero el código era un tanto caótico, si queréis os lo pongo.

Gracias por vuestro interes.

_jose_

#4
Jan 02, 2014, 04:49 pm Last Edit: Jan 02, 2014, 05:38 pm by _jose_ Reason: 1
No se si he pillado bien del todo la idea te pongo codigo y lo que hace (o deberia hacer no lo he probado es solo para
mostrar como lo veo yo...).Se trata de que en cada iteracion del loop principal primero se comprueba si el pin de entrada
esta a high o low.mientras la entrada este en high y no se haya llegado al ultimo led ira encendiendo el led siguiente .cuando la entrada pase a low ira apagando los leds desde el ultimo que hubiera encendido de forma decreciente hasta que apague el primero. Alomejor hay que corregir alguna
cosilla pero se ve la "filosofia".
Code: [Select]

// constantes
const int PIN_PC = 12;
//variables
int arrayPin[4] = {2,3,4,5};
boolean activo = false;
int posActual = 0;
int contador;

void setup() {
 for (contador=0;contador<4;contador ++) {
   pinMode(arrayPin[contador],OUTPUT);  
   digitalWrite (arrayPin[contador],LOW);
 }
 pinMode(PIN_PC, INPUT);  
}

void loop() {
  activo = (digitalRead(PIN_PC) == HIGH) ? true : false;
  if  (activo) {
    if (posActual < 4) {
       digitalWrite(arrayPin[posActual],HIGH);
       posActual ++;
    }
  }
  else {
     if (posActual >= 0) {
       digitalWrite(arrayPin[posActual],LOW);
       posActual --;
    }
  }
}

Marcial

Hay que mantener input a high antes de  iniciar ?
Hay que distanciar las salidas en el tiempo? si es así con delay() o tiene q seguir corriendo el programa?
si estando input a high pasa a low e inicia la secuencia de desactivar, y pasa de nuevo a high que tiene que hacer?

_jose_

De entrada el codigo que he puesto antes tiene un fallo ya que cuando posActual no cumple las condiciones se sigue
incrementando o decrementando llegando a valer 4 o -1 y falla el digitalWrite(arrayPin[posActual],HIGH) cuando posActual
llega a 4 y digitalWrite(arrayPin[posActual],LOW) cuando posActual llega a -1.   A ver si en la version 1.2 sale mejor.......

_jose_

#7
Jan 02, 2014, 09:02 pm Last Edit: Jan 02, 2014, 09:45 pm by _jose_ Reason: 1
bueno pues otra vuelta de tuerca en principio tiene un delay de un segundo entre cada lectura de la señal y lo dicho no lo he probado no se si funcionara......
Code: [Select]
// constantes

const int PIN_PC = 12;

//variables

int arrayPin[4] = {2,3,4,5};
boolean activo = false;
boolean limSup = true;
boolean limInf = false;
int posActual = 0;
int contador;

void setup() {
 for (contador=0;contador<4;contador ++) {
   pinMode(arrayPin[contador],OUTPUT);  
   digitalWrite (arrayPin[contador],LOW);
 }
 pinMode(PIN_PC, INPUT);  
}

void loop() {
  activo = (digitalRead(PIN_PC) == HIGH) ? true : false;
  if  (activo == true &&  limSup == true) {
    if (posActual == 3 ){
      limSup = false;
      digitalWrite(arrayPin[posActual],HIGH);
    }
    else {digitalWrite(arrayPin[posActual],HIGH);posActual ++;}
    limInf = true;
  }
  if (activo == false && limInf == true){
    if (posActual == 0) {
      limInf = false;
      digitalWrite(arrayPin[posActual],HIGH);
    }
    else {digitalWrite(arrayPin[posActual],LOW);posActual --; }
    limSup = true;
  }
  delay(1000);
}


EA1RJ

Hola Jose,

Gracias por tu sketch,  hace correctamente la secuencia, pero he tenido que cambiar una cosilla por que en el void setup se ponen todas las salidas en LOW pero una vez que se inicia la secuencia, el estado del pin2 siempre se queda en HIGH .

Lo que he cambiado es HIGH por LOW en esta parte del codigo:

if (activo == false && limInf == true){
     if (posActual == 0) {
       limInf = false;
       digitalWrite(arrayPin[posActual],LOW);  // ponia HIGH y lo he cambiado por LOW

Voy a ver si se puede hacer de forma sencilla (como con una puerta lógica NOT) que la salida del pin2 (posActual==0 creo) este invertida respecto al resto, si os fijais en el video de youtube que subi antes, el 1er rele (el del preamplificador de antena o LNA) está en un estado lógico inverso al resto de reles.

Para marcial:

// Hay que mantener input a high antes de  iniciar ?

No, el imput al pasar a HIGH inicia la secuencia, si pasa a low se avandona el encendido pero deshaciendo el camino.

// Hay que distanciar las salidas en el tiempo? si es así con delay() o tiene q seguir corriendo el programa?

No entiendo bien la pregunta, con el Delay que ha puesto Jose va bien,

// si estando input a high pasa a low e inicia la secuencia de desactivar, y pasa de nuevo a high que tiene que hacer?

Continuar la secuencia de encendido desde donde se quedo cuando iba apagando.

Gracias de nuevo.

EA1RJ - Ricardo




_jose_

#9
Jan 04, 2014, 08:17 pm Last Edit: Jan 04, 2014, 08:24 pm by _jose_ Reason: 1
Bueno version 1.3 con otra manera de hacerlo.el primer codigo esta hecho para simular la secuencia con el serial monitor ,funciona introduciendo un s para activar la secuencia y una b para desactivarla.cuando pulsas s la señal se mantiene activa hasta que pulses b y viversa cuando pulsas b esta inactiva hasta que  vuelvas a pulsar b.el segundo codigo es el mismo pero para funcionar normalmente.
Code: [Select]

//-----------------------------------------------constantes---------------------------------------------------------------
const int PIN_PC = 12;
//-----------------------------------------------variables----------------------------------------------------------------

int arrayPin[4] = {2,3,4,5};
boolean arrayEstado[4] = {false,false,false,false};
boolean activo = false;
int cont;
char orden;
//------------------------------------------------setup()-----------------------------------------------------------------
void setup() {
 Serial.begin(9600);
 for (cont=0;cont<4;cont ++) {
   pinMode(arrayPin[cont],OUTPUT);  
   digitalWrite (arrayPin[cont],LOW);
 }
 pinMode(PIN_PC, INPUT);  
}
//-------------------------------------------------loop()-----------------------------------------------------------------
void loop() {
  //activo = (digitalRead(PIN_PC) == HIGH) ? true : false;
  if(Serial.available()>0){orden=Serial.read();if(orden=='s'){activo=true;}else if(orden=='b'){activo=false;};}
  if  (activo) {
    for (cont=0;cont<4;cont++){
      if(arrayEstado[cont]==false){
        digitalWrite(arrayPin[cont],HIGH);
        arrayEstado[cont]=true;
        Serial.print("Pin salida ");Serial.print(arrayPin[cont]);Serial.println(" a HIGH");
        break;
      }
      else{continue;}
    }
  }
  else {
    for (cont=3;cont>=0;cont--){
      if(arrayEstado[cont]==true){
        digitalWrite(arrayPin[cont],LOW);
        arrayEstado[cont]=false;
        Serial.print("Pin salida ");Serial.print(arrayPin[cont]);Serial.println(" a LOW");
        break;
      }
      else{continue;}
    }
  }
  delay(2000);
}


Y el definitivo:
Code: [Select]

//-----------------------------------------------constantes---------------------------------------------------------------
const int PIN_PC = 12;
//-----------------------------------------------variables----------------------------------------------------------------

int arrayPin[4] = {2,3,4,5};
boolean arrayEstado[4] = {false,false,false,false};
boolean activo = false;
int cont;
//------------------------------------------------setup()-----------------------------------------------------------------
void setup() {
 for (cont=0;cont<4;cont ++) {
   pinMode(arrayPin[cont],OUTPUT);  
   digitalWrite (arrayPin[cont],LOW);
 }
 pinMode(PIN_PC, INPUT);  
}
//-------------------------------------------------loop()-----------------------------------------------------------------
void loop() {
  activo = (digitalRead(PIN_PC) == HIGH) ? true : false;
  if  (activo) {
    for (cont=0;cont<4;cont++){
      if(arrayEstado[cont]==false){
        digitalWrite(arrayPin[cont],HIGH);
        arrayEstado[cont]=true;
        break;
      }
      else{continue;}
    }
  }
  else {
    for (cont=3;cont>=0;cont--){
      if(arrayEstado[cont]==true){
        digitalWrite(arrayPin[cont],LOW);
        arrayEstado[cont]=false;
        break;
      }
      else{continue;}
    }
  }
  delay(2000);
}

Marcial

#10
Jan 04, 2014, 11:11 pm Last Edit: Jan 04, 2014, 11:19 pm by Marcial Reason: 1
No tengo circuito en casa para probar, pero por curiosidad prueba lo tu y dime.
Ponle los pines  y el tiempo de demora que uses

La pregunta sobre delay, me refería a que si la demora sirve con delay o tenia que ser sin el para que la ejecución del programa continúe. La diferencia esta en que con delay si estas iniciando la secuencia, mientras estas "esperando", si desaparece la señal de inicio, el pin seguirá activo hasta que finalice el delay, y viceversa al desconectar, no se si puede suponer problema

Code: [Select]
byte Entrada=12;                                 // Pin señal inicio
byte Pin_Out[]={2,3,4,5};                        // Pines de salida
boolean Senal;                                   // Para amecenar el estado de la entrada
unsigned long T_Espera=1000;                     // Tiempos de espera tras cada señal
int Pin=0;

void setup()
{  
 pinMode (Entrada, INPUT);                      // Establecer pines de entrada
 for (int x=0;x<4;x++)
 {
   pinMode (Pin_Out[x], OUTPUT);                // Establecer pines de salida
   digitalWrite(Pin_Out[x], LOW);               // Pines de salida a low para iniciar programa
 }
}

void loop()
{
 Senal=digitalRead(Entrada);                  // Almacenar el estado del pin de entrada  
 if (Senal && Pin<4)                          // Tenemos señal de encender y no esta todo encendido
 {
   digitalWrite(Pin_Out[Pin],HIGH);           // Activar pin
   delay(T_Espera);                           // Tiempo de espera
   Pin++;                                     // Siguiente pin
 }  
 else if (!Senal && Pin>0)                    // No hay señal y no hemos desconectado todo
 {
   Pin --;                                    // Anterior pin
   digitalWrite(Pin_Out[Pin],LOW);            // Desactivar pin
   delay(T_Espera);                           // Tiempo de espera
 }
}


Jose: mi profesor de metodología (dios lo tenga en su gloria por los siglos de los siglos)  siempre decía que en cualquier programa y cualquier lenguaje "break=0"  (entendamos lo bien, el break en el código y el 0 en la evaluación) y desde esa me producen urticaria  :)

noter

Marcial:
Me has quitado la palabra de la boca. Estaba escribiendo un código idéntico (salvando los nombres de las variables). Creo que más sencillo ya no se puede hacer. Tu profesor de metodología te enseñó bien.  :)
Eso sí, tampoco hay que ser "fundamentalistas anti-break", porque ya me dirás en un switch - case qué hacemos.  XD


Marcial

Noter:
En los case se usa por  imperativo legal.  :P, y que conste que intento evitar el uso de case

Ricardo:

Una modificación recomendable para el uso de relés, para activar seles con 0 o 1:

Code: [Select]
#define ON HIGH                                  // Cambiar aqui para logica positiva/negativa
#define OF LOW                                   // Cambiar aqui para logica positiva/negativa
byte Entrada=12;                                 // Pin señal inicio
byte Pin_Out[]={2,3,4,5};                        // Pines de salida
boolean Senal;                                   // Para amecenar el estado de la entrada
unsigned long T_Espera=1000;                     // Tiempos de espera tras cada señal
int Pin=0;

void setup()
{   
  pinMode (Entrada, INPUT);                      // Establecer pines de entrada
  for (int x=0;x<4;x++)
  {
    pinMode (Pin_Out[x], OUTPUT);                // Establecer pines de salida
    digitalWrite(Pin_Out[x], OF);               // Pines de salida a low para iniciar programa
  }
}
void loop()
{
  Senal=digitalRead(Entrada);                  // Almacenar el estado del pin de entrada 
  if (Senal && Pin<4)                          // Tenemos señal de encender y no esta todo encendido
  {
    digitalWrite(Pin_Out[Pin],ON);             // Activar pin
    delay(T_Espera);                           // Tiempo de espera
    Pin++;                                     // Siguiente pin
  } 
  else if (!Senal && Pin>0)                    // No hay señal y no hemos desconectado todo
  {
    Pin --;                                    // Anterior pin
    digitalWrite(Pin_Out[Pin],OF);             // Desactivar pin
    delay(T_Espera);                           // Tiempo de espera
  }
}


Por cierto, las tarjetas que muestras en el vídeo las has hecho tu?
Si es así, mis honorarios por la programacion : HEEEEEEELP  =(
Seis intentos con una tarjeta y no lo consegui  =(

pacooca

Un saludo de EB2AIC, ya somo mas de uno los que andamos cacharreando con arduino y nuestros equipos de radio....

pacooca

Un par de preguntas ester circuito que hace esactamente, ir dandole más potencia al ampli? para que no cargue toda la potencia de golpe?

Por que no conbiene utilizar los case y los break?

Go Up