¡Bienvenido visitante ! ¡Apúntate al foro ! ¡Es gratuito !
Aquí encontrarás respuesta a muchas de tus preguntas sobre modelismo ferroviario.
¡Puedes preguntar a tus anchas y aportar tus conocimientos!

MOVIENDO DESVÏOS

Un sitio específico para que cada cual hable de sus proyectos. Así no queda difuminado según el tema por los talleres.
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Hola

Tengo casi terminado un "motor" para mover desvíos basado en un servo bajo el tablero
Dejo unas fotos del primer prototipo, en unos días subiré los ficheros STL para imprimirlo en 3D
He usado un servo SG90 y una corredera para tener un movimiento lineal, el brazo del servo se recorta para dejar solo el 1er agujero donde se inserta un tornillo de M2x10mm, le h eañadido un remache para mejorar el rozamiento.

Un video del funcionamiento

Saludos
Adjuntos
VISTA_3.jpg
VISTA_3.jpg (106.19 KiB) Visto 451 veces
VISTA_2.jpg
VISTA_2.jpg (125.33 KiB) Visto 451 veces
VISTA_1.jpg
VISTA_1.jpg (133.45 KiB) Visto 451 veces
DESPIECE.jpg
DESPIECE.jpg (1.05 MiB) Visto 453 veces
Lenz + 2C + K.Bay
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Hola
Os dejo los ficheros STL por si es de interés de alguien
Saludos
Adjuntos
SG90 Servo holder.zip
(70.93 KiB) Descargado 28 veces
Lenz + 2C + K.Bay
amorrortu
Forero
Mensajes: 80
Registrado: Jue Ene 15, 2009 6:17 am
17
Ubicación: Ibarra-Pais Vasco

Re: MOVIENDO DESVÏOS

Mensaje por amorrortu »

Muchas gracias por la información.
Saludos Luis.
Multimaus,DCC-gen,NanoX-88+Minimaus(ultimo firm),RENFE-H0 y de momento sin maqueta.
Avatar de Usuario
RhB
Forero
Mensajes: 5556
Registrado: Vie Ene 20, 2006 8:57 pm
20
Ubicación: Zaragoza

Re: MOVIENDO DESVÏOS

Mensaje por RhB »

Muy ingenioso Salus. Y más cómodo que los soportes de chapa de aluminio que hice yo.
Saludos.

Manolo
Vivan las motos gordas
gon
Forero
Mensajes: 4084
Registrado: Mié Ene 18, 2006 7:54 am
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por gon »

para quitarse el sombrero.
Sunpongo que la velocidad se prodrá regular a gusto del consumidor

saludos
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Hola
Inicialmente monte estos soportes, van bien y son más sencillos, pero en escala N y vía código 55, la oscilación del alambre hace que sobresalga demasiado, según la posición y qhe algún material rodante roce y descarrile, el ajuste es muy crítico. en H0 no daría ningún problema, pero si en N.
Por ello he pasado al diseño ma´s complejo, pero consiguiendo un desplazamiento lineal
Saludos
Adjuntos
DISEÑO ANTIGUO
DISEÑO ANTIGUO
IMG-1532.jpg (1.13 MiB) Visto 400 veces
Lenz + 2C + K.Bay
Avatar de Usuario
RhB
Forero
Mensajes: 5556
Registrado: Vie Ene 20, 2006 8:57 pm
20
Ubicación: Zaragoza

Re: MOVIENDO DESVÏOS

Mensaje por RhB »

sls_h0e escribió: Lun May 25, 2020 7:36 pm ... pero en escala N y vía código 55, la oscilación del alambre hace que sobresalga demasiado... el ajuste es muy crítico
Muy cierto Salus, doy fe. No con tus soportes, naturalmente, pero sí con los de chapa de aluminio que yo me hice y que tienen el mismo funcionamiento oscilante.
Saludos.

Manolo
Vivan las motos gordas
Avatar de Usuario
palaycarbon
Forero
Mensajes: 615
Registrado: Jue Feb 16, 2006 4:54 pm
20

Re: MOVIENDO DESVÏOS

Mensaje por palaycarbon »

En su día adapté el mecanismo de Melinda (h0-fine.de) para usar servos "grandes". Su sistema está hecho a base de piezas planas y separadores, de los utilizados en electrónica para montar una placa sobre otra.

También incorpora un mecanismo de palanca para girar la señal que indica la posición del cambio de agujas.

Lástima no tener la posibilidad de sacarles una foto. Y como sigamos saturando los bares y zonas de ocio no lo podré hacer en una temporada.
¡Vivan las estaciones sin señales de entrada! :D
fco1306
Forero
Mensajes: 315
Registrado: Jue Sep 25, 2008 3:31 pm
17
Ubicación: Asturias

Re: MOVIENDO DESVÏOS

Mensaje por fco1306 »

Son ferritas lo que aparecen en el cable de los servos para evitar interferencias? ¿de que tipo?
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Lenz + 2C + K.Bay
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Hola a todos/as

Dejé esto a medias por estar con otro "lio", que cerré ayer

Como decoder para controlar servos, además de los comerciales, hay muchos montajes en la web con PIC y con Arduino.
Para mover un servo, he optado por la opción de Arduino, usando el “attiny85” de la familia de micros usados en las placas Arduino, pero con un formato DIL8, programable desde el IDE de Arduino

Desde hace tiempo tenía ganas de usar este micro, poco a poco me metí en ello y este es el resultado, le he llamado SERVO_MOTOR_2020

Aquí está todo lo referente a cómo usar este chip https://teslabem.com/arduino/programar- ... duino-uno/

El montaje se hace sobre un PCB de 35x38 mm, que encaja en el soporte del servo
En un principio el soporte era vertical, aunque simple, lo cambie por los problemas que explico en mi anterior post, cambiando la tapa de la versión final del soporte, el PCB encaja encima, quedando un montaje muy robusto.

En los adjuntos está el esquema y algunas fotos, el proyecto del PCB está aquí https://circuitmaker.com/Projects#/servo-motor/7//1

Diferencias ATtiny85/UNO
Memoria Flash (KB) - 8/32, para el sketch
SRAM (kB) - 0.5/2, para las variables
Pins I/O - 6/22, sumando digitales y analógicos

Control del servo
La librería “Servo.h” que se instala por defecto al instalar el IDE usa un “timer” de 16 bits, este micro tiene un “timer” de 8 bits, he probado varias librerías para control del servo con este micro, la que me ha dado mejor resultado (y ocupa menos memoria) es la librería “SoftwareServo.h”, cuando movemos el servo hay que añadir una llamada a la función “SoftwareServo::refresh()”

