viernes, 4 de marzo de 2022

205 - Distancia SR04 via UART EP2C5


Medición de distancia con sensor HC-SR04


Estimado lector te doy la bienvenida a mi blog referido a la descripción de circuitos digitales con Verilog, en esta ocasión veremos implementar un circuito para medir la distancia de un sensor ultrasónico HC-SR04 y mostrar su valor en centímetros a través de una comunicación serial asíncrona UART. La descripción del circuito puede implementarse en cualquier FPGA, pero en este caso haremos uso de la tarjeta EP2C5 de bajo costo que utiliza el modelo FPGA Cyclone II fabricado por Altera. También mencionar que se da por entendido contar con conocimientos sobre dispositivos lógicos programables(FPGA), el uso de lenguajes descriptivos(Verilog), así mismo contar con el software Quartus Web 13.0 instalado en una PC y para la implementación se requiere un programador(USB-Blaster) y la placa EP2C5 o similar. En Bolivia estos dispositivos lo puedes conseguir en la tienda SAWERS, aquí encontraras incluso modelos menos anticuados que la Cyclone II y en función a tu economía puedes comprar cualquiera siempre que sea de la marca Altera.

En una entrada anterior de mi blog resumo como introducción algunos datos adicionales acerca de la tarjeta EP2C5 y lo que necesitas para crear tus circuitos digitales. Dejo el enlace: <<Tarjeta EP2C5T>>

Descripción del circuito

El sensor ultrasónico HC-SR04 es un modulo bastante económico que sirve para medir la distancia de objetos y cuyo principio de funcionamiento es emitir una señal no audible y recibir su reflejo ante la presencia de cualquier obstáculo.

Si revisamos la hoja de datos del modulo podemos resumir lo siguiente:

  • El voltaje de operación es de 5VDC;
  • Consumo máximo de corriente es 20mA;
  • Rango de medición 2cm a 400cm;
  • Rango total de apertura es 30 grados.
La siguiente imagen describe el principio de operación:

Fig1. Operación del sensor ultrasónico SR04


Para dar inicio al proceso de medición con el sensor, se debe aplicar un pulso de disparo inicial en el pin TRIGGER, el mismo deberá tener una duración de al menos 10uS, una vez recibido el pulso el modulo emitirá al espacio una señal no audible(ocho tonos pulsantes de 40KHz), que durante su recorrido podrá reflejarse en cualquier obstáculo siendo este nuestro objetivo de medición, entonces la señal reflejada es capturada por un receptor posibilitando de esta manera determinar la distancia en base al retardo entre la emisión y recepción de los pulsos, como salida final el modulo a través del pin ECHO emite un pulso con un tiempo de duración proporcional al retardo. 

Para la lectura del sensor el circuito a describir debe medir el ancho del pulso en la señal ECHO y determinar la distancia considerando que los pulsos viajan a la velocidad del sonido(343m/s), y calculando la velocidad en relación a la distancia recorrida en un lapso de tiempo.

Fig2. Ecuaciones de calculo

La distancia total para el calculo incluye la distancia que recorre la señal emitida hacia objeto y la distancia reflejada desde el objeto, considerando este aspecto la ecuación final se muestra en la siguiente imagen.

Fig3. Ecuación para calcular la distancia en cm.


En esencia un contador de microsegundos es el circuito base para medir el ancho de pulso en la entrada ECHO, con los rangos de medición del sensor que van desde los 2cm hasta los 400cm, el contador deberá guardar valores desde 117us hasta 23529us, es decir que se necesitara un registro de 15 bits(0-32767).

Describiremos el modulo drvsr04.v que llevara a cabo la tarea de disparar el sensor, leer el ancho de pulso, determinar la distancia en cm y enviar esta información por una salida digital de 9 bits(0-511cm), a nivel de bloque se ilustra el esquema en la figura 4.  

Fig4. Esquema gráfico del modulo

Las señales del modulo se describen como:

  • clkus:Entrada de pulsos de 1us 
  • rstn:Entrada de reinicio  
  • echo:Entrada de recepción de señal 
  • start:Salida para inicio de lectura  
  • trig:Salida para iniciar la transmisión 
  • data:Dato con la distancia en cm

A nivel funcional la tarea que lleva a cabo este modulo puede ilustrase en el diagrama de estados de la figura 5.

