Reloj/Calendario/Posicionador Geográfico/Termómetro sincronizado por módulo GPS

Este proyecto integra el uso de PICs (16F628) enlazado con un módulo receptor GNSS(GPS) modelo Ublox GY-GPSV3-NEO-M8N que le provee la info de hora, fecha, posición geográfica que el Reloj mostrará en su display.
Una particularidad de este Reloj es que utiliza un display de tubos de vacío TRC tipo IEE MIMO de unos 70 años de antigüedad.
También incorpora efectos de Back Light RGB para iluminar los tubos y un control de temperatura para ventilar los TRCs utilizando sensores digitales tipo DS18B20, como se puede apreciar en el video.

Entonces como dije, el display utiliza tubos de rayos catódicos (CRT) marca IEE modelo NIMO BA0006-P31 (ó IEE NIMO 6000-31-0006), que en adelante llamaré directamente Tubos.
Estas son joyas electrónicas de los años 50 y 60, con su placa y circuitería original recuperada desde el fondo de alguna tienda de antigüedades.
También es original la fuente de alimentación marca IEE modelo 14549, que ingresa con 110VAC por ser americana, y que provee 1,1 VAC para los filamentos (cátodos) y 3.500 VDC para los ánodos de los Tubos.

Respecto de estos Tubos podemos detallar lo siguiente:
NIMO fue la marca comercial de una familia de Tubos de Rayos Catódicos (CRT) muy pequeños y no estandarizados, fabricados por IEE (Industrial Electronics Engineers de USA) a mediados de 1960.
En este caso el Tubo es el modelo BA0006-P31, que cuenta con 10 cañones de electrones con plantillas que dirigen y dan forma de dígito o caracter alfanumérico al haz de electrones que se proyecta e ilumina su pantalla superior.
Estos Tubos son de diseño interno artesanal y complejo pero de operación simple ya que proyectan un sólo dígito entre 10, normalmente de 0 a 9. Los hay más complejos de proyección múltiple que cuentan con deflexión magnética especial pero este no es el caso.
Este modelo de Tubo posee 3 tipos de electrodos, un filamento catódico, un ánodo y 10 grillas o rejas de control que activan los 10 haces electrónicos con sus cuadrículas correspondientes.
Las ventajas de los Tubos NIMO respecto de sus contemporáneos NIXIE es su mejor ángulo de visualización, incluso el dígito proyectado se ve desde atrás del Tubo, y su color y brillo variable (dimmerizable). Sus desventajas es su mayor complejidad de alimentación y mayor consumo. El Tubo requiere mínimo 1750 Voltios de tensión DC de ánodo, 1.1 voltios de tensión AC para los filamentos, y cierta polarización catódica como se verá luego en el circuito de control.

Los datos del Tubo IEE BA0006-p31 pueden verse aquí:
BA0000-P31.pdf

La placa de Tubos y su fuente de alimentación:

index.php


index.php


En la siguiente figura puede verse como varía el brillo o luminancia del Tubo en función de la tensión de Ánodo, lo que hace variable (dimmerizable) el brillo del tubo. Normalmente el control de brillo de un display numérico construido con estos Tubos se lograba con un reóstato en el circuito primario del transformador de su fuente anódica, hoy con una alimentación switching variable se lograría el mismo efecto.

index.php




En la siguiente figura se muestra el circuito típico de testeo del Tubo NIMO.
Como en todo tubo de rayos catódicos, la corriente de haz se controla con la tensión del electrodo Grilla o reja. Como se ve en la figura, una tensión de Grilla de -6 Voltios respecto del Cátodo producirá la repulsión de los electrones del haz, llevando la corriente del Tubo al corte y apagando el brillo de la pantalla. En cambio una tensión de Grilla de +4 Voltios respecto del Cátodo permitirá el paso pleno de los electrones del haz y el brillo máximo de la pantalla del Tubo.
Cuando la Grilla de control sea negativa, su efecto de repulsión electrónica hará que la corriente de haz de su cañón catódico sea nula. Cuando la Grilla sea positiva tomará unos pocos microamperes de corriente del haz, por lo cual debe usarse una resistencia de limitación de corriente de Grilla de un valor mínimo de 1 MegaOhms.

index.php


Un saludo
 
Última edición:
WOW re WOW , si me deja dormir de noche, me gusta para navidad !!! :unsure: Me preguntaba donde logró conseguir esas partes tan antiguas y funcionando y lo segundo 👇
¿ posicionador geográfico de que ? ¿ arroja la actual posición GPS donde se encuentra el objeto ? :unsure::rolleyes: Gracias
 
WOW re WOW , si me deja dormir de noche, me gusta para navidad !!! :unsure: Me preguntaba donde logró conseguir esas partes tan antiguas y funcionando y lo segundo 👇
¿ posicionador geográfico de que ? ¿ arroja la actual posición GPS donde se encuentra el objeto ? :unsure::rolleyes: Gracias
Jeje amigo en realidad no brilla tanto, el video lo resalta bastante, se puede dormir ;) Los tubos salieron de mis afortunadas búsquedas de joyas vintage.
El receptor GPS integrado que utiliza el diseño y que ya cité, sirve para proveer la indicación de tiempo con la precisión de los relojes atómicos del sistema GPS (este Reloj además de ser raro, jamás se saldrá de hora :cool: ) y también provee los datos de Latitud y Longitud de su posición geográfica.
Como se ve con un pulsador frontal, el display deja de mostrar Mes del año, Dia de la semana, Año, Mes, Dia, Hora, Minuto y Segundo,
y pasa a mostrar valores de Latitud (37.58,2 sur) y Longitud (57.33,5 oeste) que son las coordenadas donde está el Reloj en ese momento, datos que si mete en google earth le dirán donde ;)
Gracias amigo, un saludo
 
Última edición:
Continuando con este desarrollo, les cuento que como interface entre el PIC y los Tubos del Display, utilicé la técnica de registros de desplazamiento y decodificadores BCD que me anduvo bien en otros proyectos.
El decodificador BCD a decimal que utilicé es el antiguo CD4028 y su funcionamiento es simple, tiene 10 salidas y cada una se activará de acuerdo al código BCD de sus entradas. La alimentación será de 12 Voltios, de modo que con una polarización catódica de los Tubos de 6 Voltios, las 10 salidas del deco atacarán las 10 Grillas con +6 Voltios (tensión grilla-cátodo) cuando la salida está activa y encendiendo el dígito del Tubo, y con -6 Voltios (tensión grilla-cátodo) cuando la salida se desactiva y el dígito del Tubo se apaga. Claramente habrá un deco por cada Tubo.
Los códigos BCD de entrada a los decos los proveerán registros de desplazamiento o conversores serie/paralelo de 8 bits tipo CD4094, entonces habrá un CD4094 por cada dos CD4028. Como el Reloj será de seis dígitos (Hora: Minutos: Segundos ó Año: Mes: Dia) usará seis CD4028 y tres CD4094. Los tres registros estarán en cascada y los datos entrarán en serie desde el PIC.

De acuerdo a esto, el circuito para dos Tubos (dígitos) es el siguiente:

index.php

Y el diagrama para seis Tubos (dígitos) será:

index.php

En el video se nota un rápido parpadeo en cada segundo cuando el primer digito está apagado, eso ocurre cuando los registros reciben y almacenan los 24 (3x8) bits que les envía el microcontrolador, aunque luego se agregan más registros para otras funciones.

Continuará...
 
Última edición:
Continuando con este proyecto, adjunto una foto de las primeras pruebas de los ancianos Tubos NIMO aún con su circuitería original, la cual luego cambiará por la detallada arriba. Los dígitos "fantasmas" aparecen por problemas de humedad en la placa que se solucionan con una buena limpieza. Nótese los contactos superiores de bronce que alimentan los ánodos con 3.500 VDC, un gran cartel de ⚡¡¡¡NO TOCAR!!!⚡ sobre estos será muy conveniente ;)

index.php