Uso pin “reset”
Este micro tiene un pin de “reset”, también se puede usar como pin analógico o digital, pero es complicado hacerlo ya que hemos de programarlo quemando los fusibles del micro, con esto nos complicamos la vida para hacer marcha atrás y programarlo de nuevo, para no desperdiciar este pin, usaremos un “truco” para que sea fácil de usar en el sketch.
Para forzar un reset, la tensión de este pin ha de ser menor de 2,2V aproximadamente, con un partidor resistivo (ver esquema) mantenemos la tensión a unos 3.8V, cuando pulsamos K1 la tensión sube a 5V
En la función “ResetRead()”, con analogRead() obtenemos el valor digital correspondiente a 3.8V, alrededor de “650” y de “1023” para 5V, este valor lo comparamos con la variable “AnLimit”, si es inferior la tecla no está pulsada, si es superior la tecla está pulsada, con ello retornamos un 1 ó 0, como si de una lectura de un pin digital se tratara

Memoria
Este micro solo tiene 8K de memoria para el sketch, a diferencia de los 32K del UNO o NANO, con 8K se pueden hacer muchas cosas, pero hay que controlar el tamaño del sketch

El sketch
Inicialmente quería hacer un solo sketch para las dos versiones (analógico y digital), aunque hay funciones comunes complica mucho el seguimiento del proceso, terminé por hacer dos sketch

