Sustitución fin de carrera por sensor

Buenas tardes, tengo un problema con un código y necesitaría ayuda para resolverlo.
Tengo un motor PaP con un pequeño espejo en un extremo y su función es desviar un rayo láser que incide contra el.

El caso que para que inicie su función, debe estar en una posición determinada y de esa forma el rayo empieza una secuencia que hace que se despliegue en forma de abanico.

Para eso lleva un interruptor fin de carrera con lo que el motor se posiciona en su punto pero quiero sustituir el interruptor por un sensor TCRT5000 con lectura analógica conectado en cualquier salida analógica excepto A0 porque ya esta ocupada con otra cosa y que haga la misma función.

Este es la parte del código que ajusta el motor:

int valBot = 0;   	// Estado del botón del motor
int pinBoton = 3;   // Pin donde está conectado el interruptor de fin de carrera del motor
int pinLaser = 4;    // Pin donde esta conectado el laser
int pinLed = 6;      // Pin donde está conectado el LED de estado
int pinStep = 7;  	// Pin del Step del EasyDriver 
int pinDirec = 8;	// Pin de Direction del EasyDriver

void setup() {
Serial.begin(9600);	// Iniciamos comunicación serial
  pinMode(pinBoton, OUTPUT); 
}


// Poner el motor/espejo en su sitio al comienzo y secuencia de inicio: 

void ajusteMotor(){
  
  pinMode(pinBoton, INPUT); // Declaro el pín del motor como INPUT 
  pinMode(pinDirec, OUTPUT);
  pinMode(pinStep, OUTPUT);
  digitalWrite(pinDirec, LOW);
  digitalWrite(pinStep, LOW);

  for (int pos = 0; pos < 4000; pos++)
  {
   valBot = digitalRead(pinBoton);
   if (valBot == LOW)
   {         // si el botón está pulsado:
    //digitalWrite(pinLed, HIGH);   // enciendo el led
    digitalWrite(pinDirec, HIGH);  // cambio la dirección
    for (int pos2 = 0; pos2<posVert; pos2++)
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 

    digitalWrite(pinLaser, HIGH);   // Enciendo el laser

y esta es la parte del código que se encarga de desplegar el abanico acelerándolo linealmente, esta parte funciona perfectamente y no hay que hacerle nada:

// Secuencia abanico desplegado totalmente, acelerando linealmente:
    numpasosini=(haces-1)*pasosHaces*17/2;   // Calculo el número de pasos en la secuencia de inicio

    // Compruebo la célcula fotoeléctrica, y mando arrancar la secuencia de inicio cuando se active:
    while(true)
    {
      if ( (analogRead(0) > sensor*2 ) )     // Si el sensor recibe señal
      {
        digitalWrite(pinLed, HIGH);   // Enciendo el led
        digitalWrite(pinDirec, LOW);  // Cambio la dirección
        for (int pos2 = 0; pos2<((haces-1)*pasosHaces/2); pos2++)
        {
           digitalWrite(pinStep, LOW);
           digitalWrite(pinStep, HIGH);
           digitalWrite(pinLaser, HIGH);   // Enciendo el laser
           delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
           digitalWrite(pinLaser, LOW);   // Apago el laser
        }
        for (int pos3 = 0; pos3<4; pos3++)
        {
          digitalWrite(pinDirec, HIGH);  // Cambio la dirección
          for (int pos2 = 0; pos2<((haces-1)*pasosHaces); pos2++)
          {
             digitalWrite(pinStep, LOW);
             digitalWrite(pinStep, HIGH);
             digitalWrite(pinLaser, HIGH);   // Enciendo el laser
             delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
             digitalWrite(pinLaser, LOW);   // Apago el laser
          }
          digitalWrite(pinDirec, LOW);  // Cambio la dirección
          for (int pos2 = 0; pos2<((haces-1)*pasosHaces); pos2++)
          {
             digitalWrite(pinStep, LOW);
             digitalWrite(pinStep, HIGH);
             digitalWrite(pinLaser, HIGH);   // Enciendo el laser
             delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
             digitalWrite(pinLaser, LOW);   // Apago el laser
          }
        }
        break;
      }
    }

       break;
   }
   else
   {        // el botón no está pulsado:
    digitalWrite(pinLed, LOW);  // Mantengo el led apagado

    digitalWrite(pinStep, LOW);
    digitalWrite(pinStep, HIGH);
    delayMicroseconds(micropausa);

   }
  }
}