Fig5. Diagrama de estado en el modulo drvsr04
 

Los estados del modulo se describen como:

  • INIT: Espera pulso de inicio
  • TRIG: Retardo pulso de 10us
  • ECHO: Espera un transición ascendente
  • WAIT: Cuenta los ciclos de reloj

El código verilog del modulo drvsr04 es el siguiente:

module drvsr04(clkus, rstn, trig, echo, start, data);
input clkus, rstn, echo, start;
output reg trig;
output reg [8:0] data; //distancia en cm 0-400
reg [14:0] cnt; //Contador de pulsos 15 bits
localparam INIT=0, TRIG=1, ECHO=2, WAIT=3;
reg [1:0] state;
reg start_d0, start_d1; //Lecturas del pin
wire start_flag; //Indicador de flanco
assign start_flag = (~start_d1) & start_d0; //LTOH
always @(posedge clkus or negedge rstn)
begin
  if(rstn == 0)
  begin
    data <= 9'd0;
    cnt <= 15'd0;
    trig <= 1'b0;
    start_d0 <= 1'b0;
    start_d1 <= 1'b0;
    state <= INIT;
  end
  else
  begin
  start_d0 <= start; //Almacena estado actual
  start_d1 <= start_d0; //Almacena estado previo
  case(state)
    INIT:if(start_flag && (echo==0))
         begin
           trig <= 1'b1;
           cnt <= 15'd0;
           state <= TRIG;
         end
    TRIG:if(cnt > 19) //Espera los 10us
         begin
           trig <= 1'b0;
           cnt <= 15'd1; //Inicia en 1
       state <= ECHO;
         end
         else cnt <= cnt + 1'b1;
    ECHO:if(echo > 0)
           state <= WAIT;
    WAIT:if(echo < 1)
         begin
           data <= ((34 * cnt) / 2000); //(0.034cm * us)/2   
              state <= INIT;
         end
  endcase
  end
end
endmodule

El modulo drvsr04 representa una de las partes que se requiere para recibir la distancia del obstáculo en el circuito propuesto, y al que se agregara el modulo uart_send detallado en una entrada previa para mostrar el resultado. Entonces continuando con el circuito, la siguiente figura nos muestra como estaría conformado.

Fig6. Conformación del circuito para medir y mostrar distancia

El circuito descrito en el modulo sr04uartsend debe tomar el dato de 9 bits del modulo drvsr04, ya que este contiene la distancia en centímetros (0 a 400cm), luego las centésimas, décimas y unidades se codificaran en ASCII para ser almacenados en diferentes registros bytes conformando así un mensaje que sera enviado a través del modulo uart_send

La funcionalidad del modulo sr04uartsend se ilustra en el diagrama de estado de la figura 7, la cual se asemeja al diagrama utilizado en la entrada para el envío de datos UART <<uartsenddata>>.

 

Fig7. Diagrama de estados sr04uartsend

Note que el código del modulo descriptivo sr04uartsend, posee una entrada but con la que se da inicio a la lectura y posterior envío del dato, esta entrada se activa con un flanco ascendente pero en la practica la polaridad del símbolo se invierte para así detectar un flanco descendente originado por el pulsador, es así que la frecuencia del envío del mensaje con la distancia dependerá de cuantas veces por segundo es presionado el pulsador.

module sr04uartsend(clkus, rstn, but, start, data, busy, txreg);
input clkus, rstn, busy, but;
input [8:0] data; //Dato de distancia de 9-bit
output reg start;
output reg [7:0] txreg; //Dato byte para envío UART
reg [7:0] msg[0:7]; //Arreglo byte de 8 posiciones
localparam INIT = 0; //Estado inicial de conversión al ASCII
localparam SEND = 1;
localparam WAIT = 2;
localparam COMP = 3;//Envío de datos finalizado
reg [1:0] state;
reg [3:0] pos; //4-bit para índice de posición
reg but_d0, but_d1;
wire but_flag; //Indicador de transición bajo a alto
assign but_flag= (~but_d1) & but_d0; //LTOH
always @(posedge clkus or negedge rstn)
begin
  if(!rstn)
  begin
    msg[0] = "0"; //Centesimal inicia en 0 ASCII
    msg[1] = "0"; //Decimal inicia en 0
    msg[2] = "0"; //Unidad inicia en 0
    msg[3] = 0;
    start <= 1'b0;
    pos <= 4'd0;
     but_d0 <= 1'b0;      
    but_d1 <= 1'b0;
    state <= INIT;
  end
  else
  begin
  but_d0 <= but;
  but_d1 <= but_d0;
  case(state)
  INIT: begin
    if((but_flag) && (!busy)) //Verifica transición del pulsador
      begin
        msg[0] <= (data / 100) + 8'h30; //Centésimas
        msg[1] <= ((data % 100) / 10) + 8'h30;//Décimas
        msg[2] <= ((data % 100) % 10) + 8'h30;//Unidades
       msg[3] <= 0; //Fin de linea para el mensaje     
        state <= SEND;
     end
      pos <= 0;
   end
  SEND: begin
    txreg <= msg[pos];
    start <= 1'b1; //Inicia la transmisión y lectura del sensor
    state <= WAIT;
    end
  WAIT: begin
    start <= 1'b0;   
    if(!busy) state <= COMP;
    end
  COMP: begin
    if(msg[pos] != 0) //Verifica si es fin de linea
      begin
      pos <= pos + 1'b1; //Incrementa el índice
      if(pos > 3) pos <= 4'd0; //Limite máximo
      state <= SEND;
      end
    else
      begin
      pos <= 4'd0;
      state <= INIT;
      end
    end
  endcase
  end
end
endmodule

Implementacion del circuito

Una vez efectuadas las pruebas de estimulo a los módulos previamente descritos, estos se convierten a símbolos gráficos dentro de Quartus Web y luego en un archivo de esquema se debe realizar las conexiones entre los modulos, un modulo adicional requerido para este circuito es el generador de reloj clockgen que posee tres salidas de reloj con periodos de 1us, 1ms y 1s generadas a partir de la entrada de 50MHz.

Fig8. Diagrama del circuito final

Algo muy importante al momento de montar el circuito es que a excepción de algunos modelos del sensor HC-SR04 la gran mayoría de estos trabaja con voltaje de alimentación 5V, y como los pines E/S de la FPGA operan a 3.3V sera necesario utilizar un divisor de tensión para no sobrepasar la limitación en la entrada ECHO, para el caso de salida TRIG no habrá inconvenientes ya que el voltaje del pin estará dentro de los umbrales para la lógica 5V.

Fig9. Conversión de entrada 5V a 3V

Dicho esto se procede a efectuar la conexión al sensor HC-SR04 y luego de cargar el firmware a la placa EP2C5, para este fin se llevaron a cabo las pruebas con un pulsador y luego se cambio la entrada but a la señal de reloj de 1 segundo del modulo clockgen, siendo este el tiempo de repetición para enviar el mensaje con la distancia.

Fig10. Montaje del circuito en placa EP2C5

Se muestra la terminal serial con el mensaje de distancia en centímetros, en la que un mensaje por segundo es enviado indicando los obstáculos en dos diferentes posiciones, de 220cm(Lejos) y 30cm(Cerca).

Fig11. Mensajes con distancia en cm


Conclusiones y recomendaciones

El circuito descrito trabajo conforme a los requerimiento citados, pero es importante aclarar que la finalidad del diseño e implementación de este circuito es solo educativo, por lo que no se tomaron en cuenta factores adicionales requeridos en una implementación comercial, además que usar una tecnología basada en FPGA para un fin tan básico como este caso no representa la mejor opción en el campo de la electrónica.

Es posible mejorar la optimización de los elementos lógicos en la FPGA aplicando un algoritmo que incluya elementos combinacionales en la conversión de un numero binario a BCD durante la codificación ASCII. 

Dejo a continuación el enlace para descarga del proyecto, mismo que fue creado con el software Quartus Web versión 13.0.1: <<sr04uartsend>>

Para finalizar solo quiero agradecer tu visita a mi blog, espero que el contenido de esta entrada hubiera sido de ayuda en tu formación educativa, favor cualquier consulta al respecto pueden escribirme al correo electrónico.

Pablo Cesar Zarate Arancibia.

Electrónico
pablinzte@gmail.com / pablinza@me.com


No hay comentarios:

Publicar un comentario