Cargar valor inicial encoder

Buenas compañeros, estoy haciendo pruebas para realizar un proyecto de una puerta automática, siempre sabremos la posición de esta utilizando un encoder, el problema que me surge es el siguiente, como puedo cargar un valor de inicio al encoder en el setup y que en el loop continúe por dicho valor? he probado pero al ejecutar myEnc.read() siempre vuelve a 0. Alguna sugerencia?


#include <Encoder.h>
Encoder myEnc(5, 6);
int posicion_anterior; // SUPONGAMOS QUE ES 145
long newPosition;

void setup() {
  Serial.begin(9600);
 newPosition = posicion_anterior; // AQUI GUARDO EL 145
}

long oldPosition  = -999;

void loop() {
   newPosition = myEnc.read(); // AQUI VUELVE A 0
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

No hay forma, no estas usando encoder que retengan el valor de su posición. Si aun lo guardaras en EEPROm al momento de apagar el Arduino y lo leyeras cuando se energice fallaría si alguien adrede moviera la puerta y el encoder modificara la posición.
De todos modos esa es tu unica posibilidad. Guardar la pos en EEPROM cuando se detecta que te quedas sin energia.

Gracias por la respuesta Surbyte, te comento, el sistema llevará una shield ups para mantener alimentado arduino tras un corte de corriente, que a su vez mediante un relé detectaré por un pin cualquiera la falta de alimentación, me falta por llegar la placa. Lo que si he estado probando es almacenar un valor en una microsd, el cual lo leo en el setup al iniciar el programa de nuevo, pero el problema es que no se cargar ese valor al encoder para que continúe por donde quedó (ya se que se puede mover la puerta y seria una falla). Adjunto el código completo a falta de implementar el grabado y lectura en microsd. Gracias

//----------------------------------------------------------------------------
//--------------------------------------------------------------------------
// PROGRAMA PUERTA AUTOMATICA CON BARRERA DE SEGURIDAD,ENCODER Y CIERRE AUTOMATICO
//---------------------------------------------------------------------------------------------
// PIN-2 --- PULSADOR ABRIR
// PIN-3 --- PULSADOR CERRAR
// PIN-4 --- BARRERA SEGURIDAD
// PIN-5 --- ENCODER A
// PIN-6 --- ENCODER B
// PIN-7 --- BANDA SEGURIDAD
// PIN-8 --- RELE SALIDA ABRIR
// PIN-9 --- RELE SALIDA CERRAR
// PIN-10 -- RELE SALIDA FRENO MOTOR

#include <Encoder.h>
Encoder myEnc(5, 6);
long newPosition;
long oldPosition  = -999;

unsigned long tiempo;
unsigned long tiempo1;
int tiempo_retardo = 5000;
int resultado;
// Constantes para definir los pines
//#define micro_abierta 4
//#define micro_cerrada 5
#define pulsador_abrir 2
#define pulsador_cerrar 3
#define rele_abrir 8
#define rele_cerrar 9
#define rele_freno 10
#define barrera_seguridad 4
#define banda_seguridad 7
//--------------------------------
const int ledPin = 13;
bool puerta_abierta = false;
bool puerta_cerrada = false;
bool subiendo = false;
bool bajando = false;
bool estado_puerta_indefinido = false;
bool cierre_auto = false;
bool bloqueo_tiempo = false;
bool emergencia = false;
bool retardo = false;

bool valor_pulsador_abrir = false;
bool valor_pulsador_cerrar = false;
bool estado_micro_abierta = false;
bool estado_micro_cerrada = false;
bool estado_barrera_seguridad = false;
bool estado_banda_seguridad = false;

void setup() {
  retardo = false;  //----------------CAMBIAR A TRUE SI QUEREMOS ACTIVAR EL RETARDO CIERRE AUTOMATICO--------------------------
  cierre_auto = false;
  bloqueo_tiempo = false;
  pinMode(pulsador_abrir, INPUT);
  pinMode(pulsador_cerrar, INPUT);
  pinMode(ledPin, OUTPUT);
//  pinMode(micro_abierta, INPUT);
//  pinMode(micro_cerrada, INPUT);
  pinMode(rele_abrir, OUTPUT);
  pinMode(rele_cerrar, OUTPUT);
  pinMode(barrera_seguridad, INPUT);
  pinMode(rele_freno, OUTPUT);
  pinMode(banda_seguridad, INPUT);
  digitalWrite(rele_abrir, LOW);
  digitalWrite(rele_cerrar, LOW);
  digitalWrite(rele_freno, LOW);
  Serial.begin(9600);
}



void loop() {
  tiempo = millis();
  valor_pulsador_cerrar = digitalRead(pulsador_cerrar);
  valor_pulsador_abrir = digitalRead(pulsador_abrir);
  estado_barrera_seguridad = digitalRead(barrera_seguridad);
  estado_banda_seguridad = digitalRead(banda_seguridad);
//  estado_micro_abierta = digitalRead(micro_abierta);
//  estado_micro_cerrada = digitalRead(micro_cerrada);

  if (newPosition <= 0){
    puerta_cerrada = true;
  } else{
    puerta_cerrada = false;
  }


  if (newPosition >= 50){
    puerta_abierta = true;
  } else{
    puerta_abierta = false;
  }
  
//  if (estado_micro_abierta) {
//    puerta_abierta = true;
//  } else {
//    puerta_abierta = false;
//  }

//  if (estado_micro_cerrada) {
//    puerta_cerrada = true;
//  } else {
//    puerta_cerrada = false;
//  }

  if (estado_banda_seguridad | estado_barrera_seguridad){
    emergencia = true;
  }else{
    emergencia = false;
  }
  
  lectura_encoder();
  cierre_puerta();
  apertura_puerta();
  parada_cierre();
  parada_apertura();
//  apertura_sin_posicion();
  subida_emergencia();
  temporizador();
  

  //Serial.println(emergencia);
}






void cierre_puerta() {
  if (emergencia == false && !subiendo && puerta_abierta && valor_pulsador_cerrar == true) {
    digitalWrite(rele_cerrar, HIGH);
    digitalWrite(rele_freno, HIGH);
    bajando = true;
    Serial.println("Cerrando Puerta");
  }
}

void apertura_puerta() {
  if (!bajando && puerta_cerrada && valor_pulsador_abrir == true) {
    digitalWrite(rele_abrir, HIGH);
    digitalWrite(rele_freno, HIGH);
    subiendo = true;
    Serial.println("Abriendo Puerta");
  }
}

void parada_cierre() {
  if (bajando | cierre_auto && puerta_cerrada) {
    digitalWrite(rele_cerrar, LOW);
    digitalWrite(rele_freno, LOW);
    bajando = false;
    cierre_auto = false;
    bloqueo_tiempo = false;
    Serial.println("Puerta Cerrada");
  }
}

void parada_apertura() {
  if (subiendo && puerta_abierta) {
    digitalWrite(rele_abrir, LOW);
    digitalWrite(rele_freno, LOW);
    subiendo = false;
    cierre_auto = false;
    Serial.println("Puerta Abierta");
  }
}

void apertura_sin_posicion() {
  if (!puerta_abierta && !puerta_cerrada && valor_pulsador_abrir == true) {
    digitalWrite(rele_abrir, HIGH);
    digitalWrite(rele_freno, HIGH);
    subiendo = true;
    Serial.println("Buscando Posición");
  }
}

void subida_emergencia() {
  if (bajando | cierre_auto && emergencia) {
    digitalWrite(rele_cerrar, LOW);
    digitalWrite(rele_abrir, HIGH);
    bajando = false;
    subiendo = true;
    bloqueo_tiempo = false;
    Serial.println("Apertura Seguridad");
  }
}


void temporizador() {
  if (retardo && puerta_abierta && !bloqueo_tiempo && !emergencia) {
    tiempo1 = tiempo;
    resultado = tiempo1 + tiempo_retardo;
    bloqueo_tiempo = true;
    Serial.println(tiempo1);
    Serial.println(resultado);
  }

  if (!emergencia && retardo && puerta_abierta && tiempo > tiempo1 + tiempo_retardo) {
    digitalWrite(rele_freno, HIGH);
    digitalWrite(rele_cerrar, HIGH);
    cierre_auto = true;
    bajando = true;
    Serial.println("Cierre auto");
  }
}

void lectura_encoder(){
   newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

No puedes hacer eso.
Carga el valor en la variable que acumule la posicion del enconder y en lugar que arranque en una posicion extrema, que lo haga con la que tenía.
Tienes estas variable para indicarlo

long newPosition;

que arranca en 0, bueno en el setup si se reinicia el arduino o donde corresponda a un ciclo de reinicio lo cargas con el valor almacenado en la SD.
podrias manejar una variable llamada offset que puede valer 0 si no hay reinicio y ALGO leído de la SD si lo hubiera.

void lectura_encoder(){
   newPosition = myEnc.read() + offset;  // y aca se ve el cambio
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

si esa variable offset normalmente no afecta lo que lea el encoder pero si el sistema se apaga y luego reinica el encoder pierde referencia y parte de 0. Entonces offset supongamos quedó en 23000 y le agrega a lo que de ahi en mas haga el movimiento ese valor anterior que no es oldPositon.
Se comprende la idea?

1 Like

Ahora lo he entendido!, he modificado el código añadiendo la lectura y escritura de la variable desde la SD pero me surgen 2 problemas (he cambiado a MEGA por falta de pines)

//----------------------ARDUINO MEGA------------------------------------------------------
//--------------------------------------------------------------------------
// PROGRAMA PUERTA AUTOMATICA CON BARRERA DE SEGURIDAD,ENCODER Y CIERRE AUTOMATICO
//---------------------------------------------------------------------------------------------
// PIN-0 ---
// PIN-1 ---
// PIN-2 --- PULSADOR ABRIR
// PIN-3 --- PULSADOR CERRAR
// PIN-4 --- SCK MICRO SD
// PIN-5 --- ENCODER A
// PIN-6 --- ENCODER B
// PIN-7 --- BANDA SEGURIDAD
// PIN-8 --- RELE SALIDA ABRIR
// PIN-9 --- RELE SALIDA CERRAR
// PIN-10 -- RELE SALIDA FRENO MOTOR
// PIN-11 -- BARRERA SEGURIDAD
// PIN-12 -- RELE FALLO ALIMENTACIÓN
// PIN-50 -- MISO MICRO SD
// PIN-51 -- MOSI MICRO SD
// PIN-52 -- SCK MICRO SD



#include <SD.h>
#include <SPI.h>
#include <Encoder.h>
File myFile;
Encoder myEnc(5, 6);
long newPosition;
long oldPosition  = -999;
int posicion_anterior;


unsigned long tiempo;
unsigned long tiempo1;
int tiempo_retardo = 5000;
int resultado;
// Constantes para definir los pines
#define pulsador_abrir 2
#define pulsador_cerrar 3
#define banda_seguridad 7
#define rele_abrir 8
#define rele_cerrar 9
#define rele_freno 10
#define barrera_seguridad 11
#define fallo_alimentacion 12


//--------------------------------
const int ledPin = 13;
bool puerta_abierta = false;
bool puerta_cerrada = false;
bool subiendo = false;
bool bajando = false;
bool estado_puerta_indefinido = false;
bool cierre_auto = false;
bool bloqueo_tiempo = false;
bool emergencia = false;
bool retardo = false;
bool bloqueo = false;

bool valor_pulsador_abrir = false;
bool valor_pulsador_cerrar = false;
bool estado_micro_abierta = false;
bool estado_micro_cerrada = false;
bool estado_barrera_seguridad = false;
bool estado_banda_seguridad = false;
bool estado_alimentacion = false;


void setup() {
  retardo = false;  //----------------CAMBIAR A TRUE SI QUEREMOS ACTIVAR EL RETARDO CIERRE AUTOMATICO--------------------------
  cierre_auto = false;
  bloqueo_tiempo = false;
  estado_alimentacion = false;
  bloqueo = false;
  pinMode(fallo_alimentacion, INPUT);
  pinMode(pulsador_abrir, INPUT);
  pinMode(pulsador_cerrar, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(rele_abrir, OUTPUT);
  pinMode(rele_cerrar, OUTPUT);
  pinMode(barrera_seguridad, INPUT);
  pinMode(rele_freno, OUTPUT);
  pinMode(banda_seguridad, INPUT);
  digitalWrite(rele_abrir, LOW);
  digitalWrite(rele_cerrar, LOW);
  digitalWrite(rele_freno, LOW);
  Serial.begin(9600);


  if (!SD.begin(4)) {
    Serial.println("No se pudo inicializar");
    return;
  }
  Serial.println("inicializacion exitosa");
  LeeArchivo();
 
  
}



void loop() {
  tiempo = millis();
  valor_pulsador_cerrar = digitalRead(pulsador_cerrar);
  valor_pulsador_abrir = digitalRead(pulsador_abrir);
  estado_barrera_seguridad = digitalRead(barrera_seguridad);
  estado_banda_seguridad = digitalRead(banda_seguridad);
  estado_alimentacion = digitalRead(fallo_alimentacion);

  if (newPosition <= 0) {
    puerta_cerrada = true;
  } else {
    puerta_cerrada = false;
  }


  if (newPosition >= 50) {
    puerta_abierta = true;
  } else {
    puerta_abierta = false;
  }

  if (estado_banda_seguridad | estado_barrera_seguridad) {
    emergencia = true;
  } else {
    emergencia = false;
  }

  lectura_encoder();
  cierre_puerta();
  apertura_puerta();
  parada_cierre();
  parada_apertura();
  //  apertura_sin_posicion();
  subida_emergencia();
  temporizador();
  falta_alimentacion();
}






void cierre_puerta() {
  if (emergencia == false && !subiendo && puerta_abierta && valor_pulsador_cerrar == true) {
    digitalWrite(rele_cerrar, HIGH);
    digitalWrite(rele_freno, HIGH);
    bajando = true;
    Serial.println("Cerrando Puerta");
  }
}

void apertura_puerta() {
  if (!bajando && puerta_cerrada && valor_pulsador_abrir == true) {
    digitalWrite(rele_abrir, HIGH);
    digitalWrite(rele_freno, HIGH);
    subiendo = true;
    Serial.println("Abriendo Puerta");
  }
}

void parada_cierre() {
  if (bajando | cierre_auto && puerta_cerrada) {
    digitalWrite(rele_cerrar, LOW);
    digitalWrite(rele_freno, LOW);
    bajando = false;
    cierre_auto = false;
    bloqueo_tiempo = false;
    Serial.println("Puerta Cerrada");
  }
}

void parada_apertura() {
  if (subiendo && puerta_abierta) {
    digitalWrite(rele_abrir, LOW);
    digitalWrite(rele_freno, LOW);
    subiendo = false;
    cierre_auto = false;
    Serial.println("Puerta Abierta");
  }
}

void apertura_sin_posicion() {
  if (!puerta_abierta && !puerta_cerrada && valor_pulsador_abrir == true) {
    digitalWrite(rele_abrir, HIGH);
    digitalWrite(rele_freno, HIGH);
    subiendo = true;
    Serial.println("Buscando Posición");
  }
}

void subida_emergencia() {
  if (bajando | cierre_auto && emergencia) {
    digitalWrite(rele_cerrar, LOW);
    digitalWrite(rele_abrir, HIGH);
    bajando = false;
    subiendo = true;
    bloqueo_tiempo = false;
    Serial.println("Apertura Seguridad");
  }
}


void temporizador() {
  if (retardo && puerta_abierta && !bloqueo_tiempo && !emergencia) {
    tiempo1 = tiempo;
    resultado = tiempo1 + tiempo_retardo;
    bloqueo_tiempo = true;
    Serial.println(tiempo1);
    Serial.println(resultado);
  }

  if (!emergencia && retardo && puerta_abierta && tiempo > tiempo1 + tiempo_retardo) {
    digitalWrite(rele_freno, HIGH);
    digitalWrite(rele_cerrar, HIGH);
    cierre_auto = true;
    bajando = true;
    Serial.println("Cierre auto");
  }
}

void lectura_encoder() {
  newPosition = myEnc.read() + posicion_anterior;
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

void falta_alimentacion() {
  if (estado_alimentacion == true) {
    Serial.println("CORTE ALIMENTACION");
    guardar();
  }
}


void LeeArchivo()
{
  myFile = SD.open("PRUEBA.txt");

  if (myFile)
  {
    while (myFile.available())
    {
      char palabra = myFile.read();
      //Serial.print(palabra);

      posicion_anterior = myFile.parseInt();
      Serial.println(posicion_anterior);
    }
    myFile.close();

  }
  else
  {
    Serial.println("Error Al Abrir El Archivo");
  }
}

void guardar() {

  if (!bloqueo) {
    SD.remove("PRUEBA.txt");

    myFile = SD.open("PRUEBA.txt", FILE_WRITE);
    if (myFile) {
      Serial.print("Escribiendo valor");
      myFile.seek(0);
      myFile.println(newPosition);
      // close the file:
      myFile.close();
      bloqueo = true;

    } else {
      
      Serial.println("Error al abrir archivo");
    }
  }
}

Cuando ejecuto este void

void guardar() {

  if (!bloqueo) {
    SD.remove("PRUEBA.txt");

    myFile = SD.open("PRUEBA.txt", FILE_WRITE);
    if (myFile) {
      Serial.print("Escribiendo valor");
      myFile.seek(0);
      myFile.println(newPosition);
      // close the file:
      myFile.close();
      bloqueo = true;

    } else {
      
      Serial.println("Error al abrir archivo");
    }
  }
}

Después chequeo la sd y efectivamente el valor está ahí (el guardado lo hago borrando y creando de nuevo por que no se como leer el ultimo valor si hay mas de uno).

Cuando ejecuto la lectura solo me aparece el ultimo digito

void LeeArchivo()
{
  myFile = SD.open("PRUEBA.txt");

  if (myFile)
  {
    while (myFile.available())
    {
      char palabra = myFile.read();
      //Serial.print(palabra);

      posicion_anterior = myFile.parseInt();
      Serial.println(posicion_anterior);
    }
    myFile.close();

  }
  else
  {
    Serial.println("Error Al Abrir El Archivo");
  }
}

No se si estoy leyendo de manera correcta el archivo.

Y el otro problema es que veo es que el encoder parece que no hace todas las lecturas que debería.

Estás leyendo de forma correcta pero debes almacenar el caracter leído en una String o array char hasta encontrar un final de línea, recien entonces haces la conversión a entero.
Algo así

char caracter = myFile.read();
if (caracter != "\n") {
  palabra = palabra + caracter;
}
else {
  Serial.println(palabra);
}

Por otro lado, ¿No puedes usar un potenciómetro multivueltas (o uno común si no necesitas que gire más de 270°) en lugar de un encoder?
Te ahorrarías tener que guardar la posición ya que la leerías desde el potenciómetro.

Saludos

1 Like

Gracias por tu respuesta, voy a probar tu recomendación a ver si lo consigo, referente al encoder tiene que ser así, es para una puerta enrollable, por tanto el eje da muchas vueltas y por eso no me llega ni para un potenciómetro multivuelta, ya he corregido la lectura del encoder, lo tenia conectado en los pines 5 y 6 los cuales no tienen interrupción, ahora lo tengo conectado en los pines 2 y 3 y ahora si que lee todos los pulsos, lo que no se es si se puede cambiar el tipo de lectura del encoder, el que utilizo marca que son 600 pulsos por vuelta y arduino lee 2400 aprox, entiendo que es cuadratura X4 que lee todos los flancos, me gustaría que leyera menos, no se si será posible, un saludo

Funciona perfecto gatul, ya solo me queda intentar que el encoder tenga menos resolución, voy a probar dividiendo el resultado entre 4 a ver si funciona correctamente todo el programa

void LeeArchivo()
{
  myFile = SD.open("PRUEBA.txt");

  if (myFile)
  {
    while (myFile.available())
    {
      char caracter = myFile.read();
      if (caracter != "\n") {
        palabra = palabra + caracter;
        posicion_anterior = palabra.toInt();
      }

    }
    myFile.close();

  }
  else
  {
    Serial.println("Error Al Abrir El Archivo");
  }
}

Permitime que te cambie algo

void LeeArchivo()
{
  myFile = SD.open("PRUEBA.txt");

  if (myFile)
  {
    while (myFile.available())
    {
      char caracter = myFile.read();
      if (caracter != "\n") {
        palabra = palabra + caracter;
      }
      else {
        posicion_anterior = palabra.toInt();
        break;
      }
    }
    myFile.close();

  }
  else
  {
    Serial.println("Error Al Abrir El Archivo");
  }
}

Así solo hace la conversión a entero cuando se leyó el número completo y encuentra el final de línea.

Saludos

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.