Adaptando un ejemplo de código que usa una salida analógica lo he escrito de este modo, pero no se si está bien porque creo que hay que calibrar el sensor para que los valores coincidan con la posición que buscamos, no se si es cierto o no, yo he puesto un valor de ejemplo.


int valBot = 0;			// variable que usamos para recoger la señal del sensor
int pinsensor = A1;		// Con este pin recogemos las señales del sensor
int pinLaser = 4;    // Pin donde esta conectado el laser
int pinLed = 6;      // Pin donde está conectado el LED de estado
int pinStep = 7;  	// Pin del Step del EasyDriver 
int pinDirec = 8;	// Pin de Direction del EasyDriver

void setup() {
Serial.begin(9600);	// Iniciamos comunicación serial
}

void ajusteMotor(){
valBot = analogRead(pinsensor);		// Lectura analógica del pin del sensor
if (valBot <=700), 					// Este es un valor de ejemplo

    digitalWrite(pinLed, HIGH);   // enciendo el led
    digitalWrite(pinDirec, HIGH);  // cambio la dirección
    for (int pos2 = 0; pos2<posVert; pos2++)
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 

    digitalWrite(pinLaser, HIGH);   // Enciendo el laser
}


Agradecería un poco de ayuda.
Gracias de antemano.

Hola, lo que te aconsejo es si funciona bien porque cambiarlo?

No funciona bien y ademas en el eje del motor tengo que ponerle una especie de palanquita que acciona el fin de carrera y es muy molesto cada vez que funciona el motor el golpeteo constante.

Pones un sensor IR de ranura (tipo H2010) en lugar del final de carrera y evitas el ruido.

Buenas tardes, y volviendo al tema del sensor ya lo he instalado y he estado leyendo los valores a través de serialprintln. Me gustaría que el motor se posicionara en un punto concreto y coincide con el valor específico, en este caso es 377, ¿Me podes ayudar?, es que yo no se como se escribe eso en el código.

Este es el código donde debe estar ese valor de posicionamiento.

Gracias de antemano.

int valBot = 0;			// variable que usamos para recoger la señal del sensor
int pinsensor = A0;		// Con este pin recogemos las señales del sensor
int pinLaser = 4;    // Pin donde esta conectado el laser
int pinLed = 6;      // Pin donde está conectado el LED de estado
int pinStep = 7;  	// Pin del Step del EasyDriver 
int pinDirec = 8;	// Pin de Direction del EasyDriver

void setup() {
Serial.begin(9600);	// Iniciamos comunicación serial
}

void ajusteMotor(){
valBot = analogRead(pinsensor);		// Lectura analógica del pin del sensor
if (valBot ==377), 					// Este es el valor que quiero implementar

    digitalWrite(pinLed, HIGH);   // enciendo el led
    digitalWrite(pinDirec, HIGH);  // cambio la dirección
    for (int pos2 = 0; pos2<posVert; pos2++)
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 

    digitalWrite(pinLaser, HIGH);   // Enciendo el laser
}

Si quieres que alguien se tome el tiempo para ayudarte al menos pon el código completo.
¿Casi 10 años en el foro y no sabes que códigos parciales no sirven de nada y menos para hacerle modificaciones?

Perdón, pongo el código completo.

include <Stepper.h>	// Cargo la librería de motores a pasos

int pinLaser = 4;   // Pin donde tengo conectado el láser
int pinLed = 6;     // Pin donde tengo conectado el LED de estado
int pinBoton = A0;   // Pin donde está conectado el interruptor de fin de carrera (Cambiado por sensor de proximidad, lectura analógica) del motor. 
int pinStep = 7;  	// Pin de Step del EasyDriver
int pinDirec = 8;	// Pin de Direction del EasyDriver
int valBot = 0;   // Estado del botón del motor  ¿Puede ser el LDR este botón? DUDA
int micropausa = 1800;	// Pausa entre paso y paso (Anchura de los haces) 2000 esta bien
int micropausaInicio = 1500;  //microsegundos de pausa entre (micro)paso y (micro)paso en la secuencia de inicio
int posVert = 465;  // 465;  Número de (micro)pasos que deja el espejo para que el láser esté en su sitio al comienzo
int sensor = 155;   // 155;  Umbral de sensibilidad del fotorresitor. Cuanto más bajo, más sensible a la luz. En cuarto oscuro funciona bien con 160
int micropausaLaser = 3000;   // Tiempo que se queda encendido el láser (microsengudos). En mi caso, va bien con 2000
int micropausaSensor = 2000; // Pausa tras apagar láser y antes de girar, para dar tiempo al sensor a reaccionar (microsengudos). En mi caso, va bien con 2000
int haces = 8;        // Número haces de láser
int pasosHaces = 3;  // Controlamos el ancho del abanico

int noteStatus[] = {0,0,0,0,0,0,0,0};	// Inicializo el estado de las notas (sonando/no sonando). Debe haber el mismo número que número de haces

int notasMIDI[] = {60,62,64,65,67,69,71,72};	//   Notas asignada a cada haz. Debe haber el mismo número que número de haces



void setup() {

  pinMode(pinLaser, OUTPUT);        // Declaro el pin del laser
  digitalWrite(pinLaser, LOW);   // Apago el laser

  pinMode(pinLed, OUTPUT);  // Declaro el pin del Led de status
  digitalWrite(pinLed, LOW);  // Dejo el Led de estatus apagado

   // Configurar Seguidor de lineas para dejar el laser centrado
  Serial.begin(9600); // 
  pinMode(pinBoton, OUTPUT); 

  ajusteMotor();  // Llamo a la función ajusteMotor() para colocar el espejo en su sitio y arrancar la secuencia de incio

  //Arranco MIDI:
  Serial.begin(31250);	// Especifico el canal de comunicación para MIDI  
  Serial.write(192);	// Byte para cambiar de instrumento en canal 0
  Serial.write(15);	// Número de instrumento

  delay(100);

}

// Pongo el motor/espejo en su sitio al comienzo y secuencia de inicio:
void ajusteMotor()
{

  int numpasosini;   //número de pasos en la secuencia de inicio (se calcula automáticamente)
  int contini=0;  // contador secuencia de inicio (se calcula automáticamente)
 
  pinMode(pinBoton, INPUT); // Declaro el pin del boton como input
  pinMode(pinDirec, OUTPUT);
  pinMode(pinStep, OUTPUT);
  digitalWrite(pinDirec, LOW);
  digitalWrite(pinStep, LOW);

  for (int pos = 0; pos < 4000; pos++)
  {
   valBot = analogRead(pinBoton);
   if (valBot == LOW)
   {         // si el botón está pulsado:
    //digitalWrite(pinLed, HIGH);   // Enciendo el led
    digitalWrite(pinDirec, HIGH);  // Cambio la dirección
      for (int pos2 = 0; pos2<posVert; pos2++)
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 

    digitalWrite(pinLaser, HIGH);   // Enciendo el laser

   

    // Secuencia abanico desplegado totalmente, acelerando linealmente:
    numpasosini=(haces-1)*pasosHaces*17/2;   // Calculo el número de pasos en la secuencia de inicio

    // Compruebo la célcula fotoeléctrica, y mando arrancar la secuencia de inicio cuando se active:
    while(true)
    {
      if ( (analogRead(0) > sensor*2 ) )     // Si el sensor recibe señal
      {
        digitalWrite(pinLed, HIGH);   // Enciendo el led
        digitalWrite(pinDirec, LOW);  // Cambio la dirección
        for (int pos2 = 0; pos2<((haces-1)*pasosHaces/2); pos2++)
        {
           digitalWrite(pinStep, LOW);
           digitalWrite(pinStep, HIGH);
           digitalWrite(pinLaser, HIGH);   // Enciendo el laser
           delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
           digitalWrite(pinLaser, LOW);   // Apago el laser
        }
        for (int pos3 = 0; pos3<4; pos3++)
        {
          digitalWrite(pinDirec, HIGH);  // Cambio la dirección
          for (int pos2 = 0; pos2<((haces-1)*pasosHaces); pos2++)
          {
             digitalWrite(pinStep, LOW);
             digitalWrite(pinStep, HIGH);
             digitalWrite(pinLaser, HIGH);   // Enciendo el laser
             delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
             digitalWrite(pinLaser, LOW);   // Apago el laser
          }
          digitalWrite(pinDirec, LOW);  // Cambio la dirección
          for (int pos2 = 0; pos2<((haces-1)*pasosHaces); pos2++)
          {
             digitalWrite(pinStep, LOW);
             digitalWrite(pinStep, HIGH);
             digitalWrite(pinLaser, HIGH);   // Enciendo el laser
             delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
             digitalWrite(pinLaser, LOW);   // Apago el laser
          }
        }
        break;
      }
    }

       break;
   }
   else
   {        // el botón no está pulsado:
    digitalWrite(pinLed, LOW);  // Mantengo el led apagado

    digitalWrite(pinStep, LOW);
    digitalWrite(pinStep, HIGH);
    delayMicroseconds(micropausa);

   }
  }
}