La programación la he hecho sobre un Arduino UNO, para poder tenerlo conectado por el puerto USB y usar el terminar serie como DEBUG, luego he hecho los ajustes sobre el ATTINY, al inicio del sketch hay unas directivas para el compilador (#define), para cambiar la compilación del programa según nos interese
#define ATTINY - habilita la compilación según micro, comentar para usar UNO/NANO
#define SERIAL_DEBUG - habilita Serial.print, usar solo con UNO/NANO
#define RELE - habilita el relé, comentar para no usar el relé
#define DOS_TECLAS - para usar una o dos teclas RECTO/DESVIADO en la versión analógica

El sketch esta comentado para poder seguir el flujo del proceso, al inicio se encuentra un manual de uso
Compilando la versión digital se ocupa el 91% del espacio en memoria para el ATTINY85


Código: Seleccionar todo

/*
Control de versiones
V1 - Funcionamiento para Arduino UNO
V2 - Funcionamiento para ATtiny85
V3 - Version final para ATtiny85, con rele monoestable
V4 - Cambio a rele biestable, pulsador en pin analógico
V5 - Se mejora el control del servo (attach/detach)
V6 - Se optimizan funciones de inicializaciónReducción para reducir el uso de memoria

MANUAL DE FUNCIONAMIENTO

Funcionamiento normal, desde la central se selecciona la dirección DCC programada, con las teclas +/- se cambia la posición del servo

Tecla multifunción K1, se usa para mover el servo manualmente y para la programación de la dirección DCC, la velocidad y los ángulos de desplazamiento del servo
 
K1 pulsado al arranque > mueve servo a posición central, se detiene el programa, para alinear los espadines en la instalación en la maqueta

K1 multifuncion, depende de la duración de la pulsación se accede a una función diferente, se ha de soltar la tecla en el momento adecuado para pasar a la función deseada
El paso de una funciona a otra se muestra con un parpadeo del LED, cada 3s aproximadamente

Pulsación corta (<3s) cambia la posición del servo, el relé cambia a mitad del recorrido

Pulsación (>3s y <6s), muestra la dirección DCC a base de destellos del LED, se muestran 4 dígitos

Pulsación (>6s y <9s), programación de una nueva dirección DCC, el led parpadea, hasta que se envíe una nueva dirección DCC desde la central
enviando una orden de cambio a la nueva dirección, esta quedará programada, el led de apagará

Pulsación (>9s y <12s), programación de los ángulos de desplazamiento
- El servo se mueve a posición central, el led parpadea
- Desde la central, seleccionando la dirección DCC programada, movemos el servo con las teclas +/-, para ajustar la posición RECTO
- Al pulsar K1, la posición del servo se guarda como posición RECTO del desvío
- El LED hace un parpadeo lento
- Desde la central, seleccionando la dirección DCC programada, movemos el servo con las teclas +/-, para ajustar la posición DESVIADO
- Al pulsar K1, la posición del servo se guarda como posición DESVIADO del desvío
- El LED se apaga
- Durante el ajuste, si el LED deja de parpadear y luce fijo, es el aviso de que se ha llegado al límite máximo/mínimo 
- Al seleccionar por separado los angulos para las posiciones RECTO/DESVIADO, no importa la instalación mecánica del servo

Pulsación (>12s y <15s), programación de la velocidad de desplazamiento
- El servo se mueve alternativamente de un lado a otro, el led parpadea
- Desde la central, seleccionando la dirección DCC programada, movemos el servo con las teclas +/- para cambiar la velocidad de desplazamiento
- Al pulsar K1, la velocidad del servo se guarda, el LED se apaga
- Durante el ajuste, si el LED deja de parpadear y luce fijo, es el aviso que se ha llegado al límite máximo/mínimo 

Pulsación (>15s)
- Se programan los valores por defecto, la dirección DCC pasa a ser la #1

*/
// configuración para la compilación
#define ATTINY                      // habilitar compilación según micro, comentar para usar UNO/NANO
//#define SERIAL_DEBUG                // para habilitar Serial.print, solo con UNO
#define RELE                        // comentar para no usar relé

#if defined ATTINY                  // DEFINICIONES ATTINY85
  #include <SoftwareServo.h>        // libreria para el Servo  8 bits
  SoftwareServo ElServo;            // crea objeto servo
  #define PinLED 0                  // (5) pin LED
  #define PinServo 1                // (6) pin servo 
  #define PinDCC 2                  // (7) pin entrada DCC
  #define PinKey1 A0                // (A0) pin tecla 1 cambio posición 
#else                               // DEFINICIONES UNO / NANO
  #include <Servo.h>                // libreria para el Servo 
  Servo ElServo;                    // crea objeto servo
  #define PinLED 13                 // (13) pin LED
  #define PinServo 11               // (11) pin servo 
  #define PinDCC 2                  // (2) pin 2 como entrada de señal DCC
  #define PinKey1 A0                // (A0) pin tecla 1 cambio de posición 
#endif

#if defined RELE
  #define PinReleRecto 3            // (2) pin control relé posición recto
  #define PinReleDesvi 4            // (3) pin control relé posición desviado 
  #define RELE_RECTO {digitalWrite(PinReleRecto, LOW); LedOFF; delay(10); digitalWrite(PinReleRecto, HIGH); LedON;}
  #define RELE_DESVI {digitalWrite(PinReleDesvi, LOW); LedOFF; delay(10); digitalWrite(PinReleDesvi, HIGH); LedON;}
#endif

// Otras librerias usadas
#include <EEPROM.h>                 // Se usa la EEPROM para guardar los valores de configuracion
#include <NmraDcc.h>                // Gestion DCC
// variables de control y asignacion
NmraDcc Dcc;                        // objeto control DCC
#define LimitMin 1                  // limite minimo de desplazamiento, el valor 0 da problemas con algún servo
#define LimitMax 91                 // limite maximo de desplazamiento
#define PosMid (LimitMax - LimitMin) / 2   // posición media según LimitMin y LimitMax
#define VelRet 30                   // retardo por defecto para ajustes, a menor valor movimiento más rápido, "SIEMPRE mayor que 0"
#define SrvRetMax 75                // retardo máximo para movimiento del servo, a menor valor movimiento más rápido, "SIEMPRE mayor que 0"
#define SrvRetMin 10                // retardo minimo para movimiento del servo, "SIEMPRE mayor que 0"
#define WaitTime 300                // tiempo de espara para acciones especiales al pulsar una tecla 
#define AnLimit 900                 // usamos el pin de RESET como pin analógico, este es el límite para leer pulsación
#define LedOFF digitalWrite(PinLED, HIGH)
#define LedON digitalWrite(PinLED, LOW)
#define LedFlashTime 20           // frecuencia de parpadeo de un LED con millis()
#define LedFlash {LedON; delay(LedFlashTime);LedOFF;}
#define LedOnOff {digitalWrite(PinLED, !digitalRead(PinLED)); prevMillis = millis();}         // control parpadeo LED
#define WaitNewDirDCC 15000         // tiempo de espera para recibir una nueva direccion DCC

// variables de trabajo para el control del movimiento del servo
int Contador;                       // variable de uso general como contador
byte PosActual;                     // posición actual del servo
byte PosRecto;                      // posición para desvío recto
byte PosDesvi;                      // posición para desvío desviado
byte Retardo;                       // valor para velocidad de movimiento
#if defined RELE
  byte PosRele;                     // Posición donde se activa el rele
#endif

long prevMillis = 0;                // variable para almacenar valor previo de millis()
boolean NewDirDCC = false;          // true = en proceso de capturar nueva dirección
boolean NewSetDCC = false;          // true = en proceso de capturar nueva posición/velocidad del servo
byte AjtPosVel = 3;                 // control para lectura de teclas +/- desde el mando para ajustes de posición/velocidad del servo
int  DirDCC = 1;                    // direccione base DCC a manejar (direccion del accesorio)
int MaxDirDCC = 1020;               // maxima direccion DCC posible
int OldDirDCC = 0;                  // variable para guardar la última direccion DCC recibida
byte OldDirection = 0;              // variable para guardar la última posición del accesorío recibida

//------------------------------------------------------------------------------------------------------

void setup() {
  #if defined SERIAL_DEBUG  
    Serial.begin(9600);
  #endif  
  DirDCC = ((EEPROM[3]*256) + EEPROM[4]); //direccione base DCC a manejar (direccion del accesorio)  
  if (EEPROM[9] != 111 || DirDCC == 0){   // si NO encontramos el valor "111" en la EEPROM, quiere decir que es un micro nuevo
    InitialSet();                         // inicializamos a valores por defecto
  }
  PosActual = EEPROM[0];                  // posición actual del servo
  PosRecto = EEPROM[1];                   // posición para desvío recto
  PosDesvi = EEPROM[2];                   // posición para desvío desviado
  Retardo = EEPROM[5];                    // Valor para velocidad de movimiento
  pinMode(PinDCC, INPUT); 
  pinMode(PinLED, OUTPUT);
  LedOFF;                  
  if (ResetRead() == true) {              // con K1 pulsado al arranque, situamos servo en posición media
    #if defined SERIAL_DEBUG
      Serial.println(">> MOVE MID"); 
    #endif 
    LedON;
    MoveToPos(PosMid);                   
    while(true);                          // detenemos la ejecución del programa
  }   
  #if defined RELE                        // si usamos relé, inicializamos pins y variables
    pinMode(PinReleRecto, OUTPUT); 
    pinMode(PinReleDesvi, OUTPUT); 
    PosRele = (PosRecto + PosDesvi) / 2;  // calculamos punto médio para activar el relé
    if(PosActual == PosRecto) RELE_RECTO  // se actualiza el estado del rele
    else RELE_DESVI    
  #endif
  MoveToPos(PosActual);                   // movemos el servo a la última posición guardada  
  Dcc.pin(0,2, 1);                        // inicializamos librería DCC
  Dcc.initAccessoryDecoder(MAN_ID_DIY, 1, FLAGS_OUTPUT_ADDRESS_MODE, 0);    
  #if defined SERIAL_DEBUG
    Serial.print("PosActual: "); Serial.println(PosActual);
    Serial.print("Retardo  : ");Serial.println(Retardo);  
    Serial.print("Dir DCC  : ");Serial.println(DirDCC);  
    Serial.println("END SETUP --------------------------------------------------"); 
  #endif   
  LedFlash;
}

//
//  FUNCIONES PRINCIPALES
//

void loop() {
  Dcc.process();                                     // lanzamos el proceso de escucha DCC de forma recurrente
  if (ResetRead() == true) {                         // verificamos tecla K1 pulsada
    byte OptionNum = 0;    
    Contador = 0;     
    while (ResetRead() == true && OptionNum < 5) {   // controlamos la duración de la pulsación para seleccionar opción
      delay(10); 
      Contador++;    
      if(Contador == WaitTime){
        OptionNum++;
        Contador = 0;
        LedFlash;                                    // emitimos un destello para indicar cambio de opción 
      }
    }
    #if defined SERIAL_DEBUG 
      Serial.print("OptionNum    ");
      Serial.println(OptionNum);
    #endif     
    switch (OptionNum) {
      case 0:                                        // Movemos el servo
        if(PosActual == PosRecto) {                  // cambiamos la posición del servo
          MoveToPos(PosDesvi);
        }
        else {
          MoveToPos(PosRecto);    
        }
        break;
      case 1:                                       // se muestra la dirección DCC con flash del LED
        VerNumero(DirDCC);
        break;
      case 2:                                       // ajustamos nueva direccion DCC 
        NewDirDCC = true;                           // activamos flag
        GetDDCAddr();
        break;
      case 3:                                       // ajustamos posicion servo
        NewSetDCC = true;                           // activamos flag
        SetPos();
        NewSetDCC = false;                          // desactivamos flag
        break;    
      case 4:                                       // ajustamos velocidad de desplazamiento  
        NewSetDCC = true;                           // activamos flag
        SetVel();                    
        NewSetDCC = false;                          // desactivamos flag
        break;        
      case 5:                                       // hacemos reset a valores por defecto
        while(ResetRead() == true) {delay(10);}     // esperamos a que K1 deje de estar pulsada
        LedON;
        InitialSet();                         
        MoveToPos(PosRecto);
        LedOFF;
        break;
    }  
  }
}

void Re_Set(){
  while(ResetRead() == true) {delay(10);}                                // esperamos a que K1 deje de estar pulsada
  LedON;
  InitialSet();
  MoveToPos(PosRecto);
  LedOFF;
}

// Control de lectura en pin analógico
// para poder tener una entrada más en el ATTINY85, usamos el pin de reset para leer una tecla
// este pin se puede programar para que sea una entrada digital, pero se complica el proceso de programación del micro
// para no complicarnos, el pin esta a +5V por defecto, conectado a un partidor resistivo y una tecla que al ser pulsada 
// hace que el valor sea de unos 3V, la lectura analógica está por debajo del valor de AnLimit
// con esta funcion retornamos 0/1 como si de un pin digital se tratara
boolean ResetRead(){
  if(analogRead(PinKey1) > AnLimit) return true;
  else return false;   
}

// funcion de manejo de las direcciones DCC
void notifyDccAccTurnoutOutput(uint16_t Addr, uint8_t Direction, uint8_t OutputPower){                   
/*  #if defined SERIAL_DEBUG                                        // descomentar para ver las lecturas 
      Serial.println("LECTURA DCC ---------------------"); 
      Serial.print("Addr   ");Serial.println(Addr, DEC);
      Serial.print("Dir    ");Serial.println(Direction);
      Serial.print("Out    ");Serial.println(OutputPower);
      Serial.print("HByte  ");Serial.println(highByte(Addr)); 
      Serial.print("LByte  ");Serial.println(lowByte(Addr));  
      Serial.println("---------------------------------");    
  #endif */
  if (OutputPower != 1) return;                                     // solo ordenes para accesorios
  if (NewDirDCC == true){                                           // si estamos esperando una nueva dirección DCC
    #if defined SERIAL_DEBUG 
      Serial.print("Cur Dir    ");Serial.println(DirDCC);
    #endif 
    if (Addr <= MaxDirDCC){                                         // si la dirección recibida está dentro de los límites
      DirDCC = Addr;                                                // actualizamos valor de la variable DirDCC
      EEPROM[3] = highByte(DirDCC); // direccion DCC base byte H    // actualizamos EEPROM
      EEPROM[4] = lowByte(DirDCC);  // direccion DCC base byte L  
      NewDirDCC = false;                                            // deshabilitamos la espera de nueva DirDCC
      #if defined SERIAL_DEBUG 
        Serial.print("New Addr    ");Serial.println(DirDCC,DEC);
        Serial.print("HByte       ");Serial.println(highByte(DirDCC)); 
        Serial.print("LBYTE       ");Serial.println(lowByte(DirDCC));
      #endif
    } 
    return;                                                         // retornamos
  }                                                                 // proceso normal de una dirección DCC
  if(Addr == DirDCC){                                               // si la dirección decibida es la nuestra
    if(NewSetDCC == true){                                          // si estamos en un proceso de ajuste del movimiento del servo
      AjtPosVel = Direction;                                       // retornamos el valor para el ajuste en la variable AjtPosVel
      return;
    }     
    if(OldDirDCC == Addr && OldDirection == Direction) return;     // si es la misma DirDCC y Dirección que la vez anterior, retornamos
    if(Direction == true) {                                        // si no hemos retornado anted, movemos el servo
      MoveToPos(PosRecto);                                          // movimiento a recto si Direcction = 1
    }
    else {
      MoveToPos(PosDesvi);                                          // movimiento a recto si Direcction = 0
    }
    OldDirDCC = Addr;                                               // guardamos valores para la próxima vez
    OldDirection = Direction; 
  }  
}

// Mueve el servo a una pocición según el parámetro "NewPos"
void MoveToPos(byte NewPos){
  #if defined SERIAL_DEBUG
    Serial.print("PosActual  FROM : ");Serial.println(PosActual);  
    Serial.print("NewPos       TO : ");Serial.println(NewPos);  
  #endif  
  if (NewPos == PosActual) return;                     // si NewPos es la posición actual, cancelamos 
  LedON;
  boolean RelStatus = false;
  if (NewPos == PosRecto) RelStatus = true;            // calculamos valor para mover relé 
  ServoActivo(true);                                   // inicializacion el servo          
  if (NewPos > PosActual) { // movimiento a recto      // bucle para movimiento incrementando angulo
    for (byte i = PosActual; i <= NewPos; i++) {  
      MoveServo(i, RelStatus);
    }   
  }
  else {                                               // bucle para movimiento decrementando angulo
    for (byte i = PosActual; i >= NewPos; i--) { 
      MoveServo(i, RelStatus);
    } 
  } 
  ServoActivo(false);                                  // deshabilitamos el servo
  PosActual = NewPos;                                  // actualizamos posición
  EEPROM[0] = PosActual;                               // guardamos posicion 
  LedOFF;
}  

// Habilita/deshabilita el servo según parámetro "Estado"
// La idea de de habilitar/deshabilitar el servo la he copiado de PC
void ServoActivo(boolean Estado){                    
  if(Estado == true){
    ElServo.attach(PinServo); // inicializacion el servo 
  }
  else{
    if (ElServo.attached()){
      while (digitalRead(PinServo)== HIGH);           // Esperamos a que acabe el pulso  
      ElServo.detach();                               // lo desconectamos
      digitalWrite(PinServo,LOW);                     // nos aseguramos de que esta desconectado    
    }
  }
}

// Desplaza el servo según parámetro "i", controla el estado del relé
void MoveServo(byte i, boolean RelStatus){
  ElServo.write(i);                                   // desplaza el servo
  #if defined ATTINY               
    SoftwareServo::refresh();                         // si usamos ATTINY refrescamos          
  #endif   
  delay(Retardo);                                     // aplicamos retardo 
  #if defined RELE                                    // si usamos el relé, cambiamos su estado según parámetro "Relstatus"
    if(i == PosRele) {                                // si estamos en el punto de cambio del relé lo actualizamos
      if(RelStatus == true) RELE_RECTO
      else RELE_DESVI
    }
  #endif
}

//
//  FUNCIONES PARA LA CONFIGURACION DE VALORES, direccion DCC, posiciones, velocidad de desplazamiento y reset de valores
//

 // Se espera una nueva dirección DCC
void GetDDCAddr(){ 
  #if defined SERIAL_DEBUG
    Serial.println("SetAdr");
  #endif   
  while(NewDirDCC == true){ 
    Dcc.process();
    if(millis() - prevMillis > LedFlashTime * 5) LedOnOff                // control parpadeo LED
    if(digitalRead(PinKey1) == LOW) NewDirDCC = false;                   // salimos si pulsamos K1
  }
  LedOFF; 
}

// Definimos valores para las posiciones recto/desviado
void SetPos(){
  #if defined SERIAL_DEBUG
    Serial.println("SetPos");
  #endif
  LedON;                                                                 // encendemos LED
  while(ResetRead() == true) {delay(10);}                                // esperamos a que K1 deje de estar pulsada
  PosRecto = GetPos();                                                   // definimos posicion RECTO
  EEPROM[1] = PosRecto;                                                  // guardamos nuevo valor para posición DESVIADO 
  PosActual = PosRecto;
  #if defined SERIAL_DEBUG
    Serial.print("RECTO ? ");Serial.println(PosRecto); 
  #endif
  LedOFF; delay(1000);LedON;                                             // parpadeo del LED
  PosDesvi  = GetPos();                                                  // definimos posicion DESVIADO
  EEPROM[2] = PosDesvi;                                                  // guardamos nuevo valor para posición DESVIADO 
  PosActual = PosDesvi;                                                  // actualizamos posición actual
  #if defined SERIAL_DEBUG
    Serial.print("DESVI ? ");Serial.println(PosDesvi); 
  #endif  
  #if defined RELE                                                       // recalculamos punto de cambio, si usamos relé
    PosRele = (PosRecto + PosDesvi)/2;
  #endif
  LedOFF;                                                                // apagamos LED
}

byte GetPos() {
  byte Contador = PosMid;                                            // usamos la variable contador para ajustar la posicion del servo  
  byte PContador = PosMid;          
  MoveToPos(PosMid);                                                 // movemos el servo a posición media
  ServoActivo(true);                                                 // inicializacion el servo
  while(ResetRead() == false){
    Dcc.process();
    if(Contador == LimitMax || Contador == LimitMin){                // si se ha llagado a algún límite encendemos el LED
      LedON;
    }
    else{
      if((millis() - prevMillis) > LedFlashTime * 5) LedOnOff        // control parpadeo LED          
    }    
    if (AjtPosVel == 1 && Contador < LimitMax) Contador++;           // aumentamos angulo 
    if (AjtPosVel == 0 && Contador > LimitMin) Contador--;           // disminuimos angulo    
    if (PContador != Contador){                                      // comparamos con valor anterior
      ElServo.write(Contador);                                       // movemos servo
      #if defined ATTINY 
        SoftwareServo::refresh();                                    // si usamos ATTINY refrescamos 
      #endif   
      PContador = Contador;                                          // guardamos valor anterior
    }
    AjtPosVel = 3;                                                   // asignamos valos diferente a 0 y 1
  }
  ServoActivo(false);                                                // deshabilitamos servo
  while(ResetRead() == true) {delay(10);}                            // esperamos desactivación K1
  return Contador;                                                   // retornamos valor
} 

// Definimos velocidad de movimiento del servo
void SetVel(){
  #if defined SERIAL_DEBUG
    Serial.println("SetVel");
  #endif
  while(ResetRead() == true) {delay(10);}
  NewSetDCC = true;  
  Contador = VelRet;                                            // inicializamos valor para velocodad de desplazamiento 
  byte PosMin = min(PosRecto, PosDesvi);                        // identificamos valores máximo y mínimo para recorrido
  byte PosMax = max(PosRecto, PosDesvi);
  ServoActivo(true);                                            // inicializacion el servo
  while(ResetRead() == false) {                                 // bucle para desplazamiento del serveo entre valores PosMin/PosMax
    for (int i = PosMin; i<=PosMax; i++) {  
      if (ResetRead() == true) break;   
      if(Contador == SrvRetMax || Contador == SrvRetMin){       // si se ha llegado a los retardos máximos/mínimos, el LED luce fijo
        LedON;
      }
      else{
        if((millis() - prevMillis) > Contador * 5) LedOnOff    // control parpadeo LED          
      }
      ElServo.write(i);
      #if defined ATTINY                    
        SoftwareServo::refresh();                               // si usamos ATTINY refrescamos
      #endif 
      GetTime();
    }
    for (int i = PosMax; i >= PosMin; i--) {   
      if (ResetRead() == true) break;  
      if(Contador == SrvRetMax || Contador == SrvRetMin){       // si se ha llegado a los retardos máximos/mínimos, el LED luce fijo
        LedON;
      }
      else{
        if((millis() - prevMillis) > Contador * 5) LedOnOff    // control parpadeo LED          
      }    
      ElServo.write(i);
      #if defined ATTINY                    
        SoftwareServo::refresh();                               // si usamos ATTINY refrescamos
      #endif 
      GetTime();
    }
  }
  ServoActivo(false);
  NewSetDCC = false;    
  EEPROM[5] = Contador;                                         // guardamos retardo  
  Retardo = Contador;  
  MoveToPos(PosActual);                                         // movemos el servo a posición actual
  LedOFF;
}

// Obtenemos retardo para ajustar la velocidad de movimiento
void GetTime() { 
  Dcc.process();                                                // llamamos proceso DCC
  if(AjtPosVel == 0 && Contador < SrvRetMax) Contador++;        // según dato recibido incrementamos/decrementamos valor para ajuste
  if(AjtPosVel == 1 && Contador > SrvRetMin) Contador--;
  AjtPosVel = 3;                                                // asignamos valos diferente a 0 y 1
  delay(Contador);                                              // aplicamos retardo
  #if defined SERIAL_DEBUG
    Serial.println(Contador);
  #endif  
}

//
//  OTRAS FUNCIONES AUXILIARES
//

// Se muestra la dirección DCC con flash del LED
void VerNumero(int VerContador){
  #if defined SERIAL_DEBUG  
    Serial.print("VerNumero : ");
    Serial.println(VerContador);
  #endif
  delay(2000);
  byte Millar, Centen, Decena, Unidad;                           // obtenemos digitos correspondientes
  Millar = VerContador/1000;
  Centen = (VerContador - Millar*1000)/100;
  Decena = (VerContador - Millar*1000 - Centen*100)/10;
  Unidad = (VerContador - Millar*1000 - Centen*100 - Decena*10);
  BlinkLED(Millar);
  delay(2000);
  BlinkLED(Centen);
  delay(2000);
  BlinkLED(Decena);
  delay(2000);
  BlinkLED(Unidad);
}

// Emite parpadeos en funcion del parámetro "v"
void BlinkLED(int v){
  int t= 500;
  if (v == 0) {
    LedON;
    delay (3 * t); 
    LedOFF;
  }
  else {
    while (v > 0) {
      LedON;
      delay (t); 
      LedOFF;
      delay(t); 
      v--;
    }
  delay(1.5 * t);
  }
}

// Inicializa a valores por defecto
void InitialSet(){ // inicializamos valores por defecto
  EEPROM[0]=LimitMin; // 
  PosActual=LimitMin;
  EEPROM[1]=LimitMin; // posicion recto
  EEPROM[2]=LimitMax; // posicion desviado 
  EEPROM[3]=0; // direccion DCC base byte H
  EEPROM[4]=1; // direccion DCC base byte L   
  EEPROM[5]=VelRet; // velocidad
  EEPROM[9]=111; // control
 }


 //////////////////////////////////////////////////////////////////////////////////////////
 
Saludos
Adjuntos
Adaptador para montar el PCB sobre el servo
Adaptador para montar el PCB sobre el servo
IMG_1563.JPG (1.27 MiB) Visto 324 veces
Última edición por sls_h0e el Dom Jun 14, 2020 8:33 pm, editado 1 vez en total.
Lenz + 2C + K.Bay
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Mas fotor
Adjuntos
Montaje versión analógica
Montaje versión analógica
VISTA_ANA.jpg (683.15 KiB) Visto 321 veces
Componentes y conexiones
Componentes y conexiones
Componentes y conexiones.jpg (386.29 KiB) Visto 321 veces
Versión con soporte antiguo
Versión con soporte antiguo
MONTAJE INICIAL.jpg (1.24 MiB) Visto 321 veces
Versión final digital
Versión final digital
FINAL_DIG.jpg (650.73 KiB) Visto 321 veces
Esquema
Esquema
Esquema SERVO_MOTOR_2020.jpg (210.79 KiB) Visto 321 veces
Lenz + 2C + K.Bay
gon
Forero
Mensajes: 4084
Registrado: Mié Ene 18, 2006 7:54 am
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por gon »

Hola Salus:

muy completo el post, la mitad es como si estuviera en chino, pero se lee :roll: . Por lo menos ya sé lo que es un sketch , llevo meses leyendo la palabra en foros y pensaba que era algo de hardware.

Una pregunta, la placa ¿te la han hecho a medida?

saludos
Avatar de Usuario
sls_h0e
Forero
Mensajes: 2328
Registrado: Sab Ene 21, 2006 2:27 pm
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por sls_h0e »

Hola Gonzalo

La placa de circuitoimpreso la diseñe aquí https://circuitmaker.com/Projects#/servo-motor/7//1 , luego pedí a un proveedor chino que las fábricara, a unos 0,5€ unidad para 5u
Para meter tantos componentes me hacía falta doble cara

Este es el sketch de la versión analógica, como el anterios, al inicio hay un manual de uso

Saludos

Código: Seleccionar todo

/*
Control de versiones
V1 - Funcionamiento para Arduino UNO
V2 - Funcionamiento para ATtiny85
V3 - Version final para ATtiny85, con rele monoestable
V4 - Cambio a rele biestable, añadido pulsador en pin analógico
V5 - Se mejora el control del servo (attach/detach)
V6 - Se optimizan funciones de inicializaciónReducción para reducir el uso de memoria
V6 - Añadida opción una o dos teclas para la maniobra (para la configuración siempre se usan las dos teclas)

Control manual de servo para mover desvíos

K1 pulsación corta > mueve servo a posición DESVIADO
K2 pulsación corta > mueve servo a posición RECTO
- En Ambos casos el relé cambia de posición a la mitad del recorrido del servo

K1 pulsación larga > configuración de velocidad de desplazamiento
- Se enciende el LED
- El servo empezará a moverse a un lado y a otro
- Ajustar la velocidad de desplazamiento con K1 y K2
- Pulsar K1+K2 para grabar la posición y terminar
- El LED se apaga
K2 pulsación larga > configuración de angulos de desplazamiento
- Se enciende el LED
- El servo se desplazará a la posición central
- Ajustar la posición RECTO con K1 y K2
- Pulsar K1+K2 para grabar la posición
- El LED parpadea
- El servo retornará a la pocición central
- Ajustar la posición DESVIADO con K1 y K2
- Pulsar K1+K2 para grabar la posición y terminar
- El LED se apaga

K1 pulsado al arranque > reset a valoeres por defecto según InitialSet()
K2 pulsado al arranque > mueve servo a posición central (90º) para anclarlo mecanicamente
*/

// configuración para la compilación
#define ATTINY                      // habilitar compilación según micro, comentar para usar UNO/NANO
//#define SERIAL_DEBUG              // para habilitar Serial.print, solo con UNO/NANO
#define RELE                        // comentar para no usar el rele
#define DOS_TECLAS                  // para usar dos teclas RECTO/DESVIADO, comentar para uso de una sola tecla

#if defined ATTINY                  // DEFINICIONES ATTINY85
  #include <SoftwareServo.h>        // libreria para el Servo  8 bits
  SoftwareServo ElServo;            // crea objeto servo
  #define PinLED 0                  // (5) pin LED
  #define PinServo 1                // (6) pin servo 
  #define PinKey2 2                 // (7) pin tecla 2 posición desviado
  #define PinKey1 A0                // (A0) pin tecla 1 posición recto 
#else                               // DEFINICIONES UNO / NANO
  #include <PWMServo.h>             // libreria para el Servo 
  PWMServo ElServo;                 // crea objeto servo
  #define PinLED 13                 // (13) pin LED
  #define PinServo 11               // (11) pin servo  
  #define PinKey2 2                 // (2) pin tecla 2 posición desviado
  #define PinKey1 A0                // (A0) pin tecla 1 posición recto (ha de ser un pin analógico 
#endif

#if defined RELE
  #define PinReleRecto 3            // (2) pin control relé posición recto
  #define PinReleDesvi 4            // (3) pin control relé posición desviado 
  #define RELE_RECTO {digitalWrite(PinReleRecto, LOW); LedON; delay(10); digitalWrite(PinReleRecto, HIGH); LedOFF;}
  #define RELE_DESVI {digitalWrite(PinReleDesvi, LOW); LedON; delay(10); digitalWrite(PinReleDesvi, HIGH); LedOFF;}
#endif

// Otras librerias usadas
#include <EEPROM.h>                 // Se usa la EEPROM para guardar los valores de configuracion
// variables de control y asignacion
#define LimitMin 1                  // limite minimo de desplazamiento (grados)
#define LimitMax 46                 // limite maximo de desplazamiento (grados)
#define PosMid (LimitMax - LimitMin) / 2   // posición media según LimitMin y LimitMax
#define VerRet 30                   // velocidad por defecto para ajuste 
#define SrvRetMax 75                // maximo retardo para movimiento
#define SrvRetMin 10                // minimo retardo para movimiento
#define WaitTime 300                // tiempo de espara para acciones especiales al pulsar una tecla (300 = 3s)
#define AnLimit 900                 // usamos el pin de RESET como pin analógico, este es el límite para leer pulsación
#define LedOFF digitalWrite(PinLED, HIGH)
#define LedON digitalWrite(PinLED, LOW)
#define LedFlashTime 20           // frecuencia de parpadeo de un LED con millis()
#define LedFlash {LedON; delay(LedFlashTime);LedOFF;}     

// variables de trabajo para el control del movimiento del servo
int Contador;                       // variable de uso general como contador
byte PosActual;                     // posición actual del servo
byte PosRecto;                      // posición para desvío recto
byte PosDesvi;                      // posición para desvío desviado
byte Retardo;                       // Valor para velocidad de movimiento
#if defined RELE
  byte PosRele;                     // Punto de cambio donde se activa el rele
#endif

//------------------------------------------------------------------------------------------------------

void setup() {
	#if defined SERIAL_DEBUG  
	  Serial.begin(9600);
	#endif   
  if (EEPROM[9] != 111) {              // si NO encontramos el valor "111" en la EEPROM, quiere decir que es un micro nuevo
    InitialSet();                      // inicializamos a valores por defecto
  }
  // iniciamos variables con los valores guardados en la sesión anterior
  PosActual = EEPROM[0];               // posición actual del servo
  PosRecto = EEPROM[1];                // posición para desvío recto
  PosDesvi = EEPROM[2];                // posición para desvío desviado
  Retardo = EEPROM[5];                 // Valor para velocidad de movimiento
  pinMode(PinKey2, INPUT_PULLUP);
  pinMode(PinLED, OUTPUT);
  LedOFF;   
  if (digitalRead(PinKey2) == LOW) {   // con K2 pulsado al arranque, situamos servo en posición media
    #if defined SERIAL_DEBUG
      Serial.println(">> MOVE MID"); 
    #endif 
    LedON;
    MoveToPos(PosMid);
    while(true);                       // detenemos la ejecución del programa
  }  
	if (ResetRead() == true) {	         // con K1 reseteamos a valores por defecto
		for(byte i=0;i<5;i++){             // avisamos con parpadeos del LED
      LedFlash;
      delay(100);
		}
		InitialSet();                      // inicicializamos valires por defecto
    while(true);                       // detenemos la ejecución del programa
	} 

  #if defined RELE                     // inicializamos relé
    pinMode(PinReleRecto, OUTPUT); 
    pinMode(PinReleDesvi, OUTPUT); 
    PosRele = (PosRecto + PosDesvi) / 2;
    if(PosActual == PosRecto) RELE_RECTO  // se actualiza el estado del relé
    else RELE_DESVI    
	#endif
  MoveToPos(PosActual);                 // movemos el servo a la última posición guardada   
	#if defined SERIAL_DEBUG
	  Serial.print("PosActual: "); Serial.println(PosActual);
	  Serial.print("Retardo  : ");Serial.println(Retardo);   
	#endif 
  LedFlash;
}

//
//  FUNCIONES PRINCIPALES
//
void loop() {
  // verificamos si hay tecla pulsada de forma continua, actuamos según la pulsación es larga/corta y si usamos una/dos teclas 
  if (digitalRead(PinKey2) == LOW) {  // verificamos tecla K2 pulsada
    #if defined SERIAL_DEBUG
      Serial.println("K2");
    #endif   
    Contador = WaitTime;              
    while (digitalRead(PinKey2) == LOW && Contador != 0) {   // controlamos tiempo de pulsación
      delay(10);
      Contador--;
    }
    if (Contador == 0) {              // identificamos pulsación larga o corta
      #if defined SERIAL_DEBUG
        Serial.println(">> SET_POS");  
      #endif
      SetPos();                       // si es posición larga, pasamos a programación de posiciones del servo
    }
    else {                            // si es posición corta
      #if defined DOS_TECLAS
        MoveToPos(PosRecto);          // si usamos dos teclas, movemos servo a RECTO
      #else                           // si usamos una tecla, cambiamos la posición del servo
        if(PosActual == PosRecto) MoveToPos(PosDesvi); 
        else MoveToPos(PosRecto); 
      #endif
    }
  }
  if (ResetRead() == true) {          // verificamos tecla K1 pulsada
    #if defined SERIAL_DEBUG
      Serial.println("K1");
    #endif     
    Contador = WaitTime;
    while (ResetRead() == true  && Contador != 0) {        // controlamos tiempo de pulsación
      delay(10);
      Contador--;
    }
    if (Contador == 0) {              // si es posición larga, pasamos a programación de la velocidad de desplazamiento del servo
      SetVel();      
      #if defined SERIAL_DEBUG
        Serial.println(">> SET_VEL"); 
      #endif
    }
    #if defined DOS_TECLAS 
      else MoveToPos(PosDesvi);       // si usamos dos teclas, movemos servo a DESVIADO
    #endif    
  }
}

// Control de lectura en pin analógico
// para poder tener una entrada más en el ATTINY85, usamos el pin de reset para leer una tecla
// este pin se puede programar para que sea una entrada digital, pero se complica el proceso de programación del micro
// para no complicarnos, el pin esta a +5V por defecto, conectado a un partidor resistivo y una tecla que al ser pulsada 
// hace que el valor sea de unos 3,5V, la lectura analógica está por debajo del valor de AnLimit
// Con esta funcion retornamos 0/1 como si de un pin digital se tratara
boolean ResetRead(){           
  if(analogRead(PinKey1) > AnLimit) return true;
  else return false;   
}

// Mueve el servo a una pocición según el parámetro "NewPos"
void MoveToPos(byte NewPos){
  if (NewPos == PosActual) return;                     // si NewPos es la posición actual, cancelamos 
  boolean RelStatus = false;
	if (NewPos == PosRecto) RelStatus = true;            // calculamos valor para mover relé
	#if defined SERIAL_DEBUG
	  Serial.print("PosActual  FROM : ");Serial.println(PosActual);  
	  Serial.print("NewPos       TO : ");Serial.println(NewPos);  
	#endif 
  ServoActivo(true);                                   // inicializacion el servo          
	if (NewPos > PosActual) {	                           // bucle para movimiento incrementando angulo
		for (byte i = PosActual; i <= NewPos; i++) {  
			MoveServo(i, RelStatus);
		}   
	}
	else {                                               // bucle para movimiento decrementando angulo
		for (byte i = PosActual; i >= NewPos; i--) {
			MoveServo(i, RelStatus);
		} 
	}	
  ServoActivo(false);                                  // deshabilitamos el servo
  PosActual = NewPos;                                  // actualizamos posición
  EEPROM[0] = PosActual;                               // guardamos posicion 
}  

// Habilita/deshabilita el servo según parámetro "Estado"
// Lo de habilitar/deshabilitar el servo me lo he copiado de PC
void ServoActivo(boolean Estado){
  if(Estado == true){
    ElServo.attach(PinServo); // inicializacion el servo 
  }
  else{
    if (ElServo.attached()){
      while (digitalRead(PinServo)== HIGH);       // Esperamos a que acabe el pulso  
      ElServo.detach();                           // lo desconectamos
      digitalWrite(PinServo,LOW);                 // nos aseguramos de que esta desconectado    
    }
  }
}

// Desplaza el servo según parámetro "i", controla el estado del relé
void MoveServo(byte i, boolean RelStatus){
  ElServo.write(i);                               // desplaza el servo
  #if defined ATTINY               
    SoftwareServo::refresh();                     // si usamos ATTINY refrescamos          
  #endif   
  delay(Retardo);                                 // aplicamos retardo 
  #if defined RELE                                // si usamos el relé, cambiamos su estado según parámetro "Relstatus"
    if(i == PosRele) {                            // si estamos en el punto de cambio del relé lo actualizamos
      if(RelStatus == true) RELE_RECTO
      else RELE_DESVI
    }
  #endif
}

//
//  FUNCIONES PARA LA CONFIGURACION DE VALORES, angulo de posiciones recto/curvo, velocidad de desplazamiento y reset de valores
//
// Definimos valores para las posiciones recto/desviado
void SetPos(){
	#if defined SERIAL_DEBUG
	  Serial.println("SetPos");
	#endif
	LedON;                       // encendemos LED
	while(digitalRead(PinKey2) == LOW) {delay(10);}  // esperamos a que K2 deje de estar pulsada
  PosRecto = GetPos();         // definimos posicion DESVIADO 
  EEPROM[1] = PosRecto;        // guardamos nuevo valor para posición DESVIADO 
  PosActual = PosRecto;	
	LedOFF;                      // parpadeo del LED 0,5s
	delay(500);                  
	LedON;
  PosDesvi  = GetPos();        // definimos posicion DESVIADO 
  EEPROM[2] = PosDesvi;        // guardamos nuevo valor para posición DESVIADO 
  PosActual = PosDesvi;        // actualizamos posición actual
  #if defined RELE             // si usamos relé, recalculamos punto de cambio
	  PosRele = (PosRecto + PosDesvi)/2;
	#endif
	LedOFF;                      // apagamos LED
}

// Definimos posición del servo con las teclas K1/K2
byte GetPos() {
	byte Contador = PosMid;                                               // usamos la variable contador para ajustar la posicion del servo            
  MoveToPos(PosMid);                                                    // movemos el servo a posición media
  ServoActivo(true);           // inicializacion el servo
  while (true) {                                                        // entramos en un bucle para ajustar la posición del servo mediante K1/K2
	  if (ResetRead() == true && Contador < LimitMax) Contador++;         // si K1 pulsada aumentamos angulo 
		if (digitalRead(PinKey2) == LOW && Contador > LimitMin) Contador--; // si K2 pulsada disminuimos angulo
		ElServo.write(Contador);                                            // movemos servo
    #if defined ATTINY 
      SoftwareServo::refresh();                                         // si usamos ATTINY refrescamos 
    #endif          
		delay(VerRet);                                                      // aplicamos retardo
		if (digitalRead(PinKey2) == LOW && ResetRead() == true) {           // si pulsamos K1+K2 salimos del bucle
			break;
		}
  }
  ServoActivo(false);          // deshabilitamos servo 
  return Contador;                                                      // retornamos valor
} 

// Definimos velocidad de movimiento del servo
void SetVel(){
  LedON;
	#if defined SERIAL_DEBUG
	  Serial.println("SetVel");
	#endif
	Contador = VerRet;                        // inicializamos valor para velocidad de desplazamiento
	byte PosMin = min(PosRecto, PosDesvi);
	byte PosMax = max(PosRecto, PosDesvi);
  ServoActivo(true);                        // inicializacion el servo
	while (true) {                            // entramos en un bucle para ajustar la velocidad del servo mediante K1/K2, movemos el servo de forma continua entre "PosMin" y "PosMax"    
		for (int i = PosMin; i<=PosMax; i++) {  // movemos desde PosMin a PosMax
			if (digitalRead(PinKey2) == LOW && ResetRead() == true) break;     // si pulsamos K1+K2 salimos del bucle "for"  
			ElServo.write(i);                     // movemos servo
      #if defined ATTINY                    
        SoftwareServo::refresh();           // si usamos ATTINY refrescamos
      #endif 
			delay(10);
			GetTime();                            // cambiamos valor del retardo
		}
		for (int i = PosMax; i >= PosMin; i--) { // movemos desde PosMax a PosMin  
			if (digitalRead(PinKey2) == LOW && ResetRead() == true) break;     // si pulsamos K1+K2 salimos del bucle "for"    
			ElServo.write(i);                     // movemos servo
      #if defined ATTINY 
        SoftwareServo::refresh();           // si usamos ATTINY refrescamos
      #endif 
			delay(10);
			GetTime();                            // cambiamos valor del retardo
		}
		if (digitalRead(PinKey2) == LOW && ResetRead() == true) break; // si pulsamos K1+K2 salimos del bucle "while"  
	} 
  ServoActivo(false);                       // deshabilitamos servo
	EEPROM[5]=Contador;                       // Guardamos nuevo valor del retardo  
	Retardo = Contador;   
	LedOFF;
}

// Obtenemos nuevo valor para retardo según K1/K2
void GetTime() {
	if (digitalRead(PinKey2) == LOW && Contador <= SrvRetMax) Contador++;    // si K2 pulsada, incrementamos valor
	if (ResetRead() == true && Contador >= SrvRetMin) Contador--;            // si K1 pulsada, decrementamos valor  
	delay(Contador);                                                         // aplicamos retardo
	#if defined SERIAL_DEBUG
	  Serial.println(Contador);
	#endif  
}

// Inicializa a valores por defecto
void InitialSet(){
	EEPROM[0]=LimitMin;    // posición actual segín límite mínimo (angulo) de desplazamiento del servo
	PosActual=LimitMin;    // inicializamos posición actual
	EEPROM[1]=LimitMin;    // posicion K1 recto, (angulo) de desplazamiento del servo
	EEPROM[2]=LimitMax;    // posicion K2 desviado, (angulo) de desplazamiento del servo
	EEPROM[5]=VerRet;      // retardo para fejar la velocidad  de desplazamiento del servo
	EEPROM[9]=111;         // control inicial
 
  #if defined SERIAL_DEBUG
    Serial.println(">> RESET"); 
  #endif 
}
Adjuntos
VISTA PISTAS.jpg
VISTA PISTAS.jpg (844.18 KiB) Visto 299 veces
Lenz + 2C + K.Bay
gon
Forero
Mensajes: 4084
Registrado: Mié Ene 18, 2006 7:54 am
20
Ubicación: Madrid

Re: MOVIENDO DESVÏOS

Mensaje por gon »

Madre mía con los chinos. Te habrá costado más caro el transporte que las placas. A 50 céntimos y doble cara. Como para hacerlas en casa. Lo único el mes que habrá que esperar.

Muchas gracias

saludos
Responder
 
  • Contacto
  • Nombre de Usuario:
    Email:
    Asunto:
    Mensaje: