Está en la página 1de 12

Programa Principal (main)

#include "board.h"
#include "Inicializacion.h"
#include "Librerias_Proyecto.h"

/* Definición de constantes */
#define tmuestreo0 1000 // Tiempo de muestreo de la temperatura (en ms)
#define tmuestreo1 10 // Tiempo de muestreo del nivel de agua (en ms)
#define encendido 0
#define apagado 1
#define timeairon 300000 // Tiempo en el cual el aireador se mantiene encendido
#define timeairoff 1200000 // Tiempo en el cual el aireador se mantiene apagado
#define timeledon 1000 // Tiempo en el cual el LED amarillo se mantiene encendido (mientras parpadea)
#define timeledoff 1000 // Tiempo en el cual el LED amarillo se mantiene apagado (mientras parpadea)
#define timebuzzeron 1000 // Tiempo en el cual el buzzer se mantiene encendido (mientras chilla intermitentemente)
#define timebuzzeroff 5000 // Tiempo en el cual el buzzer se mantiene apagado (mientras chilla intermitentemente)
#define ciclocorto 20000 // Duración del ciclo corto
#define ciclomedio 30000 // Duración del ciclo medio
#define ciclolargo 40000 // Duración del ciclo largo
#define umbralmax 1800 // Umbral de tensión (en mV) del sensor de nivel de agua a partir del cual el tubo está lleno
#define umbralmin 800 // Umbral de tensión (en mV) del sensor de nivel de agua a partir del cual el tubo está vacío
#define offsetvaciado 60000 // Tiempo extra de vaciado del tubo
#define tmanguera 180000 // Tiempo de espera para saber si la manguera ha sido conectada
#define tsolnutritiva 60000 // Tiempo de espera para que el usuario agregue la solución nutritiva

/* Definimos los pines del módulo relay como constantes de acuerdo al dispositivo que controlan */
#define pinvalvula1 9 // Pin correspondiente a la electroválvula 1 (P0.9)
#define pinvalvula2 7 // Pin correspondiente a la electroválvula 2 (P0.7)
#define pinbomba1 6 // Pin correspondiente a la bomba de agua 1 (P0.6)
#define pinaireador 18 // Pin correspondiente al aireador (P0.18)
#define pinverde 17 // Pin correspondiente al LED verde (P0.17)
#define pinamarillo 15 // Pin correspondiente al LED amarillo (P0.15)
#define pinbomba2 16 // Pin correspondiente a la bomba de agua 2 (P0.16)
#define pinbuzzer 12 // Pin correspondiente al buzzer (P2.12)

/* Variables globales para el muestreo de la temperatura */


float prom, volpromtemp; // Promedio de las 60 muesttas
uint8_t tprom; // Temperatura promedio
uint16_t voltemp[60]; // Vector para guardar las 60 muestras (tensión equivalente del resultado de la conversión en mV)
uint16_t tiempo0 = tmuestreo0; // Tiempo de muestreo de la temperatura
uint8_t cant0 = 0; // Contador que se incrementa a medida que se toman las muestras por minuto

/* Variables para el muestreo del nivel de agua en el tubo */


float promagua, volpromagua; // Promedio de las muestras
uint8_t cant1 = 0; // Contador que se incrementa a medida que se toman las muestras
uint16_t volagua[60]; // Tensión equivalente del resultado de la conversión de nivel de agua en mV
uint16_t tiempo1 = tmuestreo1; // Tiempo de muestreo del nivel de agua
uint16_t tvaciado; // Tiempo en el cual el tubo continúa vaciándose después de la lectura umbralmin del sensor de nivel de agua

/* Variables globales para el llenado del tanque y del tubo */


uint32_t t1 = 0; // Tiempo de espera para saber si la manguera está conectada
uint32_t t2 = 0; // Tiempo de espera para que el usuario agregue la solución nutritiva
bool sbajo; // Estado del sensor de nivel bajo
bool salto; // Estado del sensor de nivel alto
uint8_t esttanque; // Estado del diagrama de estados del llenado de tanque y tubo
uint16_t tdelay; // Demora para que se elimine el ruido producido al desactivar la electroválvula 2 y la bomba de agua 2

/* Variables para el ciclo de riego */


uint8_t ciclo = 1; // Ciclo de llenado basado en la temperatura
uint32_t tciclo = 0; // Tiempo de ciclo

/* Variables para la recepción de datos desde la app */


uint8_t nbytes; // Número de bytes recibidos
char rxbuf[1]; // Cadena de caracteres recibida

/* Variables para el control del aireador */


uint8_t estair; // Estado del aireador (encendido/apagado)
uint32_t tairon; // Tiempo en el cual el aireador se mantiene encendido (5 minutos)
uint32_t tairoff; // Tiempo en el cual el aireador se mantiene apagado (20 minutos)

/* Variables para activar/desactivar los LEDs indicadores */


uint16_t tledon; // Tiempo en el cual el LED amarillo se mantiene encendido (1 segundo)
uint16_t tledoff; // Tiempo en el cual el LED amarillo se mantiene apagado (1 segundo)
uint8_t estled = 1;
bool flag_led = 0; /* Variable tipo bandera para indicar cuándo debe parpadear el LED amarillo. Se pone en 1 cuandocomienza el
ciclo de llenado, y se pone en 0 cuando termina dicho ciclo */

/* Variables para controlar el buzzer */


uint16_t tbuzzeron; // Tiempo en el cual el buzzer se mantiene encendido (1 segundo)
uint16_t tbuzzeroff; // Tiempo en el cual el buzzer se mantiene apagado (5 segundos)
uint8_t estbuzzer = 1; // Variable para controlar el estado del buzzer
bool flag_buzzer = 0; /* Variable tipo bandera para indicar cuándo debe chillar el buzzer. Se pone en 1 cuando la manguera está
desconectada y se envía el aviso correspondiente a través de la app, y se pone en 0 cuando el usuario conectó la manguera */

void LeerNivAgua(void);
void CicloDeRiego(void);
void DiagramaLlenado(void);
void EstadoInicial(void);
void Aireador(void);
void ParpadeoLED(void);
void Buzzer(void);
void LeerTemperatura(void);

int main(void) {

/* Rutinas de inicialización */
InitHardware1();
InitPinsGPIO();
InitADC();
ConfigUART();

EstadoInicial();

while(1) {

/* Rutinas que implementan los diagramas de estado para atender a todos los componentes del proyecto */
LeerTemperatura();
LeerNivAgua();
DiagramaLlenado();

}
return 0 ;
}

void DiagramaLlenado(void){

ParpadeoLED();
Buzzer();

switch(esttanque){
case 0:{
/* En el estado 0, el tubo está vaciándose (luego de haber finalizado el ciclo), y cuando el sensor de nivel agua baja
del umbralmin, se inicia una demora (programable con la constante offsetvaciado) para permitir que el tubo siga vaciándose un
tiempo más, pasando al estado 1 */
if(volpromagua > umbralmin){
esttanque = 0;
}
else {
esttanque = 1;
tvaciado = offsetvaciado; // Tiempo extra de vaciado del tubo después de haber detectado el umbralmin
Chip_UART_SendBlocking(LPC_UART3, "*b65*", 5); // Enviamos a través de la app el nivel del tubo (65%)
}
}
break;
case 1:{
/* En el estado 1, el tubo sigue vaciándose luego de haberse iniciado el offset de vaciado. Una vez finalizado el
tiempo, leemos el estado del sensor de nivel bajo. Si este sensor marca un 0, pasamos al estado 2 y volvemos a llenar el tubo, y
el ciclo comienza nuevamente. Si marca un 1, llenamos el tanque, pasando al estado 3. */
if(tvaciado == 0){
AlternarPin(0,pinvalvula2); // Cerrar electroválvula 2 (de vaciado de tubos)
AlternarPin(0,pinbomba2); // Desactivar bomba de agua 2
Chip_UART_SendBlocking(LPC_UART3, "*b30*", 5); // Enviamos a través de la app el nivel del tubo (30%)
sbajo = Chip_GPIO_ReadPortBit(LPC_GPIO, 0, 3); // Leemos el estado del sensor de nivel bajo
/* Luego de haber conmutado la electroválvula 2 y la bomba de agua 2, comienza una demora de 300 ms
para que se elimine el ruido producido por dicha conmutación */
tdelay = 300;
while(tdelay > 0){
esttanque = 1;
}
/* Finalizada esa demora, evaluamos el sensor de nivel bajo */
if(sbajo == 0){
esttanque = 2;
AlternarPin(0,pinbomba1); // Activar bomba de agua 1 (de llenado de tubo)
}
else {
esttanque = 3;
salto = 1;
t1 = tmanguera; // Tiempo de espera para saber si la manguera está conectada
AlternarPin(0,pinvalvula1); // Abrir electroválvula 1 (para el llenado del tanque)
/* Habilitamos las interrupciones por flanco descendente del sensor de nivel alto, limpiando
previamente las interrupciones pendientes */
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, GPIOINT_PORT0, 1 << 2);
Chip_GPIOINT_SetIntFalling(LPC_GPIOINT, GPIOINT_PORT0, 1 << 2);
/* Enviar el dato del nivel inferior del tanque (11 litros) */
Chip_UART_SendBlocking(LPC_UART3, "*B11*", 5);
}
}
else esttanque = 1;
}
break;
case 2:{
/* En el estado 2, el tubo está llenándose, luego de que se completara el llenado del tanque y se agregara la
solución nutritiva. Cuando el tubo finalmente se llena, pasamos al estado 6 (estado final). */
if(volpromagua > umbralmax){
esttanque = 6;
AlternarPin(0,pinbomba1); // Desactivar bomba de agua 1
AlternarPin(0,pinverde); // Encender LED verde
flag_led = 0; // El LED amarillo deja de parpadear
/* Enviamos a través de la app el nivel del tubo (100%) */
Chip_UART_SendBlocking(LPC_UART3, "*b100*", 6);
}
else {
esttanque = 2;
}
}
break;
case 3:{
/* En este estado, el tanque empieza a llenarse, con la electroválvula 1 activada. Una vez que el tanque
completa su llenado y recibimos la correspondiente interrupción del sensor de nivel alto, saltamos al estado 5, y le indicamos al
usuario que debe agregar la solución nutritiva. Si la manguera no está conectada, saltamos al estado 4 y le avisamos al usuario
que debe conectar la manguera */
if(salto == 0){
salto = 1;
// Deshabilitamos las interrupciones por flanco descendente del sensor de nivel alto
Chip_GPIOINT_SetIntFalling(LPC_GPIOINT, GPIOINT_PORT0, 0 << 2);
esttanque = 5;
AlternarPin(0,pinvalvula1); // Cerrar electroválvula 1 (para el llenado del tanque)
/* Indicar al usuario que debe agregar solución nutritiva al tanque */
Chip_UART_SendBlocking(LPC_UART3, "*MAgregar solucion nutritiva\r\n*", 31);
t2 = tsolnutritiva; // Tiempo de espera de 60 s para que el usuario agregue la solución nutritiva
Chip_UART_SendBlocking(LPC_UART3, "*B30*", 5); // Enviar el dato del nivel superior del tanque (30
litros)
}
else {
if(t1 == 0){
esttanque = 4;
t1 = tmanguera;
/* Avisar al usuario que la manguera no está conectada */
Chip_UART_SendBlocking(LPC_UART3, "*MLa manguera no esta conectada\r\n*", 34);
flag_buzzer = 1; // Empieza a chillar el buzzer
AlternarPin(0,pinvalvula1); // Apagamos momentáneamente la electroválvula 1
}
else esttanque = 3;
}
}
break;
case 4:{
/* Una vez que la manguera fue conectada, el usuario debe mandar un mensaje de aviso a través de la app
* para luego volver al estado 4 */
if(t1 == 0){
esttanque = 4;
t1 = tmanguera;
/* Avisar al usuario que la manguera no está conectada */
Chip_UART_SendBlocking(LPC_UART3, "*MLa manguera no esta conectada\r\n*", 34);
}
else {
/* Si se recibió un "c" como caracter desde la app, encendemos nuevamente la electroválvula 1 y el
buzzer deja de chillar */
if(strcmp(rxbuf,"c") == 0){
memset(rxbuf,0,1); // Reiniciamos la variable rxbuf con un caracter 0
esttanque = 3;
flag_buzzer = 0; // El buzzer deja de chillar
AlternarPin(0,pinvalvula1); // Volvemos a encender la electroválvula 1
}
else esttanque = 4;
}
}
break;
case 5:{
/* Una vez que la solución nutritiva fue agregada, el usuario debe mandar un mensaje de confirmación a
* través de la app para luego pasar al estado 2 */
if(t2 == 0){
esttanque = 5;
t2 = tsolnutritiva;
/* Indicar al usuario que debe agregar solución nutritiva al tanque */
Chip_UART_SendBlocking(LPC_UART3, "*MAgregar solucion nutritiva\r\n*", 31);
}
else {
if(strcmp(rxbuf,"a") == 0){
memset(rxbuf,0,1); // Reiniciamos la variable rxbuf con un caracter 0
esttanque = 2;
AlternarPin(0,pinbomba1); // Activar bomba de agua 1
AlternarPin(0,pinaireador); // Activar aireador
tairon = timeairon; // Tiempo en el cual el aireador se mantiene encendido (5 minutos)
estair = encendido;
}
else esttanque = 5;
}
}
break;
case 6:{
/* Estado final. Se selecciona el ciclo de riego de acuerdo a la temperatura */
CicloDeRiego();
Aireador();
}
break;
}
}

/* Toma de muestras de la temperatura. Se toma 1 muestra por segundo (tiempo de muestreo de 1 s) y se promedian 60 muestras por
minuto */
void LeerTemperatura(void){

if(cant0<60){
if(tiempo0 == 0){
cant0=LeerDato(voltemp,cant0,ADC_CH0);
tiempo0 = tmuestreo0;
}
}
else {
volpromtemp = PromedioMuestras(voltemp,cant0);
cant0=0;
tprom = volpromtemp/10; // Temperatura promedio
EnviarDato(tprom); // Enviamos el dato de temperatura a través de la app
}
}

/* Toma de muestras del nivel de agua del tubo. Se toma 1 muestra cada 10 ms (tiempo de muestreo de 10 ms) y se promedian las
últimas 30 muestras (o sea, se promedia cada 0.3 s) */
void LeerNivAgua(void){

if(cant1<30){
if(tiempo1 == 0){
cant1=LeerDato(volagua,cant1,ADC_CH1);
tiempo1 = tmuestreo1;
}
}
else {
volpromagua = PromedioMuestras(volagua,cant1);
cant1=0;
}
}

void CicloDeRiego(void){

/* Se elige alguno de los ciclos de riego en función de la temperatura. Tenemos 3 ciclos: el ciclo corto (para
temperaturas superiores a 20°C), el ciclo medio (para temperaturas de entre 10 y 20°C) y el ciclo largo (para temperaturas
inferiores a 10°C */

switch(ciclo){
case 1: {
if(tprom < 10){
tciclo = ciclolargo; // Tiempo de riego (invierno)
ciclo = 2;
}
else{
if(tprom > 20){
tciclo = ciclocorto; // Tiempo de riego (verano)
ciclo = 2;
}
else{
tciclo = ciclomedio; // Tiempo de riego (media estación)
ciclo = 2;
}
}
}
break;
case 2:{
if(tciclo == 0){
ciclo = 1;
esttanque = 0;
AlternarPin(0,pinvalvula2); // Vaciar tubo hasta que el nivel de agua llegue a su valor óptimo
AlternarPin(0,pinbomba2); // Activar bomba de agua 2
AlternarPin(0,pinverde); // Apagar LED verde
flag_led = 1; // Comienza a parpadear el LED amarillo
}
else ciclo = 2;
}
break;
}
}

/* Diagrama de estados que controla el aireador, manteniéndolo encendido durante 5 minutos y apagado durante 20 minutos */
void Aireador(void){

switch(estair){
case encendido:{
if(tairon == 0){
estair = apagado;
tairoff = timeairoff; // Tiempo en el cual el aireador se mantiene apagado (20 minutos)
AlternarPin(0,pinaireador); // Apagar aireador
}
else estair = encendido;
}
break;
case apagado:{
if(tairoff == 0){
estair = encendido;
tairon = timeairon; // Tiempo en el cual el aireador se mantiene encendido (5 minutos)
AlternarPin(0,pinaireador); // Encender aireador
}
else estair = apagado;
}
break;
}
}

/* Esta función se utiliza para hacer que el LED amarillo titile. Consta de un diagrama de estados con 2 estados:
* En el estado 1, el LED amarillo permanece apagado, y se enciende cuando comienza el ciclo de llenado, pasando
* al estado 2. En los estados 2 y 3, el LED parpadea periódicamente, manteniéndose encendido en el estado 2 y apagado en el
* estado 3. El LED deja de parpadear cuando se acaba el ciclo de llenado, volviendo al estado 1. */

void ParpadeoLED(void){

switch(estled){
case 1:{
if(flag_led){
estled = 2;
// Tiempo en el cual el LED amarillo se mantiene encendido mientras parpadea (1 segundo)
tledon = timeledon;
AlternarPin(0,pinamarillo); // El LED amarillo comienza a parpadear
}
else estled = 1;
}
break;
case 2:{
if(flag_led){
estled = 2;
if(tledon == 0){
estled = 3;
// Tiempo en el cual el LED amarillo se mantiene apagado mientras parpadea (1 s)
tledoff = timeledoff;
AlternarPin(0,pinamarillo); // El LED amarillo se apaga (mientras parpadea)
}
}
else {
estled = 1;
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 15); // Apagar el LED amarillo
}
}
break;
case 3:{
if(flag_led){
estled = 3;
if(tledoff == 0){
estled = 2;
// Tiempo en el cual el LED amarillo se mantiene encendido mientras parpadea (1 s)
tledon = timeledon;
AlternarPin(0,pinamarillo); // El LED amarillo se enciende (mientras parpadea)
}
}
else {
estled = 1;
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 15); // Apagar el LED amarillo
}
}
break;
}
}

/* Esta función se utiliza para hacer que el buzzer chille intermitentemente. Consta de un diagrama de estados con
* 2 estados: En el estado 1, el buzzer permanece apagado, y comienza a chillar cuando la manguera no está conectada (luego
* del tiempo de espera de 60 s) pasando al estado 2. En los estados 2 y 3, el buzzer chilla de forma intermitente,
* manteniéndose encendido durante 1 segundo (en el estado 2) y apagado durante 5 segundos (en el estado 3). El buzzer deja
* de chillar cuando se conecta la manguera, volviendo al estado 1. */
void Buzzer(void){

switch(estbuzzer){
case 1:{
if(flag_buzzer){
estbuzzer = 2;
tbuzzeron = timebuzzeron; // Tiempo en el cual el buzzer se mantiene encendido mientras chilla (1 s)
AlternarPin(2,pinbuzzer); // El buzzer comienza a chillar
}
else estbuzzer = 1;
}
break;
case 2:{
if(flag_buzzer){
estbuzzer = 2;
if(tbuzzeron == 0){
estbuzzer = 3;
tbuzzeroff = timebuzzeroff; // Tiempo en el cual el buzzer se mantiene apagado (5 s)
AlternarPin(2,pinbuzzer); // El buzzer se apaga por 5 segundos
}
}
else {
estbuzzer = 1;
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 2, 12); // El buzzer deja de chillar
}
}
break;
case 3:{
if(flag_buzzer){
estbuzzer = 3;
if(tbuzzeroff == 0){
estbuzzer = 2;
tbuzzeron = timebuzzeron; // Tiempo en el cual el buzzer se mantiene encendido (1 s)
AlternarPin(2,pinbuzzer); // El buzzer se enciende por un segundo
}
}
else {
estbuzzer = 1;
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 2, 12); // El buzzer deja de chillar
}
}
break;
}
}
/* Esta función nos permite ingresar al diagrama de estados principal según las condiciones iniciales del programa */
void EstadoInicial(void){

uint16_t adc_value1, volaguainit; // Variables locales para tomar muestra inicial del nivel del agua del tubo

sbajo = Chip_GPIO_ReadPortBit(LPC_GPIO, 0, 3); // Leemos el sensor de nivel bajo

Chip_ADC_ReadValue(LPC_ADC, ADC_CH1, &adc_value1); // Leemos el nivel de agua del tubo


volaguainit = adc_value1*3300/4095; // Resultado de la conversión en mV
tprom = 25; // Asignamos una temperatura promedior superior a 20°C para que el sistema arranque en el ciclo más corto

/* Ponemos en 1 todos los pines conectados al módulo relay */


Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 9);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 7);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 6);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 2, 12);

Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 18);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 17);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 15);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 16);

flag_led = 1; // Comienza a parpadear el LED amarillo

/* Primero medimos el nivel de agua del tubo. Si excede el nivel máximo, significa que el tubo está lleno; por lo tanto,
comenzamos a vaciarlo, ingresando al estado 0. Si el nivel de agua está por debajo del umbral máximo, evaluamos el sensor de
nivel bajo del tanque. Si marca un 1, ingresamos al estado 3, comenzando así con el llenado del tanque; mientras que si marca un
0, pasamos al estado 2 para comenzar con el llenado del tubo */

if(volagua[0] > umbralmax){


esttanque = 0;
AlternarPin(0,pinvalvula2); // Vaciar tubo hasta que el nivel de agua llegue a su valor óptimo
AlternarPin(0,pinbomba2); // Activar bomba de agua 2
}
else {
if(sbajo == 1){
sbajo = 0;
salto = 1; // Estado del sensor de nivel alto cuando empezamos a llenar el tanque
esttanque = 3;
t1 = tmanguera; // Espera de 60 segundos para saber si la manguera está conectada
AlternarPin(0,pinvalvula1); // Abrir electroválvula de llenado de tanque
Chip_UART_SendBlocking(LPC_UART3, "*B11*", 5); // Enviar el dato del nivel inferior del tanque (11
litros)
}
else {
esttanque = 2;
AlternarPin(0,pinbomba1); // Abrir bomba de agua 1 para el llenado del tubo
}
}
}

/* Rutina de atención a las interrupciones del pin del sensor de nivel alto */
void EINT3_IRQHandler(void){

/* Interrupción por flanco descendente del P0.2 (sensor de nivel alto) */


if (Chip_GPIOINT_GetStatusFalling(LPC_GPIOINT, GPIOINT_PORT0) && (1 << 2)) {
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, GPIOINT_PORT0, 1 << 2);
salto = 0; // Estado del sensor
}

/* Rutina de atención a las interrupciones de la UART3 */


void UART3_IRQHandler(void){

/* Deshabilitación de las interrupciones */


NVIC_DisableIRQ(UART3_IRQn); // Desabilita las interrupciones de la UART en el NVIC
Chip_UART_IntDisable(LPC_UART3, UART_IER_RBRINT); // Desabilita las interrupción del RBR (buffer de recepción) en la
UART

nbytes = Chip_UART_Read(LPC_UART3, rxbuf, 1); // Lee datos a través del periférico UART3 (de a un

/* Habilitación de las interrupciones */


Chip_UART_IntEnable(LPC_UART3, UART_IER_RBRINT); // Habilita las interrupciones del RBR en la unidad UART
NVIC_EnableIRQ(UART3_IRQn); // Habilita las interrupciones de la UART en el NVIC
}
/* Función para controlar las distintas variables que funcionan como temporizadores a través del temporizador del sistema
(SysTick) Este temporizador es un contador descendente de 24 bits que genera una interrupción cada vez que llega a 0. Cuando se
genera dicha interrupción, se decrementan las variables de temporización definidas en el programa, siempre y cuando estén
cargadas con un valor mayor a cero. Las interrupciones del Systick se generan cada 1 ms, según lo definido en la función de
inicialización del sistema */
void SysTick_Handler(void){

// Interrupción asociada al tiempo de muestreo de la temperatura


if(tiempo0){
tiempo0--;
}

// Interrupción asociada al tiempo de muestreo del nivel de agua


if(tiempo1){
tiempo1--;
}

// Interrupción asociada al tiempo de espera para que el usuario conecte la manguera


if(t1){
t1--;
}

// Interrupción asociada al tiempo de espera para que el usuario agregue la solución nutritiva
if(t2){
t2--;
}

// Interrupción vinculada al tiempo que dura un ciclo determinado


if(tciclo){
tciclo--;
}

// Interrupción asociada al tiempo en el cual el aireador permanece encendido


if(tairon){
tairon--;
}

// Interrupción asociada al tiempo en el cual el aireador permanece apagado


if(tairoff){
tairoff--;
}

// Interrupción asociada al tiempo en el cual el LED amarillo se mantiene encendido (mientras parpadea)
if(tledon){
tledon--;
}

// Interrupción asociada al tiempo en el cual el LED amarillo se mantiene apagado (mientras parpadea)
if(tledoff){
tledoff--;
}

// Interrupción asociada al tiempo en el cual el buzzer se mantiene encendido (mientras chilla)


if(tbuzzeron){
tbuzzeron--;
}

// Interrupción asociada al tiempo en el cual el buzzer se mantiene apagado


if(tbuzzeroff){
tbuzzeroff--;
}

// Interrupción asociada al tiempo de vaciado del tubo


if(tvaciado){
tvaciado--;
}
// Interrupción asociada al tiempo de demora después de la conmutación de la electroválvula 2
if(tdelay){
tdelay--;
}
}
Librería de Inicialización
Inicializacion.h (archivo de cabecera)
/*
* Inicializacion.h
*
* Created on: 16 feb. 2021
* Author: Usuario
*/

#ifndef INICIALIZACION_H_
#define INICIALIZACION_H_

#include "board.h"

/* Prototipos de las funciones */


void InitHardware1(void);
void InitPinsGPIO(void);
void InitADC(void);
void ConfigUART(void);

#endif /* INICIALIZACION_H_ */

Inicialización.c (archivo fuente)


/*
* Inicializacion.c
*
* Created on: 16 feb. 2021
* Author: Usuario
*/

#include "Inicializacion.h"

/* Definición de las funciones */

/* Inicializa el hardware de la placa */


void InitHardware1(void){

SystemCoreClockUpdate(); // Configura la frecuencia del reloj de la CPU

Board_Init(); // Configura e inicializa todos los bloques requeridos y funciones relacionadas con el hardware de la placa

Board_LED_Set(0, true); // Enciende el LED de la placa

SysTick_Config(SystemCoreClock/1000); // Configura el temporizador del sistema SysTick para que genere interrupciones cada 1
ms
}

/* Inicializa los pines GPIO y configura las interrupciones de los pines de entrada */
void InitPinsGPIO(void){

// Configuración de los pines P0.2 y P0.3 como entradas


Chip_GPIO_SetPinDIRInput(LPC_GPIO, 0, 2); // J6-21 (Sensor flotante de nivel alto)
Chip_GPIO_SetPinDIRInput(LPC_GPIO, 0, 3); // J6-22 (Sensor flotante de nivel bajo)

// Configuración de los pines P0.9, P0.7, P0.6 y P0.5 como salidas


Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 9); // J6-5 (Mod. relay - electroválvula 1)
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 7); // J6-7 (Mod. relay - electroválvula 2)
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 6); // J6-8 (Mod. relay - bomba de agua 1)
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 2, 12); // J6-53 (Mod. relay - buzzer)

// Configuración de los pines P0.18, P0.17, P0.15 y P0.16 como salidas


Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 18); // J6-11 (Mod. relay - aireador)
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 17); // J6-12 (Mod. relay - LED indicador verde)
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 15); // J6-13 (Mod. relay - LED indicador amarillo)
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 16); // J6-14 (Mod. relay - bomba de agua 2)

/* Configuración de las interrupciones de los pines de entrada */

/* Interrupción por flanco descendente (sensor de nivel alto) */


Chip_GPIOINT_SetIntFalling(LPC_GPIOINT, GPIOINT_PORT0, 1 << 2);
NVIC_ClearPendingIRQ(EINT3_IRQn); // Limpiamos las interrupciones pendientes en el NVIC
NVIC_EnableIRQ(EINT3_IRQn); // Habilitamos las interrupciones de los pines GPIO en el NVIC
}
/* Inicializa los canales 0 y 1 del ADC y habilita el modo ráfaga del ADC */
void InitADC(void){

ADC_CLOCK_SETUP_T ADCSetup; // Variable tipo estructura que contiene parámetros del ADC (rate, precisión)

/* Configuración del pin P0.23 como AD0.0 y P0.24 como AD0.1 */


Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 23, IOCON_FUNC1); // J6-15 (Sensor de nivel de agua)
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 24, IOCON_FUNC1); // J6-16 (Sensor de temperatura)

/* Configuración del ADC */


Chip_ADC_Init(LPC_ADC, &ADCSetup);
Chip_ADC_EnableChannel(LPC_ADC, ADC_CH1, ENABLE); // Habilita el canal 1 del ADC
Chip_ADC_EnableChannel(LPC_ADC, ADC_CH0, ENABLE); // Habilita el canal 0 del ADC

/* Habilitación del modo ráfaga */


Chip_ADC_SetBurstCmd(LPC_ADC, ENABLE);
}

/* Inicializa y configura la UART */


void ConfigUART(void){

/* Configuración del pin P0.0 como TxD3 Y P0.1 como RxD3 */


Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 0, IOCON_FUNC2); // J6-9
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 1, IOCON_FUNC2); // J6-10

/* Configuración de la UART3: 9600 bps, 8 bits de datos, sin bit de paridad */


Chip_UART_Init(LPC_UART3);
Chip_UART_SetBaud(LPC_UART3, 9600); // Configura la velocidad de transmisión a 9600 bps

/* Configura el tamaño de la palabra de datos, la cantidad de bits de parada y los bits de paridad
* - UART_LCR_WLEN8 - Tamaño de la palabra de datos (8 bits)
* - UART_LCR_SBS_1BIT - Selección del bit de parada (1 bit de parada)
* - UART_LCR_PARITY_EN - Habilitación de paridad (bit de paridad habilitado)
* - UART_LCR_PARITY_EVEN - Selección de paridad (paridad par) */

Chip_UART_ConfigData(LPC_UART3, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT));

/* Configuración del sistema de cola FIFO


* - UART_FCR_FIFO_EN - Habilitación del sistema de cola
* - UART_FCR_RX_RS - RX FIFO reset (resetea la unidad FIFO de recepción)
* - UART_FCR_TX_RS - TX FIFO reset (resetea la unidad FIFO de transmisión)
* - UART_FCR_DMAMODE_SEL - Selecciona el modo DMA siempre y cuando la unidad FIFO esté habilitada
*/
Chip_UART_SetupFIFOS(LPC_UART3, (UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS | UART_FCR_DMAMODE_SEL));
Chip_UART_TXEnable(LPC_UART3); // Habilita la transmisión en el pin TXD0

Chip_UART_IntEnable(LPC_UART3, UART_IER_RBRINT); // Habilita las interrupciones del RBR en la unidad UART


NVIC_EnableIRQ(UART3_IRQn); // Habilita las interrupciones de la UART en el NVIC
}
Librería del proyecto
Librerias_Proyecto.h
/*
* Librerias_Proyecto.h
*
* Created on: 16 feb. 2021
* Author: Usuario
*/

#ifndef LIBRERIAS_PROYECTO_H_
#define LIBRERIAS_PROYECTO_H_

#include "board.h"
#include "string.h"
#include "stdlib.h"

/* Definición de constantes */
#define alto 1
#define bajo 0

/* Definición de variables externas */


extern uint32_t suma;
extern float pr;
extern uint8_t i;
extern char temp[3];
extern char tempf[6];
extern char tchar[3];

/* Prototipos de funciones */
void AlternarPin(int,int);
float PromedioMuestras(uint16_t [], uint16_t);
void EnviarDato(uint8_t);
uint8_t LeerDato(uint16_t [],uint8_t,ADC_CHANNEL_T);

#endif /* LIBRERIAS_PROYECTO_H_ */

Librerias_Proyecto.c
/*
* Librerias_Proyecto.c
*
* Created on: 16 feb. 2021
* Author: Usuario
*/

#include "Librerias_Proyecto.h"

/* Declaración de variables */
uint32_t suma;
float pr;
uint8_t i;
char temp[3] = "*T";
char tempf[6];
char tchar[3];

/* Definición de las funciones */

/* Realiza el promedio de las muestras guardadas en un vector */


float PromedioMuestras(uint16_t val[], uint16_t cantmuestras){

/* Se suman todas las muestras contenidas en el vector */


for(i=0;i<cantmuestras;i++){
suma = suma+val[i];
}
pr = suma/cantmuestras; // Se divide la suma anterior por la cantidad de muestras (se hace el promedio)
suma = 0; // Se resetea la variable suma para poder calcular otro promedio
return pr;
}

/* Cambia el estado lógico del pin (si hay un 1, pone un 0, y si hay un 0 pone un 1) */
void AlternarPin(int port, int pin){
_Bool pinstate;

pinstate = Chip_GPIO_ReadPortBit(LPC_GPIO, port, pin); // Leemos el estado lógico del pin

switch(pinstate){
case alto:{
Chip_GPIO_SetPinOutLow(LPC_GPIO, port, pin); // El pin se pone en 0
pinstate = bajo;
}
break;
case bajo:{
Chip_GPIO_SetPinOutHigh(LPC_GPIO, port, pin); // El pin se pone en 1
pinstate = alto;
}
break;
}
}

/* Envía el dato de temperatura a la app a través de la UART3 (la cual se comunica con el módulo Bluetooth */
void EnviarDato(uint8_t tprom){

/* Armamos el string para enviar a través de la app, con el siguiente formato: *T<Dato de temperatura>* */
strcat(tempf,temp);
itoa(tprom,tchar,10); // Se convierte el dato de temperatura (entero) en un string (cadena de caracteres)
strcat(tempf,tchar);
strncat(tempf,temp,1);

Chip_UART_SendBlocking(LPC_UART3, &tempf, 6); // Transmite un arreglo de bytes en el periférico UART

memset(tempf,0,6); /* Se resetea el string tempf para que contenga sólo ceros y luego pueda ser rellenado con un nuevo
valor de temp. */
}

/* Esta función lee los resultados de la conversión más reciente y los guarda en un vector */
uint8_t LeerDato(uint16_t vol[], uint8_t cant, ADC_CHANNEL_T channel){

uint16_t adc_value;

Chip_ADC_ReadValue(LPC_ADC, channel, &adc_value); // Guardamos el resultado de la conversión


vol[cant] = adc_value*3300/4095; // Tensión equivalente del resultado de la conversión en mV
cant++; // Incrementamos la variable cant cada vez que tomamos una muestra
return cant;
}

También podría gustarte