Ahora algunas consideraciones sobre el Display del Reloj.
Como puede verse la placa posee cinco Tubos NIMO o sea que falta uno para completar los seis dígitos necesarios para mostrar con dos dígitos cada uno, los tres valores de Hora, Minutos y Segundos en el modo Reloj, ó Día, Mes, Año en el modo Calendario. Y además como dije arriba, también mostrará Longitud y Latitud en el modo de Posicionador Geográfico.
Como estos Tubos son reliquias escasas y caras, la solución del sexto dígito será utilizar un Tubo especial (no NIMO) llamado de "medio dígito" que solamente mostrará un "1" o estará apagado. Como puede verse en el video este Tubo no es igual a los otros cinco.

Entonces de acuerdo a este criterio, el Display de seis dígitos mostrará lo siguiente (la X corresponde a dígito apagado):

- En el modo Reloj, la hora en el formato de 12 horas AM/PM, desde X1:00:00 hasta 12:59:59
- En el modo Calendario, la fecha en el formato Mes: Año: Día, desde X1:23:01 hasta 12:23:31 (desde el 1ro de enero hasta el 31 de diciembre de este año, por ejemplo)
- En el modo Posicionador Geográfico,
- Longitud en el formato Grados (tres dígitos) y Minutos (dos dígitos mas un dígito decimal) desde + 180:00.0 hasta - 180:00.0
- Latitud en el formato Grados (tres dígitos) y Minutos (dos dígitos mas un dígito decimal) desde + X90:00.0 hasta - X90:00.0

Como sólo hay seis dígitos para mostrar todo, el cambio entre vista de Hora / Fecha será automático en el modo siguiente.
El Reloj en cada cuenta de diez segundos mostrará durante ocho segundos la Hora y durante dos segundos la Fecha.
Según esto, se verá en los segundos de 0 a 5 la Hora, durante los segundos 6 y 7 la Fecha, y en los segundos 8 y 9 de nuevo la Hora, y serán acompañados por los indicadores de abajo del display.

Y el cambio para pasar a mostrar Longitud/Latitud será con un pulsador que mientras esté oprimido (como puede verse en el video), las vistas de Longitud/Latitud se alternarán cada cinco segundos.

Por ejemplo en este momento el Reloj muestra:
- Hora, 10:31:18 ; Fecha, 07:23:12 ; Longitud, - 57:33.0; Latitud, - 37:58.6

Continua...
 
Última edición:
Continuando por aquí, aunque faltan algunos detalles sobre el Display, ya hay una idea general de como se verá.

Pasaré ahora al estudio del módulo GNSS (GPS) que le suministrará la info al microcontrolador, que procesará y mostrará en el Display.

El módulo como ya adelanté, será un receptor y procesador de señal GNSS (Global Navigation Satellite System) marca Ublox modelo GY-GPSV3-NEO-M8N de octava generación (8G), que fue liberado para uso civil en 2020 (hasta 2020 la Ublox 8G era de uso militar (drones), hoy es de uso militar la Ublox 9G)

Aquí el módulo en su placa de evaluación con su antena integrada:

index.php



Sus características principales son las siguientes:

UbloxCompact 8th generation GPS/GNSS receive/processor GPS module‎ GY-GPSV3-NEO-M8N breakout board general features:

- 72-channel u-blox M8 engine GPS/QZSS L1 C/A, GLONASS L10F, BeiDou B1 SBAS L1 C/A: WAAS, EGNOS, MSAS Galileo-ready E1B/C (NEO-M8N)
- SuperSense Indoor GPS, -167dBm
- On-board Ultra low noise 3.3V voltage regulator and RF filter for noise blocking
- I2C (SDA,SCL) and Uart (Tx,Rx)
- Triple band GPS, Glonass and BeiDou antenna
- Triple band Band Pass filter
- Triple Band LNA
- U-center GPS Evaluation Software
- Extensive visualization and evaluation features
- Supports AssistNow Online and AssistNow Offline A-GPS services
- 1 TTL UART port, 1 I2C port
- Time pulse LED
- Battery for HOT module start and settings storage
- Build-in HMC5983 Compass
- Dimensions: 33*33mm hole distance 22x22mm
- Fully assembled and ready to use

Las hojas de datos del módulo NEO-M8N pueden verse aquí:
NEO-M8N Hoja de datos
NEO-M8-FW3_DataSheet_(UBX-15031086).pdf

Y sus características mas detalladas de funciones y protocolos pueden verse aquí:
NEO-M8N características, funciones y protocolos
u-blox8-M8_ReceiverDescrProtSpec_(UBX-13003221)_Public.pdf

Este módulo receptor/procesador NEO-M8N cumple con las especificaciones y normas actuales de los sistemas GNSS globales que están en operación, que actualmente son cuatro, el GPS(USA), el GLONASS(URSS), el BeiDou(China) y el Galileo(UE, aún en desarrollo),
y realmente de su gran potencia y versatilidad se usará muy poco en esta aplicación.

Aquí el microcontrolador se comunicará con el módulo por medio de su interface serial USART, utilizando el protocolo universal NMEA por medio del cual recibirá los parámetros de tiempo necesarios para actualizar su indicación de Hora, Minutos y Segundos, de Dia, Mes y Año, y de Posición geográfica.
El protocolo NMEA es un estandar de comunicaciones jerárquico bidireccional (master-slave) para equipos electrónicos marítimos introducido en USA en el año 1983 y actualizado en los 2000s. Su manual de referencia puede verse aquí:
NMEA Reference Manual-Rev2.1-Dec07.pdf

El módulo NEO-M8N dispone entre otros de ese protocolo, que utiliza comunicación serial asincrónica (normas RS422/RS232) entre un dispositivo "hablador" (master ó talker) y uno o varios "escuchas" (slave ó listener).
Los parámetros de comunicación serial normalizados son los siguientes:

Baud rate: 9600
Number of data bits: 8 (bit 7 is 0)
Stop bits: 1 (or more)
Parity: none
Handshake: none

El formato general de los mensajes del protocolo NMEA utiliza exclusivamente caracteres imprimibles en formato ASCII de 8 bits, comenzando el mensaje con el signo $ (pesos) y terminando con CR (carriage return) y LF (line feed)
El formato general del mensaje que recibirá el microcontrolador será el siguiente:

$TTSSS,D1,D2,...<CR>,<LF>

Donde TT es el identificador del dispositivo Master que envía el mensaje (dos letras), SSS es identificador de mensaje (tres letras) , y D1, D2, etc. son los datos que eventualmente acompañaran la respuesta.

Para testear el módulo NEO-M8N, conocer sus características principales y elegir el mensaje adecuado para obtener los datos de Hora, Fecha y Posición en tiempo real, utilizaré la aplicación provista por el fabricante, la U-Center v20.01 GNSS Evaluation Software for Windows cuya guía de usuario puede verse aquí:

U-Center v20.01 User Guide
u-center_Userguide_(UBX-13005250).pdf

Continua...
 
Test y pruebas del módulo GNSS NEO-M8N

Entonces continuando, para testear el módulo NEO-M8N, conocer sus características principales y elegir el mensaje a utilizar para obtener los datos, utilizaré la aplicación provista por el fabricante, la U-Center v20.01 GNSS Evaluation Software for Windows
cuya vista principal se ve así:

p1.jpg

Como se vé, la aplicación brinda toda la información en tiempo real que provee el módulo NEO-M8N. Le daremos un rápido vistazo a sus ventanas.
En la línea de abajo se lee que el módulo está conectado al Computador por la interface serial COM6 a 9600 baudios y que utiliza el protocolo NMEA.
De izquierda a derecha en la pantalla de la aplicación aparecen distintas ventanas con información variada.
La primera ventana muestra los satélites GNSS recibidos, su rótulo y nivel de señal, los 6 de letra G son GPS (USA) y los 4 de letra R son GLONASS (Rusia), del sistema BeiDou(China) y del Galileo(UE) no hay ninguno visible sino serían también mostrados por la aplicación.
Los satelites en Verde están OK recibidos normalmente, los Azules están en proceso de adquisición, y en los Rojos se ha perdido la señal.
Luego está la ventana de Satellite Position que muestra la constelación visible y su posición relativa respecto del receptor, luego la ventana de Signal History que indica el historial de señal, sus rótulos y las banderas de nacionalidad de los distintos satélites visibles.

Luego aparecen las ventanas de Data View, Altitude, Compass y Watch (Reloj) que se muestran con mas detalle aquí:

p22.jpg

Por último aparece la ventana de Consola que muestra los mensajes en formato NMEA que se reciben del módulo y que proveen toda la información para actualizar todas las ventanas.
Luego de este vistazo a las pantallas de la aplicación U-center de test y control, veremos cual mensaje de la gran variedad que envía el módulo será el requerido para que el microcontrolador rescate la info de Hora, Fecha y Posición necesaria para mostrar en el Reloj de este diseño.
Esta información podría estar distribuida en distintos mensajes de data del módulo, pero por suerte hay un mensaje en este protocolo que reúne todos estos datos,

Entonces el mensaje seleccionado será el $GNRMC, cuyo formato será:

GNRMC.jpg

El mensaje a procesar entonces será el que tenga el encabezado $GNRMC, (24-47-4E-52-4D-43-2C en Hexa) cuyos datos se marcan en la siguiente captura de consola y será la info que el microcontrolador deberá extraer.

p4.jpg


Entonces este será el mensaje $GNRMC del protocolo NMEA, donde el identificador de dispositivo es GN (GNSS módule) y el tipo de mensaje es RMC (Recommended Minimum Specific GNSS Data)
Como se ve, la indicación de tiempo es suministrada con una resolución de milesimas de segundo y la presición será la correspondiente a los relojes atómicos del sistema GPS. Lógicamente esta gran precisión excede los requerimientos de este diseño.

Entonces la interface serial asincrónica (USART) del módulo se comunicará con la interface serial del microcontrolador a 9600 baudios (parámetros ya vistos arriba) pasándole todos los mensajes que se ven en la pantalla de Consola.
La USART del microcontrolador actuará por interrupciones y su rutina (rutina de servicio de interrupción o ISR) identificará el mensaje requerido y recogerá los datos que serán almacenados en registros de memoria.
Luego el PPal (programa principal) procesará estos datos y los mostrará en el Display del Reloj.

El siguiente diagrama muestra la interacción entre la ISR y el PPal

isrppal.jpg
Como se ve, La USART recibe los mensajes NMEA del módulo y dispara la ISR con cada carácter (dato de 8 bits) recibido, identifica el encabezado del mensaje $GNRMC y almacena los datos en registros de memoria. el PPal lee esos registros, procesa los datos como veremos luego y los muestra en el Display. Todos los demás mensajes que no sean el requerido son descartados.

El Display como ya vimos es de seis dígitos y mostrará alternativamente Hora, Minutos y Segundos, y Mes, Año, Dia.
En la figura, HD y HU corresponden a Hora Decenas y Hora Unidades, MD y MU a Minuto Decenas y Minuto Unidades, y SD y SU a Segundos Decenas y Segundos Unidades. Lo mismo ocurre con la Fecha y DD,DU, ED,EU y AD,AU (la E la uso para Mes pues la M ya esta usada). La info de Posición geográfica no esta en el diagrama pero se obtiene en forma similar.

El código de la ISR de la USART sigue el modelo de "maquina de estados", o sea tiene una variable de estado que le indica en que punto del mensaje está el proceso y que debe hacer con el dato recibido.

Un diagrama simplificado de esta ISR (RSI) es el siguiente:

rsi.jpg

El proceso ISR ingresa por el punto Verde y en la primera columna sigue el encabezamiento de mensaje $GNRMC y avanza la variable de Estado (É) comparando el dato recibido (Á) con los caracteres del encabezamiento. Cualquier comparación que no se cumpla en el seguimiento del encabezado de mensaje $GNRMC abortará la secuencia volviendo al Estado de Reposo (É=0)
Si se alcanza el estado É=7 significa que el mensaje fue identificado con éxito y comienza en la segunda columna la adquisición de los datos de Hora en los registros de memoria.
Al final de esta columna se habilita un "contador de comas" para que la ISR saltee los demás parámetros que trae el mensaje y que no interesan en esta aplicación, las comas son los separadores de parámetros y son constantes.
Por último en la tercera columna se recogen los datos de Fecha y finaliza la secuencia exitosa de la ISR, volviendo al Estado de reposo y comenzando de nuevo con la detección del encabezamiento.
La rutina tiene la posibilidad de hacer "eco" del dato recibido en la TX del microcontrolador con el fin de chequear su validez con una PC,
Luego con el código del programa se aclaran más detalles.

Continuará...
 
Última edición:
Continuando con este desarrollo, ahora vemos el diagrama simplificado del hardware

nimo_cc1.jpg


En este caso utilizo un microcontrolador (uC) de MicroChip familia 16FXXX (628/648) que provee dos puertas I/O de 8 bits (RA y RB) ,
y la asignación de sus pines se ve en el diagrama.
La interface entre USARTs del módulo NEO-M8N y el uC es un conocido CD40106 (Hex Inverter Schmitt Trigger) que adapta los 3,3 Voltios de salida Txd del módulo a los 5 Voltios de RXD (RB1) del uC por medio de R1 y R2.
El módulo NEO se alimenta con 5V y tiene un regulador integrado de 3,3V y las señales Rxd y Txd son de 3,3V.
La salida TXD (RB2) del uC pasa también por inversores proveyendo la salida para monitoreo por HiperTerminal.
Al final hay dos Leds que indican la actividad de datos de RXD(Verde) y TXD(Amarillo).
En el video inicial, estos Leds pueden verse en el costado izquierdo del Reloj, notándose que el Verde tiene un largo parpadeo en cada segundo pues se activa con todos los mensajes que bajan del módulo y que se muestran en Consola, en cambio el Amarillo tiene un parpadeo corto pues sólo se activa con los datos que "echoan" hacia la PC si se desea chequear la validez de los datos recibidos.

Los transistores T1 y T2 actúan como interface con los registros de desplazamiento del Display (ya visto antes), pasando las señales de 5V (alimentación del uC) RB6 (CK) y RB7 (DT) a señales de 12V (alimentación de los registros), siendo DT los datos seriales de los registros y CK el clock de los registros.
Luego está el Xtal requerido por el UC de 8 MHz en RA6/RA7
El pulsador BT ingresa en RB3, y actuará para cambiar la visualización de Hora/Fecha a Longitud/Latitud

Todos los resistores del pulsador BT y de los Leds van a la fuente de +5 Voltios

Las demás líneas (pines) se usan para manejar Leds Separadores (RGB tres colores) e Indicadores (Amarillos abajo de los números) en el Display.
Los Leds se muestran en el color correspondiente o sin color (apagados), según la siguiente figura:

display_cc1.jpg

Las funciones de las líneas (pines) se detallan a continuación:

- SVHM (Separador Verde H,M,S (RB5)) maneja 4 Leds Separadores Verdes Hora: Minuto: Segundo.
Estos Leds parpadean 1/4 Seg en cada Segundo.
- SRAM (Separador Rojo M,D,A (RB4)) maneja 4 Leds Separadores Rojos Mes: Año: Dia
Estos Leds parpadean 1/4 Seg. en cada Segundo.

Recuérdese que en el modo normal Hora/Fecha, el Display durante los segundos 0,1,2,3,4 y 9 mostrará la Hora y durante los segundos 5,6 y 7 mostrará la Fecha, con el correspondiente cambio de color en los Leds Separadores.

- SVLO (Separador Verde Longitud (RA3)) maneja 2 Leds Separadores Verdes y un Led de Punto Decimal de Longitud;
Grados:Minutos.Decimas de Min.
- SRLA (Separador Rojo Latitud (RA2)) maneja 2 Leds Separadores Rojos y un Led de Punto Decimal de Latitud;
Grados:Minutos.Decimas de Min.

Recuérdese que con el pulsador BT se cambiará la visualización del modo normal Hora/Fecha al modo Posición Geográfica Longitud/Latitud.
La indicación de Longitud/Latitud se alternará cada 5 Seg. mientras el BT está oprimido, con el correspondiente cambio de color en los Leds Separadores y Punto Decimal.

- IHMS (Indicador H,M,S (RA1)) maneja 3 Leds Indicadores Amarillos de HOR: MIN: SEG que se encienden debajo del Display
- IDMA (Indicador M,A,D (RA0)) maneja 3 Leds Indicadores Amarillos de MES: AÑO: DIA que se encienden debajo del Display

Los otros 4 Leds Indicadores Amarillos de LONGITUD, GRADOS, MINUTOS y LATITUD ; y demás Leds que indicarán Dia de la semana, nombre del Mes, etc. encienden por otros medios que veremos luego.

Por último, como los Leds son RGB está disponible el color Azul que será usado como indicador de errores.
Entonces la línea IAER (RA4) encenderá los 7 Leds AZULes del Display, indicando algún error (errores de encuadre, overrun usart, checksun, etc)

Continua...
 
Última edición:
Aquí una vista del prototipo todavía con el hardware original.
Luego las fuentes de alta tensión y tensión de filamento original para los tubos de los años 50 que se ven allí y el transformador necesario de 220/110 VCA se cambiarán por fuentes switching de menor tamaño y consumo

bastidor1.jpg

Continua...
 
Continuando con el proyecto y como ya dije antes, el Display será de 6 dígitos de los cuales 5 dígitos serán Tubos Nimo normales con números de 0 a 9, y el sexto tubo será de "medio dígito" ya que sólo mostrará el número 1 o estará apagado.
También como se vio, el Display será manejado por 3 registros de desplazamiento CD4094 y 5 decodificadores CD4028 para cada uno de los dígitos completos, y se dedicará sólo un bit para el manejo del sexto medio dígito ya que sólo tendrá dos estados.
Por lo tanto los 3 bits sobrantes en el (medio) registro CD4094 del sexto dígito, serán usados para el efecto de Back Light o luz de fondo que se puede ver iluminando los Tubos en el video del primer posteo. Los Leds a usar serán tipo RGB de ánodo común.

De acuerdo a esto, el diagrama del Display será así:

nimo_f.jpg
y el circuito de mando de los Leds RGB de Back Light será así:

rgb_nimo.jpg
Entonces como veremos luego en el código de programa del uC, de los 24 (3x8) bits que envía este en forma serial sincrónica cada segundo a los registros para actualizar el Display, los últimos tres bits llevarán el código de color RGB del Back Light , el cual se puede mantener fijo un tiempo (aproximadamente un minuto en el video). Y la tabla de colores correspondientes será la siguiente:


Q1(Rojo)Q2(Verde)Q3(Azul)Color
000Apagado
001Azul
010Verde
011Cian
100Rojo
101Magenta
110Amarillo
111Blanco

colores.png

Continua...
 
Volviendo ahora al tema de la hora y fecha a mostrar en el Display se deben hacer algunas consideraciones

Digamos que al utilizar un módulo GNSS (GPS) como el NEO-M8N para obtener la información de Hora y Fecha desde los sistemas satelitales de posicionamiento global, aparece el problema de la corrección a la Hora y Fecha Locales que deberá ser mostrada en el Reloj.
Los sistemas de satélites GNSS que recibe el módulo (GPS, GLONASS, Beidou, Galileo) son globales y transmiten sus señales a todo el mundo, por lo cual envían con alta precisión exclusivamente el tiempo UTC (Coordinated Universal Time) ó GMT (Greenwich Mean Time) y no incluyen en su programación ninguna corrección por posición geográfica.
Por lo tanto el país o región que reciba y procese dicha señal, deberá realizar las correcciones necesarias a su Hora y Fecha Local, que dependerá de su posición geográfica y factores estacionales (países que adelantan su hora en invierno, etc.)

En este tema de corrección de tiempo deben tenerse en cuenta algunos detalles.
Por ejemplo los países americanos que se encuentran al Oeste de Greenwich o Meridiano Cero tienen correcciones de tiempo negativas, p.e. para Argentina la corrección o Offset horario es (-3), esto significa que cuando la Hora UTC es p.e. 09:17 en Argentina es Hora Local 06:17. La solución de este corrimiento o Offset horario sería sencillo, sólo basta restar 3 a la Hora UTC y queda la Hora Local corregida.

Otro ejemplo sería que la Hora UTC es p.e. 02:36 entonces la Hora Local será 23:36 y la resta debe hacerse en el sistema binario en el uC para obtener la Hora a mostrar, y además la Fecha UTC ya estará un día adelantada a la Fecha Local y también deberá corregirse mostrando el día anterior (el día local).

Esta corrección al día anterior que debe mantenerse en las tres últimas horas del día corriente en un país con Offset ( -3) como Argentina se complica un poco más el primer día del mes, ya que el día anterior al 1ro de mes depende de cual fue el mes anterior que puede contar con 28, 30 o 31 días, y se deberá mostrar además el mes anterior en ese caso. También además en un Reloj que muestra Mes y Año como en este caso, deberá corregirse el Mes mostrado y el año mostrado en las tres últimas horas del 31/12, ya que el tiempo UTC ya estará en año y mes nuevo, mientras que el país todavía en año y mes viejo.
Otra tema adicional son los años bisiestos que en principio no los tendremos en cuenta

Entonces resumiendo, deberán efectuarse cuatro correcciones a los datos recibidos del módulo NE8-M8N para luego mostrar el Tiempo correcto en el Display, que son los siguientes:

1) Restar el Offset (-3) a la Hora UTC recibida para obtener la Hora local a mostrar
2) Si con la corrección de Hora se pasa al día anterior, mostrar al Dia anterior
3) Si con la corrección de Dia se pasa al mes anterior, corregir al Mes y al Dia anterior
4) La hora corregida en el punto 1 está en el formato 24 hs, pasar al formato 12 hs AM/PM

Todo este proceso en el uC que incluye código de programación y tablas en EPROM se verá más adelante,

Continua...
 
Última edición:
Continuando con este proyecto y como puede verse en el video del primer post, el display calendario que estará debajo de los Tubos indicará Nombre del Dia de la Semana y Nombre del Mes iluminando la indicación con Leds Amarillos
Entonces en total, este display contará con 6+4+7+12 = 29 Leds en 4 líneas, a saber:

Primera línea (6 Leds): HOR MES MIN AÑO SEG DIA (estos son manejados directamente por el uC)
Segunda línea (4 Leds): LON. GRADOS MINUTOS LAT (estos son manejados por registros de desplazamiento)
Tercera línea (7 Leds): LUN MAR MIE JUE VIE SAB DOM (estos son manejados por registros de desplazamiento)
Cuarta linea (12 Leds): ENE FEB MAR ABR MAY JUN JUL AGO SEP OCT NOV DIC (estos son manejados por registros de desp.)

La electrónica para manejar estos indicadores será otra vez con registros de desplazamiento tipo CD4094 como se ve a continuación, los tres grupos de Leds de cada línea:

nimo_cal.jpg


Estos tres registros adicionales seguirán en cascada a los tres registros anteriores que manejan el Display de Tubos (totalizando seis registros), y se deberán mandar los bits seriales con los códigos de Leds a encender antes que los códigos de los dígitos del Display.

El criterio para mandar el código correcto del Nombre de Mes a encender será sencillo. Con el número de Mes mostrado en el Display se entra a una tabla y se obtiene el código del Led correspondiente a enviar y encender.
El criterio de Nombre del Día de la semana es más complicado. De acuerdo a que día arranca el Mes, se cuenta en módulo 7 hasta el día presente, y con ese contador en módulo 7 se obtiene desde tabla, el código del Led correspondiente a enviar y encender.
Luego con el código de programación del uC se aclararán estos criterios.

Continua...
 
Última edición:
Continuando y como se puede ver en el video del comienzo , este proyecto incluye un termómetro digital de dos canales cuyos displays de 7 segmentos se ven a la derecha del display del Reloj.
Este termómetro que mide y controla la temperatura interna y externa del gabinete del Reloj, encendiendo el ventilador trasero en caso de exceso de temperatura, utiliza un microcontrolador uC exclusivo y dos sensores de precisión tipo DS18B20.
Alrededor del segundo 0,33 del video puede verse el sensor de temperatura DS18B20 interno pegado sobre el transformador de alta tensión de los Tubos, uno de los puntos mas calientes del gabinete.
Para no complicar este tema, el diseño completo de este termómetro lo colgaré en un hilo aparte.

Estando ya prácticamente finalizado el diseño del hardware del Reloj y explicado su funcionamiento, comenzaré en lo siguiente con el desarrollo del código de programación, el cual está escrito exclusivamente en lenguaje Ensamblado o Assembler del uC correspondiente.

Ya finalizando este proyecto, colocaré algunas partes del código de programación de UC , no mucho para no aburrir y si es de interés ampliaré luego alguna sección.

Continúa...
 
Ya finalizando este proyecto, colocaré algunas partes del código de programación de UC , no mucho para no aburrir y si es de interés ampliaré luego alguna sección.

1) ISR (Interrupt Service Routine)

El código de la ISR de la USART de uC en este proyecto sigue el modelo de "maquina de estados", y utiliza una variable de estado que le indica en que punto del mensaje ya visto está el proceso y que debe hacer con el dato recibido.

El diagrama de flujo simplificado de esta ISR (RSI) es el siguiente:

rsi.jpg

Inicialización de la USART para recibir los mensajes del módulo GPS a 9600 baudios

Código:
; INICIALIZAR RX TX USART

        bcf STATUS,RP1      ;apuntar      
    bsf STATUS,RP0     ;banco1
                                 ; Ajustar divisor para 9600 baudios para Xtal de 8MHZ
    movlw 0x33          ; cargar el divisor baurate con 51 (33h), da 9615 = 8.000.000/(16*(51+1) ,  manual pag. 71
    movwf SPBRG        ;para clock 8MHz da 9615  o sea +0,16 de error;
    ;          
    bsf TXSTA,BRGH         ;set modo High Speed
    bcf TXSTA,SYNC         ;set modo asincrónico
        ;
    bcf STATUS,RP0        ;apuntar banco 0
    bsf RCSTA,SPEN         ;conectar RB1 y RB2 como RX y TX, TRISB 1 y 2 deben ser 1 (buffer de salida desconectado)
    bsf STATUS,RP0         ;apuntar banco  1

    bsf TXSTA,TXEN        ;Habilitar transmison , queda esperando el dato a transmitir
    bsf PIE1,RCIE                  ;Habilitar interrupcion de recepcion

    bcf STATUS,RP0        ;Apuntar banco 0
    bsf RCSTA,CREN         ;Habilitar recepcion de datos seriales en RB1 (RXD)
                                                ;Habilitar interrupciones
    bsf INTCON,PEIE        ; periheral interrup enable (incluye usart)
    bsf INTCON,GIE        ; all interrup enable

ISR, Rutina de Servicio de Interrupción

Código:
ORG     0x0004                 ; interrupt vector location
        movwf      WTEMP            ; salvar el W
        movfw    STATUS,W        ; salvar el
        movwf    STEMP              ; STATUS

        bcf STATUS,RP1        ;  apuntar
        bcf STATUS,RP0        ;  banco 0
        call     usa_rt                      ; llamando a procesar el dato que llegó
                                                        ;
        movf   STEMP,W        ; recuperar W y STATUS
        movwf    STATUS            ;
        movf WTEMP,W
        retfie                               ; return from interrupt

Rutina de proceso del carácter (dato) recibido en usa_rt

Código:
usa_rt
    ;
        bsf PORTB,AZA4 ;apagar el Led indicador de errores
    ;
    btfss PIR1,RCIF ; llego un caracter, ver como esta el flag de recepcion, debe estar encendido sino es ilogico
    goto err_flag  ;hay algun error ilogico!!!

ckc_ferr                           ; llego un dato,  primero procesar errores
    btfsc RCSTA,FERR    ;ver si hay error FRAME (o sea que NO se detecto el bit de STOP )
    goto err_ferr           ; si hay error FRAME

ckc_over    
        btfsc RCSTA,OERR   ;ver si hay error OVERRUN, si llego un dato y el anterior no se leyó!
        goto err_over         ; si hay error Over

sin_error                        ;ninguno de los dos errores fue detectado
    movf RCREG,w       ; se resetea el flag de interrupcion RCIF, el FERR  y el dato recibido pasa al W
    movwf RCDATO     ;se guarda el dato recibido
    goto case_00       ; ir a procesar el Dato recibido!
    ;
        ;procesar errores, enciende LED indicador y  resetea Flags de errores,  el dato se procesa igual  
err_flag
err_ferr  
    ; encender el Led indicador de error, el proximo caracter correcto lo apaga
        bcf PORTA,AZA4   ;encender el indicador de error
    goto sin_error     ; si el Led enciende permanente hay un problema

err_over
    bcf RCSTA,CREN     ;resetear error Overrun
    nop
    bsf RCSTA,CREN     ;habilitar RX
    goto err_flag           ; encender el Led indicador de errores y continuar
;                                                                
;-------------------------------------------------------------------------------------
case_00
;

Detección del encabezamiento del mensaje $GNRMC

Código:
case_00  ;procesar estado 0 (reposo) de la máquina de estados
    ;
    movfw ESTADO ; Comparar
    xorlw 0x00       ; con estado 0
    btfss STATUS,Z ;si son iguales saltar
    goto case_01   ; no es 0, continuar
    ;el estado es 0, procesarlo
    movfw RCDATO    ;el ESTADO es 0 (reposo), verifcar si llego $
    xorlw 0x24      ; comparar con $, el primer caracter del encabezamiento $GNRMC
    btfsc STATUS,Z ; ver si llego $, si no llego saltear cambio de ESTADO
    goto si_PP       ;exito!, estado 0 y llego un $ ,
    clrf ESTADO     ;no exito, esta en 0 pero no es $ lo que llegó
    return           ;resetear ESTADO y volver (aca no haria falta resetear)
si_PP ;en ESTADO 0 llego un $, pasar al estado 1 y no echoar dato  
    movlw 0X01   ; cargar el estado 01
    movwf ESTADO  ;pasar al estado 01 de la maquina de estados
    return
    ;
case_01  ;procesar estado 1 y caracter "G"
;
    movfw ESTADO  ; Comparar
    xorlw 0x01        ; con estado 1
    btfss STATUS,Z  ;si son iguales saltar
    goto case_02    ; no es 1, continuar
    movfw RCDATO    ;el ESTADO es 1, verifcar si llego el caracter G
    xorlw 0x47        ; comparar con "G" (código ASCII en exadecimal)
    btfsc STATUS,Z  ; ver si llego G, si no llego saltear cambio de ESTADO
    goto si_GG        ;exito, estado en 1 y llego un G
    clrf ESTADO       ;no exito, esta en 1 pero no es G
    return            ;resetear ESTADO y volver, la secuencia exitosa se abortó
si_GG ;en ESTADO 1 llego un G, pasar al estado 2 y no echoar dato  
    movlw 0x02
    movwf ESTADO ;pasar al estado 02
    ;call echo_ar  ;NO hacer eco del dato G a la PC
    return
    ;
case_02  ;procesar estado 2 y "N"
    movfw ESTADO ; Comparar
    xorlw 0x02       ; con estado 2
    btfss STATUS,Z ;si son iguales saltar
    goto case_03   ; no es 2, continuar
    movfw RCDATO    ;el ESTADO es 2, verifcar si llego "N"
    xorlw 0x4E        ; comparar con N en ASCII exadecimal
    btfsc STATUS,Z   ;ver si llego N, si no llego saltear cambio de ESTADO
    goto si_NN  ;exito, esta en estado 1 y llego un G
    clrf ESTADO ;no exito, esta en 1 pero no es G
    return        ;resetear ESTADO y volver
si_NN  ;en ESTADO 2 y llego una N, pasar al estado 3 y no echoar dato  
    movlw 0x03
    movwf ESTADO ;pasar al estado 03
    ;call echo_ar  ;hacer eco del dato N a la PC
    return
    ;
case_03  ;procesar estado 3 y R
    movfw ESTADO ; Comparar
    xorlw 0x03   ; con estado 3
    btfss STATUS,Z ;si son iguales saltar
    goto case_04 ; no es 3, continuar
    movfw RCDATO    ;el ESTADO es 3, verifcar si llego "R"
    xorlw 0x52       ; comparar con R
    btfsc STATUS,Z  ;ver si llego M, si no llego saltear cambio de ESTADO
    goto si_RR     ;exito, estado en 3 y llego un R
    clrf ESTADO    ;no exito, esta en 3 pero no es R
    return        ;resetear ESTADO y volver
si_RR ;en ESTADO 3 llego un R, pasar al estado 4 y no echoar dato  
    movlw 0x04
    movwf ESTADO ;pasar al estado 04
    ;call echo_ar  ;hacer eco del dato G a la PC
    return
    ;
case_04  ;procesar estado 4 y M
    movfw ESTADO ; Comparar
    xorlw 0x04       ; con estado 4
    btfss STATUS,Z ;si son iguales saltar
    goto case_05 ; no es 0, continuar
    movfw RCDATO    ;el ESTADO es 4, verifcar si llego "M"
    xorlw 0x4D      ; comparar con "M"
    btfsc STATUS,Z ;ver si llego M, si no llego saltear cambio de ESTADO
    goto si_MM     ;exito, estado en 4 y llego un M
    clrf ESTADO   ;no exito, estado en 4 pero no es M
    return        ;resetear ESTADO y volver
si_MM  ;en ESTADO 4 llego un M, pasar al estado 5 y no echoar dato  
    movlw 0x05
    movwf ESTADO ;pasar al estado 05
    ;call echo_ar    ;hacer eco del dato M a la PC
    return
    ;
case_05  ;procesar estado 5 y "C"
    movfw ESTADO  ; Comparar
    xorlw 0x05        ; con estado 5
    btfss STATUS,Z  ;si son iguales saltar
    goto case_06   ; no es estado 5, continuar
    movfw RCDATO    ;el ESTADO es 5, verifcar si llego "C"
    xorlw 0x43          ; comparar con C
    btfsc STATUS,Z ;ver si llego C, si no llego saltear cambio de ESTADO
    goto si_CC       ;exito, estado en 5 y llego un C
    clrf ESTADO      ;no exito, estado en 5 pero no es C
    return            ;resetear ESTADO y volver
si_CC ;en ESTADO 5 llego un C, pasar al estado 6 y no echoar dato  
    movlw 0x06
    movwf ESTADO ;pasar al estado 06
    ;call echo_ar  ;hacer eco del dato C a la PC
    return
    ;
case_06  ;procesar estado 6 y , procesar la coma "," que sigue al encabezamiento
    movfw ESTADO ; Comparar
    xorlw 0x06        ; con estado 6
    btfss STATUS,Z ;si son iguales saltar
    goto case_10   ; no es 6, continuar
    movfw RCDATO    ;el ESTADO es 6, verifcar si llego ","
    xorlw 0x2C          ; comparar con , o 2E es . punto
    btfsc STATUS,Z    ;ver si llego "," , si no llego saltear cambio de ESTADO
    goto si_CO       ;exito, estado en 6 y llego un ,  pongo CO la , molesta
    clrf ESTADO      ;no exito, esta en 6 pero no es ,
    return        ;resetear ESTADO y volver
si_CO ;en ESTADO 6 llego una ,, pasar al estado 10 y no echoar dato  
    movlw 0x10  ;
    movwf ESTADO ;pasar al estado 10
    ;call echo_ar  ;hacer eco del dato M a la PC
    return
;
;La detección del encabezamiento fue exitosa, comienza recolección de datos de Hora
;
case_10  ;Recibiendo HORHIG (las decenas de Hora, viene en ASCII, o una segunda coma si no hay datos)

Respecto del tiempo de ejecución, digamos que la ISR será llamada a ejecutarse cada vez que la USART tenga un caracter/dato listo para procesar. Como la velocidad de datos es 9600 baudios, la duración de bit será de 1/9600 = 104 uS y la duración de carácter será de 1 mS aprox.
(tomando 1 bit START, 8 bit DATO, 1 bit STOP , total 10 bits)
Entonces la ISR será llamada a ejecutarse como máximo una vez en cada milisegundo, por lo cual el proceso de la ISR no puede tardar mas que un miliSeg para que no se pierdan datos y no ocurran errores de encuadre, por lo cual se requiere un cristal de 8 MHz en el PIC.

Otra consideración es que la ISR procesa el mensaje $GNRMC hasta que obtiene los datos de Fecha que están al final del mensaje, todo lo que sigue incluido el checksum, lo descarta ya que no se justifica para esta aplicación

Continua...
 
Para ya finalizar este proyecto, colocaré algunas partes más del código de programación de UC , y en otro hilo desarrollaré el tema pendiente del termómetro digital de dos canales que muestra y controla la temperatura del gabinete.

Un poco más de código de la ISR, aquí la parte de recibir los seis dígitos de la Hora

Código:
case_10 ;Recibiendo HORHIG , el dígito Decenas de Horas, viene en ASCII
              ;o la segunda coma si todavía no hay datos (módulo inicializandose)
              ; , o el botón para mostrar Posición Geográfica
    movfw ESTADO ; Comparar
    xorlw 0x10       ; con estado 10
    btfss STATUS,Z ;si son iguales saltar
    goto case_11   ; no es estado 10, continuar
    movfw RCDATO    ;el ESTADO es 10, llega HORHIG en ASCII, le sobran 30 para obtener el número a mostrar
    xorlw 0x2C   ; comparar con la segunda coma para detectar el mensaje de NO DATA   $GNRMC,,V,,,,,,,,,,N*4D
    btfsc STATUS,Z ; si no es coma, continuar, pues no es el mensaje de NO DATA (el módulo aún no no adquiere info de los GNSS)
    goto es_coma ;se detecta la segunda coma, todavia no llegan los datos válidos
    movfw RCDATO   ;si no es coma, recuperar dato recibido y procesarlo
    andlw 0x0F     ; mascara para borrar ASCII, sacarle el 30; el 30 queda en 00, 31 en 01 etc.
    movwf HORHIX   ; cargar el digito de hora en registro auxiliar HORHIX (es hora  UTC, no local)
    ;chequear boton de solicitud de mostrar Posición geográfica
        btfss PORTB,BTB3 ;si el boton no fue apretado,esta en 1, seguir, saltar
    goto bot_on  ;si hay boton oprimido, ir a procesar latitud/longitud ; si no continuar normal con hora y fecha
    movlw 0x11
    movwf ESTADO ;pasar al estado 11
    call echo_ar  ;hacer eco del dígito de Hora HORHIG a la PC para chequear su validez
    return
    ;
bot_on  ;el boton esta oprimido, ir a recoger latitud y longitud y mostrala. Ya se recibio HORHIG pero ese valor se  descarta
    movlw 0x02 ;cargar el contador de comas a saltear dentro del mensaje, son 2
    movwf ESTAUX ; en ESTAUX
        movlw 0x40   ; el proximo estado de la maquina de estados sera el 40, arranca la secuencia de recoger  latitud y longitud
    movwf ESTADO ;pasar al estado 40
    return
es_coma ;se detecto una segunda coma despues de la primera, el mensaje completo $GNRMC con todos los datos todavia no llega
    movlw 0x36 ; estado final 36,  para no mandar nada pues esta llegando el mensaje sin data $GNRMC,,V,,,,,,,,,,N*4D
    movwf ESTADO ;pasar al estado 36, solo para mandar $+CR+LF e ir al estado de reposo 38, el último estado de la maquina
    movlw 0x24   ;echoar el signo $ a la PC, luego CR,LF; la HiperTerminal de monitoreo mostrará el signo $, una linea por segundo
    call tx_dato  ; mientras no llega Data (el módulo GPS esta en inicialización o perdió toda señal)
    return        ;
    ;No hubo segunda coma , no hubo Boton, la secuencia continua normalmente recogiendo los dígitos de Hora
case_11    ;Recibiendo el dígito de Unidades de Hora, se guarda en registro HORLOX , viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x11       ; con estado 11
    btfss STATUS,Z ;si son iguales saltar
    goto case_12  ; no es 11, continuar
    movfw RCDATO    ;el ESTADO es 11, llega el dígito de unidades de Horas HORLOX en ASCII, le sobran 30
    andlw 0x0F     ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc.
    movwf HORLOX   ; cargar el digito de hora en registro auxiliar HORLOX para corregir hora UTC a hora local
    movlw 0x12
    movwf ESTADO ;pasar al estado 12
    call echo_ar      ;hacer eco del dígito a la PC
    return
    ;
case_12    ;Recibiendo decenas de Minutos, se guarda en el registro MINHIG , viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x12       ; con estado 12
    btfss STATUS,Z ;si son iguales saltar
    goto case_13    ; no es 12, continuar
    movfw RCDATO    ;el ESTADO es 12, llega MINHIG en ASCII, le sobran 30
    andlw 0x0F     ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
    movwf MINHIG   ; cargar el digito de MINHIG
    movlw 0x13
    movwf ESTADO ;pasar al estado 13
    call echo_ar  ;MINHIG a la PC
    return
    ;
case_13    ;Recibiendo unidades de minutos, se guarda en MINLOW , viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x13       ; con estado 13
    btfss STATUS,Z ;si son iguales saltar
    goto case_14 ; no es 13, continuar
    movfw RCDATO    ;el ESTADO es 13, llega MINLOW en ASCII, le sobran 30
    andlw 0x0F     ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
    movwf MINLOW   ; cargar el digito MINLOW
    movlw 0x14
    movwf ESTADO ;pasar al estado 14
    call echo_ar  ;hacer eco de MINLOW a la PC
    return
    ;
case_14    ;Recibiendo digito de decenas de Segundos, guardar en SEGHIG , viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x14       ; con estado 14
    btfss STATUS,Z ;si son iguales saltar
    goto case_15 ; no es 14, continuar
    movfw RCDATO    ;el ESTADO es 14, llega SEGHIG en ASCII, le sobran 30
    andlw 0x0F     ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
    movwf SEGHIG   ; cargar el digito SEGHIG
    movlw 0x15
    movwf ESTADO ;pasar al estado 15
    call echo_ar  ;hacer eco de SEGHIG a la PC
    return
    ;
case_15    ;Recibiendo unidades de Segundos, guardar en SEGLOW ,
    movfw ESTADO ; Comparar
    xorlw 0x15       ; con estado 15
    btfss STATUS,Z ;si son iguales saltar
    goto case_16   ; no es 15, continuar a 16
    movfw RCDATO    ;el ESTADO es 15, llega SEGLOW en ASCII, le sobran 30
    andlw 0x0F     ; mascara para borrar ASCII, 30 queda en 00, 31 en 01 etc
    movwf SEGLOW  ; cargar el digito SEGLOW
    movlw 0x16   
    movwf ESTADO ;pasar al estado 16
    call echo_ar  ;hacer eco de SEGLOW a la PC
    return
    ;

case_16    ;Recibiendo el punto decimal de las centecimas de Segundos en el mensaje, viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x16       ; con estado 16
    btfss STATUS,Z ;si son iguales saltar
    goto case_17  ; no es 16, ir a 17
        movfw RCDATO    ;el ESTADO es 16, verifcar si llego el "."
    xorlw 0x2E      ; comparar con  . punto
    btfsc STATUS,Z ; si no llego, hay error, en ese lugar debe haber un punto, si no está hay error, ergo resetear estado
    goto si_PU  ; si se detecta  el "." ir a seguir la secuencia exitosa
    clrf ESTADO ;no se detecto el "."
    return        ;resetear ESTADO y volver
si_PU ;   
    movlw 0x17
    movwf ESTADO ;pasar al estado 17
    call echo_ar ;hacer eco del punto decimal a la PC
    return   

case_17    ;Recibiendo el cero 0X de las centecimas de Segundo en el mensaje, viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x17       ; con estado 17
    btfss STATUS,Z ;si son iguales saltar
    goto case_18   ; el estado no es 17,
        movfw RCDATO    ;el ESTADO es 17, verifcar si llego 0 (el modo del módulo no reporta decimales, estos siempre serán ceros)
    xorlw 0x30           ; comparar con  0
    btfsc STATUS,Z ; si no llego 0, hay error, resetear estado
    goto si_0X  ; si llego el 0, seguir secuencia
    clrf ESTADO ;no era 0
    return        ;resetear ESTADO y volver
si_0X ;   
    movlw 0x18
    movwf ESTADO ;pasar al estado 18
    movlw 0x0D     ; en lugar de mandar las centesimas que siempre son 00, mandar CR(0Dh), luego LF (0Ah)
    call tx_dato      ; para que la linea del HiperTerminal de monitoreo muestre la Hora y avance una linea
    return
    
case_18    ;Recibiendo el cero x0 o segundo cero  de las centecimas, viene en ASCII
    movfw ESTADO ; Comparar
    xorlw 0x18       ; con estado 18
    btfss STATUS,Z  ;si son iguales saltar
    goto case_20    ; no es 18, sera 20?
        movfw RCDATO    ;el ESTADO es 18, verifcar si llego 0
    xorlw 0x30      ; comparar con 0 en ASCII
    btfsc STATUS,Z ; si no llego 0, hay error, resetear estado
    goto si_X0       ; si llego el 0 , seguir secuencia
    clrf ESTADO     ;no era "0"
    return           ;resetear ESTADO y volver
si_X0 ;   
    movlw 0x08    ; ACA cargar el contador de comas a saltear, parámetros que no son requeridos son salteados, SON 8!
    movwf ESTAUX ; en el registro ESTAUX
    movlw 0x20
    movwf ESTADO ;pasar al estado 20 de la máquina de estados
    movlw 0x0A ; mandar LF (0Ah) para completar la linea en la HiperTerminal
    call tx_dato ;
    return   

case_20 ;aquí se cuentan las 8 comas que separan la Hora de la Fecha en el mensaje, luego se recoge la Fecha con secuencia
              ;de estados similar a la Hora y se cargan sus registros.

La rutina de mando de los dígitos al Display será la siguiente:

Código:
;------------------------------------------------------------------------------
;---  MOSTRAR HORA, MIN, SEG EN EL DISPLAY, "SHIFTEANDO" LOS BITS EN LOS REGISTROS
;------------------------------------------------------------------------------
;
; El orden de envío serial de los números será HU, MD, MU, SD, SU, y  HD que será 0 o 1
; luego se envían los bits de Back Light
;
mos_hor ; mostrar hora,min,seg, "SHIFtiando" el dato de memoria en los registros de desplazamiento
    ;CKB7 (RB7) es el Clock (CK) de los registros.        Recordar que los transistores de cambio de tensión
    ;DTB6  (RB6) es el Dato (DT) de los registros         invierten las señales CK y DT
    ;
    ;mandar hora low HU, las unidades de Hora están en los 4 bits < peso de HORLOW
    bsf PORTB,DTB6    ; Poner Datos a 1, o sea 0 en los registros (el Transistor de conversión de nivel invierte)
    btfsc HORLOW,0 ; si el bit esta en 0 no hacer nada, el T ya esta en 0
    bcf PORTB,DTB6  ; si el bit esta en 1, poner DT a 0 pues el T invierte y estara en 1
    call Pulso ; Pulsar CK para cargar/shiftear el bit en los registros
    btfsc HORLOW,1 ; continuar con los restantes 3 bits del registro
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc HORLOW,2 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc HORLOW,3 ;
    bcf PORTB,DTB6  ;
    call Pulso
    ;
   ;mandar minutos high MD, las decenas de Minutos están en los 4 bits < peso de MINHIG
    btfsc MINHIG,0 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc MINHIG,1 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc MINHIG,2 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc MINHIG,3 ;
    bcf PORTB,DTB6  ;
    call Pulso
    ;
    ;mandar minutos low MU
    btfsc MINLOW,0 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc MINLOW,1 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc MINLOW,2 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc MINLOW,3 ;
    bcf PORTB,DTB6  ;
    call Pulso
    ;
    ;mandar segundos high SD
    btfsc SEGHIG,0 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc SEGHIG,1 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc SEGHIG,2 ;
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc SEGHIG,3 ;
    bcf PORTB,DTB6  ;
    call Pulso
    ;
   ;mandar segundos low SU
    btfsc SEGLOW,0 ; Si el bit es UNO
    bcf PORTB,DTB6  ; apagar o sea encender el T
    call Pulso  ; pulsa el Clock y deja en cero la salida
    btfsc SEGLOW,1 ;
    bcf PORTB,DTB6  ; apagar o sea encender
    call Pulso
    btfsc SEGLOW,2 ;
    bcf PORTB,DTB6  ; apagar/encender
    call Pulso
    btfsc SEGLOW,3 ;
    bcf PORTB,DTB6  ;
    call Pulso
    ;
    ;mandar hora high HD, Decenas de Horas  el HD es "apagado o 1"
    btfsc HORHIG,0 ;      HORHIG sera 0000 entonces apagar
    bcf PORTB,DTB6  ;  HORHIG = 0001 entonces encender el 1 del medio digito
    call Pulso   
   ;Aqui se mandan  los 3 bits del RGB del back light
    btfsc BACLIG,0 ; mandar el bit R             serán Q1, Q2 y Q3 del ultimo registro
    bcf PORTB,DTB6  ;     
    call Pulso
    btfsc BACLIG,1 ;mandar el bit G         Mandar el estado del contador de BACLIG
    bcf PORTB,DTB6  ;
    call Pulso
    btfsc BACLIG,2 ; mandar el bit B
    bcf PORTB,DTB6  ;
    call Pulso
    ;
    return
;---------------- FIN DE MOSTRAR HORA

Pulso ; el Clock de los registros de desplazamiento
    nop  ;Los NOPs regulan el ancho de pulso y los tiempos de bajada y subida
    nop   ; los colectores de los transistores con resistencia manejando entradas CMOS dan un tiempo de subida de 2 uS
    nop   ;
    nop  ;estabilizar la salida con NOPs
    nop
    nop
    bcf PORTB,CKB7 ;flanco descendente, flanco ascendente en los registros, se produce el SHIFT
    nop  ; el tiempo que el PULSO esta en 0 (1)
    nop
    nop
    nop  ;estabilizar la salida
    nop
    nop
    bsf PORTB,CKB7 ;pasa a  1 (cero) el pulso
    nop  ;estabilizar la salida
    nop
    nop
    nop
    nop
    nop
    bsf PORTB,DTB6    ;  y dejar la salida en 1 (0) Los transistores invierten
    return
;-------------------------------------------------------------------------------------------
;
; La rutina de proceso del Back Light, es llamada cada de 7 a 10 minutos para el cambio de código de color

baklig
    ;AQUI PROCESAR EL BACKLIGHT
    incf CONLIG,1 ;incrementar el contador de espera de cambio de color
    btfss CONLIG,0X07 ;1000.0000 contador de espera para cambiar el color
    return ; si no llegó todavia, entonces volver
    clrf CONLIG ; si llegó, resetear contador de espera y procesar backlight
    btfss SEGLOW,0 ;  Agrego este toque pseudoramdom, depende como se encuentren los bits del SEGLOW, salto el color
    incf BACLIG,1 ; este incremento es random                 <Para que la secuencia de color de fondo no sea siempre la misma>
    btfss SEGLOW,1 ; Otro toque pseudoranmdom           <se agrega un toque pseudorandom de acuerdo al estado de los bits de los>
    incf BACLIG,1 ; este incremento es random                   <segundos en el momento de cambiar de codigo de color>
    incf BACLIG,1   ;incrementar el registro de Back Light, ESTE se hace siempre
    btfsc BACLIG,0X03 ; detectar 0000.1000 ó 0000.1XXX para que solo se manejen 3 bits
    clrf BACLIG ;poner a cero si llego a 8 o se pasó a 9 0 A por el random
    return
;-------------FIN DE BACK LIGHT ----------   
;

Por ultimo, parte del proceso del calendario que se muestra debajo del display

Código:
act_alm
;actualizar variables de almanaque antes de enviar las variable a los registros externos y encender los Leds
;Las variables que se usan y su asignación:
;                            Posiciones de bits;   7   6   5   4     3   2   1   0       
;P0SDI3  Variable de LEDs de posición y tres dias: LON,GRA,MIN,LAT,LIBRE,LUN,MAR,MIE
;DI4ME4  Variable de LEDs de 4 dias y 4 meses:     JUE,VIE,SAB,DOM,  ENE,FEB,MAR,ABR
;MESES8  Variable de LEDs de 8 meses:              MAY,JUN,JUL,AGO,  SEP,OCT,NOV,DIC
;Uso las auxiliares COUNT0, COUNT1, COUNT3
;
;--------primero procesar mes -----------------------------------
;       
    clrf MESES8 ; acerar variables del almanaque
    clrf DI4ME4 ;
    clrf POSDI3 ;
    ;Recuperar el mes mostrado en el display, armar las variables de almanaque y mandarlas a los registros externos
    swapf MESHIG,0 ;invertir los nibles, queda en W, el MESHIG no cambia (MESHIG son las decenas de Mes)
    andlw 0xF0   ;limpiar los bits de < peso por las dudas
    iorwf MESLOW,0 ; sumo ambos, el dato queda en W, el MESLOW no cambia
    movwf COUNT0 ; salvar el mes en la auxiliar COUNT0, el mes expresado en BCD está ahi
    ;
    ;-------------------------------------------------------
    movfw COUNT0 ; recuperar el mes en BCD
    xorlw 0x12 ; ver si es 12 (diciembre)
    btfss STATUS,Z
    goto no_12
    bsf MESES8,0 ; es 12 diciembre, encender el bit del led
    movlw 0x03 ;el 01/12/21 es miercoles   OJO , Código ACTUALIZADO AL 2021
    movwf COUNT1 ; uso la auxiliar COUNT1 para guardar el indice del primer dia del mes
    goto dia_alm ;                     
no_12 ;             Indice que se guarda en COUNT1 es : 1-lun,2-mar,3-mie,4-jue,5-vie,6-sab,7-dom
    movfw COUNT0 ;
    xorlw 0x11
    btfss STATUS,Z
    goto no_11
    bsf MESES8,1 ; es 11 (nov), encender el led
    movlw 0x01 ;el 01/11/21 es lunes
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_11
    movfw COUNT0 ;
    xorlw 0x10
    btfss STATUS,Z
    goto no_10
    bsf MESES8,2 ; es 10 octubre, encender el led
    movlw 0x05 ;el 01/10/21 es viernes
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_10
    movfw COUNT0 ;
    xorlw 0x09
    btfss STATUS,Z
    goto no_09
    bsf MESES8,3 ; es 09 septiembre, encender el led
    movlw 0x03 ;el 01/09/21 es miercoles
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_09
    movfw COUNT0 ;
    xorlw 0x08
    btfss STATUS,Z
    goto no_08
    bsf MESES8,4 ; es 08 agosto, encender el led
    movlw 0x07 ;el 01/08/21 es domingo
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_08
    movfw COUNT0 ;
    xorlw 0x07
    btfss STATUS,Z
    goto no_07
    bsf MESES8,5 ; es 07 julio, encender el led
    movlw 0x04 ;el 01/07/21 es jueves
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_07
    movfw COUNT0 ;
    xorlw 0x06
    btfss STATUS,Z
    goto no_06
    bsf MESES8,6 ; es 06 junio, encender el led
    movlw 0x02 ;el 01/06/21 es martes
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_06
    movfw COUNT0 ;
    xorlw 0x05
    btfss STATUS,Z
    goto no_05
    bsf MESES8,7 ; es 05 mayo , encender el led
    movlw 0x06 ;el 01/12/21 es sabado
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_05
    movfw COUNT0 ;
    xorlw 0x04
    btfss STATUS,Z
    goto no_04
    bsf DI4ME4,0 ; es 04 abril, encender el led
    movlw 0x04 ;el 01/04/21 es jueves
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_04
    movfw COUNT0 ;
    xorlw 0x03
    btfss STATUS,Z
    goto no_03
    bsf DI4ME4,1 ; es 03 marzo, encender el led
    movlw 0x01 ;el 01/03/21 es lunes
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_03
    movfw COUNT0 ;
    xorlw 0x02
    btfss STATUS,Z
    goto no_02
    bsf DI4ME4,2 ; es 02 febrero, encender el led
    movlw 0x01 ;el 01/02/21 es lunes
    movwf COUNT1 ;inicializar COUNT1
    goto dia_alm
no_02 ; entonces es 01
    bsf DI4ME4,3 ; es 01 enero, encender el led
    movlw 0x05 ;el 01/01/21 es viernes
    movwf COUNT1 ;inicializar COUNT1

dia_alm
;
;--------aqui procesar dia de la semana -----------------------------------
;       

;

Entonces aquí doy por finalizado este proyecto, cualquier duda o ampliación me escriben
Gracias por el espacio y la atención
Nos vemos en el siguiente proyecto
Saludos
 
Atrás
Arriba