void loop()
{
  for (int pos = 1; pos < haces; pos++)
  { // En una dirección
    digitalWrite(pinDirec, HIGH);	// Establezco la dirección del motor
    digitalWrite(pinLaser, HIGH);	// Enciendo el láser
    delayMicroseconds(micropausaLaser);	// Dejo el láser encendido el tiempo micropausaLaser

    // Compruebo la célcula fotoeléctrica, y mando tocar/parar de tocar la nota correspondiente:
    if ( (analogRead(0) > sensor ) && ( noteStatus[pos] == 0 ))     // Si el sensor recibe señal, y la nota no está sonando
    {
      noteMIDI(0x90, notasMIDI[pos-1], 0x45); // Que se toque la nota por MIDI
      digitalWrite(pinLed, HIGH); // Enciendo el Led de estado
      noteStatus[pos]++;  // Cambio el estado de esa nota a "sonando"
    }
    else if (analogRead(0) < sensor )   // Si el sensor no recibe señal
    {
      if (noteStatus[pos] >= 1) // Si hay una nota tocando (porque aún no la he apagado, aunque no haya señal)
      {
        
          noteMIDI(0x90, notasMIDI[pos-1], 0x00);  // Parar de tocar la nota por MIDI
          digitalWrite(pinLed, LOW);  // Apago el led de estado
          noteStatus[pos]=0;  // Cambio el estado de esa nota a "apagada"
      }
    }
    
    digitalWrite(pinLaser, LOW);      // Apago el láser   
    delayMicroseconds(micropausaSensor); // Antes de pasar al siguiente haz, pequeña pausa para reacción del sensor fotoeléctrico

   
    
    
    
    
    //Muevo el motor al siguiente haz:
    for (int pos2 = 0; pos2<pasosHaces; pos2++) // Avanzo un haz (el número de (micro)pasos definidos en la variable pasosHaces
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 
  }
  
  for (int pos = haces; pos > 1; pos--)
  { // En la otra dirección
    digitalWrite(pinDirec, LOW);	// Pongo el motor en el sentido contrario
    digitalWrite(pinLaser, HIGH);	// Enciendo el láser
    delayMicroseconds(micropausaLaser);	// Dejo el láser encendido el tiempo micropausaLaser
    
    // Compruebo la célcula fotoeléctrica, y mando tocar/parar de tocar la nota correspondiente:
    if ( (analogRead(0) > sensor ) && ( noteStatus[pos] == 0 ))     // Si el sensor recibe señal, y la nota no está sonando
    {
      noteMIDI(0x90, notasMIDI[pos-1], 0x45); // Que se toque la nota
      digitalWrite(pinLed, HIGH); // Enciendo el Led de estado
      noteStatus[pos]++;  // Cambio el estado de esa nota a "sonando"
    }
    else if (analogRead(0) < sensor )   // Si el sensor no recibe señal
    {
      if (noteStatus[pos] >= 1) // Si hay una nota tocando (porque aún no la he apagado, aunque no haya señal)
      {
          noteMIDI(0x90, notasMIDI[pos-1], 0x00);  // Parar de tocar la nota por MIDI
          digitalWrite(pinLed, LOW);  // Apago el led de estado
          noteStatus[pos]=0;  // Cambio el estado de esa nota a "apagada"
        //}
      }
    }
    
    digitalWrite(pinLaser, LOW);      // Apago el láser   
    delayMicroseconds(micropausaSensor); // Antes de pasar al siguiente haz, pequeña pausa para reacción del sensor fotoeléctrico

   
    
    
    
    //Muevo el motor al siguiente haz:
    for (int pos2 = 0; pos2<pasosHaces; pos2++) // Avanzo un haz (el número de (micro)pasos definidos en la variable pasosHaces
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 
  }
}



void noteMIDI(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

Lo que veo es que en las instrucciones:
digitalWrite(pinStep, LOW);
digitalWrite(pinStep, HIGH);
esos cambios ni siquiera se van a notar porque no hay una pausa entre esas instrucciones, el procesador las ejecuta tan rapido que no creo que se vayan a notar

Esto es un arpa láser que estoy construyendo, es de un blog que se llama Arpa Láser | Carlini's Blog, me funciona todo excepto el posicionamiento del rayo cuando se inicia, pero luego todo lo demás va, el midi funciona, el motor con el espejo hace su función, etc,, únicamente que tengo que posicionar yo manualmente el espejo y la idea es integrar todo en una caja, de ahí mi pregunta.

Hola ya estuve explorando tu proyecto y se ve interesante, ademas ya vi el detalle con el interruptor de final de carrera que estas usando. Ese alambre que colocas para activar el final de carrera no es muy preciso puedes usar una placa circular atornillada al eje del motor provista de lobulos

Podrías subir un video en YouTube con la toma del eje del motor y el interruptor de final de carrera para ver el detalle de como se activa y así darte mis sugerencias

Buenas noches, pues si hay algún modo de posicionar el motor de manera que no necesite final de carrera sería lo ideal. La idea es que al conectar arduino, directamente se posicione en un punto concreto el motor de modo que el laser quede totalmente vertical para que inicie desde ese punto la secuencia de inicio del abanico. Ahora lo inicia desde cualquier punto en el que quede parado el motor/espejo, por tanto tengo que posicionarlo yo a mano para que quede centrado.

Intentaré hacer un video y subirlo a youtube antes del fin de semana.

Como técnico en análisis de sistemas te confirmo que tienes dos opciones:
1- Dejar todo como está y seguir posicionándolo a mano.
2- Poner un final de carrera, sea óptico, magnético o mecánico, y que la posición la busque el código.

Por otro lado solo piensas en poner el final de carrera en el eje del pap, ¿y qué pasaría si lo acoplaras al espejo?

Aqui dejo un enlace al video que he subido a youtube.

Visto el video lo relaciono con mi impresora 3D.
Cuando le indico que haga un autohome o le mando imprimir, lo primero que hace es "buscar" los finales de carrera de cada eje.
Por ejemplo, para cada eje se pueden dar 2 opciones, que ya esté tocando el final de carrera o que esté en cualquier otro punto del recorrido.
Así que si no detecta que el fin de carrera está cerrado (o sea tocando) está en la segunda opción, y mueve el motor (retrocediendo) hasta que el tope toca el final de carrera. Luego, para cualquiera de las 2 opciones, avanza x pasos y luego retrocede nuevamente hasta el final de carrera (supongo que para verificar que la posición es correcta) y vuelve a avanzar hasta la posición "cero" (que no necesariamente coincide con el fin de carrera).

Ahora, por lo que veo, tu espejo no debería dar nunca una vuelta completa, entonces nunca debería tocar más de una vez el final de carrera.
Pienso que deberías usar la misma estrategia.
Al iniciar (en setup())

Leer el estado del sensor;
Mientras el sensor esté abierto {  // while()
  Retroceder 1 paso;
  Leer el estado del sensor;
}
// aqui el motor deberia estar tocando el final de carrera
// para verificar posición
Avanzar 10 pasos;  // o los que creas oportuno
Leer sensor; // verificar que abrio
Mientras sensor abierto {
  Retroceder 1 paso;
  Contar pasos;
} 
Si retrocedio 10 pasos { // todo correcto
  Avanzar x pasos; // para llegar a la posicion "cero" del espejo.
}

En otras palabras, busca el final de carrera (si ya no está ahí) moviéndose en sentido horario, al encontrarlo se mueve determinada cantidad de pasos de control en sentido antihorario, retrocede en sentido horario para confirmar que se encontraba a tantos pasos del final de carrera, si todo es correcto se mueve en sentido antihorario tantos pasos como sean necesarios (tu sabes cuantos) para que el espejo quede en la posición inicial correcta.

Tambien puedes ponerle un enconder al motor y saber donde esta.
Un enconder absoluto tiene la ventaja que si la energía se pierde, su salida será corregida cada vez que la energía sea restablecida. No es necesario ir a una posición referencial como con los encoders de tipo incremental.

Finalmente con este código he conseguido posicionar el motor en el punto exacto donde yo lo quiero.

#include <AccelStepper.h>
const int pinStep = 7; // Pin conectado al STEP del EasyDriver
const int pinDirec = 8;  // Pin conectado al DIR del EasyDriver
const int pinBoton = 3; // Pin conectado al interruptor de final de carrera
int posVert = 90; // Sustituye este valor por el número de pasos hasta la posición X deseada

void setup() {
  pinMode(pinStep, OUTPUT);
  pinMode(pinDirec, OUTPUT);
  pinMode(pinBoton, INPUT_PULLUP); // Utiliza resistencia de pull-up interna
  findZero(); // Encuentra la posición cero
  posVert(); // Mueve el motor a la posición X
}

void loop() {
  
}

void findZero() {
  // Asume que mover el motor en dirección LOW lo acerca al interruptor de final de carrera
  digitalWrite(pinDirec, LOW);
  while (digitalRead(pinBoton) == HIGH) { // Mientras el interruptor no esté presionado
    stepMotor();
  }
  // Aquí el motor ha presionado el interruptor, indicando la posición cero
}

void moveToX() {
  // Cambia la dirección para alejarse del interruptor y moverse hacia la posición X
  digitalWrite(pinDirec, HIGH);
  for (int i = 0; i < posVert; i++) { // Mueve el motor un número fijo de pasos para llegar a X
    stepMotor();
  }
}

void stepMotor() {
  digitalWrite(pinStep, HIGH);
  delay(1); // Ajusta este valor para controlar la velocidad del motor
  digitalWrite(pinStep, LOW);
  delay(1); // Ajusta este valor para controlar la velocidad del motor
}

que bien que ya lo hayas resuelto, la idea del encoder me parece muy buena

Cierto, como esto solo es un prototipo quizás pruebe también con el encoder. Ya veremos

Varias cosas:

  1. Tu quieres reemplazar un microswitch por un sensor óptico. Okay. Pero usas un PAP Motor Paso a Paso. No entiendo algo entonces. El PAP en algun momento quedó en la posición correcta o en una que no lo es, digamos no en la que quieres arrancar pero si conoces su posición relativa y por ende también la absoluta o sea (diferencia con la inicial).
    Se trata de un motor paso a paso. En algun momento le dijiste respecto de la posición inicial muevente 20, 50, 100 vuelve 30. Siempre sabes donde esta. En eso decides apagar, pues bien, guarda la posición relativa al sensor en EEPROM. Listo!! se terminó tu dilema.
    Al arrancar lees la posición. Motor PAP en el paso 140 respecto a sensor optico y actuas en consecuencia.

Por si lo anterior no sirve..

  1. Insisto con el encoder, debe ser absoluto sino pierdes la posicion cuando lo apagas o debes dotarlo de electronica que no le permite perder la posicion o sea volverlo inteligente.
    Si compras un enconder común digamos, tendras que hacer lo mismo que los fines de carrera, ir hasta una posición y leer desde ahi.