SISTEMA DE RIEGO AUTOMÁTICO CON MÚSICA

El objetivo era hacer un programa que pueda activar una bomba de agua en la noche, y que por las mañanas reproduzca música para las plantas. El depósito de agua debe tener un flotador eléctrico que mande señal de que no hay agua. Los mensajes deben verse en el LCD. Además, implementar una aplicación sencilla de labview.
Para más detalles puede consultar: https://www.dropbox.com/s/hjyeaymroexqjgf/Proyecto%20de%20Microcontroladores.zip?dl=0
  • Código:
#include <sistemaderiego.h>
#define LCD_ENABLE_PIN PIN_D3
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
int i,flag, cont,dato[8],leds[8],tt=0,lola=1;
int music[8]={00,0b01111,0b01001,0b01001,0b11011,0b11011,00};
float valor,valorn;
#include <lcd.c>

#define nDO     0    // DO
#define nDO_    1    // DO#
#define nRE     2    // RE
#define nRE_    3    // RE#
#define nMI     4    // MI
#define nFA     5    // FA
#define nFA_    6    // FA#
#define nSOL    7    // SOL
#define nSOL_   8    // SOL#
#define nLA     9    // LA
#define nLA_    10   // LA#
#define nSI     11   // SI
#define Speaker   PIN_B2      // Altavoz conectado a RB2
#define valvula   PIN_C0     //activo bomba

int16 FreqNota[12]={// retardos entre estado alto y bajo para generar las notas                        
15289, // DO
14430, // DO#
13620, // RE
12856, // RE#
12134, // MI
11453, // FA
10810, // FA#
10204, // SOL
9631,  // SOL#
9090,  // LA
8580,  // LA#
8099   // SI
};

//-------------------------------------------------Función de audio
void Play(int nota, int octava, int16 duracion){
 int16 fn;

 int16 mS_Transcurridos=0;  // Contadores necesarios
                            // para controlar la duración
 int16 CiclosL=0;           // Contandor de uS

 fn=FreqNota[nota];         // Define los retardos para generar
                            // la frecuencia de cada nota
 fn>>=(octava);             // Adapta la frecuencia a la octava actual
                            // haciendo una rotación
                            // a la derecha por octava
do{

    output_high(Speaker);   // Genera la frecuencia
    delay_us(fn);           // con los retardos mientras
    CiclosL+=(fn);          // aumenta el contador de
                            // ciclos transcurridos
    output_low(Speaker);    // en dos partes para repartir el
    delay_us(fn);           // trabajo entre estado alto y bajo.
    CiclosL+=(fn);          //
    CiclosL+=25;            // Compensador.

    while(CiclosL>999){     // Se queda en el bucle mientras CiclosL
                            // sea menor a 1000 (1 mS)
       CiclosL-=1000;       // Le resta 1000 a CiclosL
       mS_Transcurridos++;  // y le suma 1 a mS_Transcurridos.
       CiclosL+=25;         // Compensador.
    }
 }while (duracion>mS_Transcurridos); // Repite el bucle hasta que haya
                                     // pasado el tiempo indicado.
}

void playcancion(){  //city of stars
        for(i=0;i<2;i++){
        play (nSOL   ,4,250);
        play (nLA   ,4,250);
        play (nSI   ,4,250);
        play (nRE   ,5,1250);
        delay_ms(125);
        play (nRE   ,5,125);
        play (nMI   ,5,250);
        play (nFA   ,5,250);
        play (nRE   ,5,250);
        play (nMI   ,5,250);
        play (nDO   ,5,250);
        play (nRE   ,5,250);
        play (nLA   ,4,1300);
        delay_ms(250);}
        delay_ms(250);
        play (nLA   ,4,500);
        play (nSI   ,4,1000);
        delay_ms(250);
        play (nRE   ,5,125);
        play (nDO   ,5,250);
        play (nRE   ,5,250);
        play (nDO   ,5,250);
        play (nRE   ,5,250);
        play (nDO   ,5,250);
        play (nRE   ,5,250);
        play (nLA   ,4,750);
        play (nLA   ,4,125);
        play (nLA   ,4,125);
        play (nLA   ,4,500);
        play (nLA   ,4,750);
        delay_ms(250);
        play (nSOL   ,5,500);
        play (nSOL   ,5,1000);
        play (nRE   ,5,1000);
        play (nMI   ,5,1300);
        delay_ms(250);
        play (nDO   ,5,125);
        play (nRE   ,5,250);
        play (nSOL   ,5,250);
        play (nFA   ,5,500);
        play (nMI   ,5,500);
        play (nRE   ,5,1000);}

void playcancion2(){  //yesterday
        play (nSOL   ,4,250);
        play (nFA   ,4,250);
        play (nFA   ,4,1200);
        delay_ms(250);
        play (nLA   ,4,250);
        play (nSI   ,4,250);
        play (nDO_   ,4,250);
        play (nRE   ,5,250);
        play (nMI   ,5,250);
        play (nFA   ,5,250);
        play (nMI   ,5,500);
        play (nRE   ,5,250);
        play (nRE   ,5,1200);
        delay_ms(250);
        for(i=1;i<2;i++){
        play (nRE   ,5,250);
        play (nRE   ,5,250);
        play (nDO   ,5,250);
        play (nSI   ,4,250);
        play (nLA   ,4,250);
        play (nSOL   ,4,250);
        play (nLA   ,4,500);
        play (nLA   ,4,250);
        play (nLA   ,4,250);
        play (nLA   ,4,750);
        play (nSOL   ,4,500);
        play (nFA   ,4,500);
        play (nLA   ,4,250);
        play (nSOL   ,4,750);
        delay_ms(250);
        play (nRE   ,4,125);
        play (nFA   ,4,500);
        play (nLA   ,4,250);
        play (nLA   ,4,250);
        play (nLA   ,4,750);
        delay_ms(250);
        play (nSOL   ,4,250);
        play (nFA   ,4,1400);
        delay_ms(250);
        play (nLA   ,4,250);
        play (nSI   ,4,250);
        play (nDO_   ,5,250);
        play (nRE   ,5,250);
        play (nMI   ,5,250);
        play (nFA   ,5,250);
        play (nMI   ,5,500);
        play (nRE   ,5,250);
        play (nRE   ,5,1250);
        delay_ms(250);}
        play (nLA   ,4,1000);
        play (nLA   ,4,1000);
        play (nRE   ,5,1000);
        play (nMI   ,5,1000);
        play (nFA   ,5,1000);
        play (nMI   ,5,250);
        play (nRE   ,5,250);
        play (nMI   ,5,1400);
        play (nRE   ,5,125);
        play (nDO   ,5,500);
        play (nRE   ,5,1000);
        play (nLA   ,4,1400);
        delay_ms(250);
        play (nLA   ,4,1000);
        play (nLA   ,4,1000);
        play (nRE   ,5,500);
        play (nMI   ,5,500);
        play (nFA   ,5,500);
        play (nMI   ,5,250);
        play (nRE   ,5,250);
        play (nMI   ,5,750);
        play (nRE   ,5,125);
        play (nDO   ,5,500);
        play (nRE   ,5,500);
        play (nLA   ,4,1400);
        play (nLA   ,4,250);
        play (nSI   ,4,250);
        play (nDO   ,5,250);
        play (nRE   ,5,250);
        play (nMI   ,5,250);
        play (nFA   ,5,250);
        play (nMI   ,5,200);
        play (nRE   ,5,250);
        play (nRE   ,5,750);
        play (nRE   ,5,750);
        delay_ms(250);
        play (nRE   ,5,250);
        play (nRE   ,5,250);
        play (nDO   ,5,250);
        play (nSI   ,4,250);
        play (nLA   ,4,250);
        play (nSOL   ,4,250);
        play (nSI   ,4,500);
        play (nLA   ,4,250);
        play (nLA   ,4,700);
        play (nSOL   ,4,500);
        play (nFA   ,4,500);
        play (nLA   ,4,250);
        play (nSOL   ,4,800);
        play (nRE   ,4,500);
        play (nFA   ,4,500);
        play (nLA   ,4,250);
        play (nLA   ,4,700);
        delay_ms(250);
        play (nFA   ,4,500);
        play (nLA   ,4,500);
        play (nSOL   ,4,500);
        play (nRE   ,4,500);
        play (nFA   ,4,500);
        play (nLA   ,4,500);
        play (nLA   ,4,1400);}

void playcancion3(){ //Himno de la alegria
   play (nSI   ,5,500);
   play (nDO_   ,6,250);
   play (nRE_   ,6,250);
   play (nRE_   ,6,250);
   play (nDO_   ,6,250);
   play (nSI   ,5,250);
   play (nLA_   ,5,250);
   play (nSOL_   ,5,250);
   play (nSOL_   ,5,250);
   play (nLA_   ,5,250);
   play (nSI   ,5,250);
   play (nSI   ,5,400);
   play (nLA_   ,5,125);
   play (nLA_   ,5,500);
   play (nSI   ,5,500);
   play (nDO_   ,6,250);
   play (nRE_   ,6,250);
   play (nRE_   ,6,250);
   play (nDO_   ,6,250);
   play (nSI   ,5,250);
   play (nLA_   ,5,250);
   play (nSOL_   ,5,250);
   play (nSOL_   ,5,250);
   play (nLA_   ,5,250);
   play (nSI   ,5,250);
   play (nLA_   ,5,400);
   play (nSOL_   ,5,125);
   play (nSOL_   ,5,500);
   play (nLA_   ,5,500);
   play (nSI   ,5,250);
   play (nSOL_   ,5,250); 
   play (nLA_   ,5,250);
   play (nSI   ,5,125);
   play (nDO_   ,6,125);
   play (nSI   ,5,125);
   play (nSOL_   ,5,250);
   play (nLA_   ,5,250);
   play (nSI   ,5,125);
   play (nDO_   ,6,125);
   play (nSI   ,5,125);
   play (nLA_   ,5,250);
   play (nSOL_   ,5,250);
   play (nLA_   ,5,250);
   play (nRE_   ,5,500);
   play (nSI   ,5,500);
   play (nDO_   ,6,250);
   play (nRE_   ,6,250);
   play (nRE_   ,6,250);
   play (nDO_   ,6,250);
   play (nSI   ,5,250);
   play (nLA_   ,5,250);
   play (nSOL_   ,5,250);
   play (nSOL_   ,5,250);
   play (nLA_   ,5,250);
   play (nSI   ,5,250);
   play (nLA_   ,5,400);
   play (nSOL_   ,5,125);
   play (nSOL_   ,5,250);
}

//----------------------------------------------FUNCION PRINCIPAL
void main()
{
   setup_adc_ports(AN0_TO_AN1);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   lcd_init();
   lcd_set_cgram_char(1,music);
  
   //-----------------------------------------------------------------------------------CONTORL USB
   /*usb_init();
   usb_wait_for_enumeration();//espera a que la pc enumere al pic (asigna posicion */
  
   lcd_gotoxy(1,1);
   lcd_putc("Hola, se activo");
   lcd_gotoxy(1,2);
   lcd_putc("control nocturno");
   delay_ms(3000);
   lcd_putc("\f");
   flag=1;
   cont=10;
       
   //-----------------------CONTROL NOCTURNO verificando si es noche o dia
   while(TRUE)
   {      
    //--------------------------------------------PARA USAR USB LABVIEW
    /*usb_task();
         
   while(input(PIN_B4) && lola==1){
      lcd_putc("\f");
      lcd_gotoxy(5,1);
      lcd_putc("Labview");
      lcd_gotoxy(5,2);
      lcd_putc("activado");
      if (usb_kbhit(1))//siempre va a ser 1 por que es un solo pic el end point verifica el canal
       {
      usb_get_packet(1, dato,8);
      dato[0]=dato[0]-0x30;
      output_c(dato[0]);
      }

      leds[0]=read_adc();
      leds[1]=pin_C0;
      leds[2]=pin_B1;
      usb_put_packet(1, leds, 3, USB_DTS_TOGGLE);
      delay_ms(20);
     
      if(!input(PIN_B4))
         lola=0;
   }*/
  
      //-----------------------------------------------------------------PARTE DE PROYECTO NORMAL
      do{
   valor=read_adc();
   valorn=((5*valor)/1023);
      
   if(valorn>3.5)
        cont=10;
  
   while(valorn>3.5 && input(PIN_B1) && tt==0){  //PIN_B1 Flotador   
      lcd_putc("\f");
      lcd_gotoxy(7,1);
      lcd_putc("Riego");
      lcd_gotoxy(5,2);
      lcd_putc("activado");
      delay_ms(2000);
      output_HIGH(valvula);  //--------------------Encender bomba       
      delay_ms(20);
      lcd_putc("\f");
      lcd_gotoxy(5,1);
      lcd_putc("Bomba ON");
      delay_ms(16000);
      lcd_putc("\f");
      lcd_gotoxy(5,1);
      output_LOW(valvula);
      lcd_putc("Bomba OFF");
      delay_ms(5000);
      tt=1;
      }
   
    while(!input(PIN_B1)){ 
      lcd_putc("\f");
      lcd_gotoxy(7,1);
      lcd_putc("Agua");
      lcd_gotoxy(5,2);
      lcd_putc("insuficiente"); 
      delay_ms(3000);
      cont==0;
      if(input(PIN_B1)){
      lcd_putc("\f");
      lcd_gotoxy(7,1);
      lcd_putc("Agua");
      lcd_gotoxy(5,2);
      lcd_putc("suficiente");
      delay_ms(2000);
      break;}
     
    }
   
    if(valorn<3.5){ //---------de dia poner canciones
      delay_ms(10);
      lcd_putc("\f");
      lcd_gotoxy(7,1);
      lcd_putc("Riego");
      lcd_gotoxy(4,2);
      lcd_putc("Desactivado");
      delay_ms(3000);
      output_LOW(valvula);
      flag=0;
      lcd_putc("\f");
      lcd_gotoxy(1,1);//---------City of stars
      lcd_putc("Reproduciendo...");
      lcd_gotoxy(1,2);  lcd_putc(1);
      lcd_gotoxy(3,2);
      lcd_putc("City of stars");
      lcd_gotoxy(16,2); lcd_putc(1);
      playcancion();
      delay_ms(3000);
      lcd_putc("\f");//---------Yesterday
      lcd_gotoxy(1,1);
      lcd_putc("Reproduciendo...");
      lcd_gotoxy(1,2);  lcd_putc(1);
      lcd_gotoxy(3,2);
      lcd_putc("Yesterday");
      lcd_gotoxy(13,2); lcd_putc(1);
      playcancion2();
      delay_ms(3000);
      lcd_putc("\f");//---------Himno de la alegria
      lcd_gotoxy(1,1);
      lcd_putc("Reproduciendo...");
      lcd_gotoxy(1,2); lcd_putc(1);
      lcd_gotoxy(2,2);
      lcd_putc("Himno alegria");
      lcd_gotoxy(16,2); lcd_putc(1);
      playcancion3();
      delay_ms(3000);}

   }while(flag=1);
 
   }

}


  • Visualización en Labview:



  • Simulación en Proteus:


  • Armado en físico:


MASTER Y ESCLAVO EN PIC

Este programa contiene el código del master y un esclavo. Se debe disponer de 2 PIC's, los cuales, están conectados a través del protocolo SPI y se enviarán valores del potenciómetro.
  • Código del Master:
#include <clase14.h>
//SPI MASTER
#use spi (MASTER, SPI1, MODE=0, BITS=8, STREAM=SPI_1)
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
int valor;
void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("Susana master");
   lcd_gotoxy(1,2);
   lcd_putc("valor=");
  
   while(TRUE)
   {
      valor=read_adc();
      lcd_gotoxy(9,2);
      printf(lcd_putc,"%X",valor);
      output_toggle(PIN_B4);
      delay_ms(100);     
      SPI_WRITE(valor);
   }
}

  • Código del esclavo:
#include <slave.h>
//SPI slave, el slave es como una impresora a un computadora, varias compus a una principal
#use spi (SLAVE, SPI1, MODE=0, BITS=8, STREAM=SPI_1)
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
int valor;
#INT_SSP
void  SSP_isr(void) //interrupcion SPI
{
   valor=spi_read();
   lcd_gotoxy(9,2);
   printf(lcd_putc,"%X",valor);
}
void main()
{
   //la interrupcion es cuando master manda un dato, se interrumpe el toggle
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   lcd_init();
   lcd_putc("Susana slave");
   lcd_gotoxy(1,2);
   lcd_putc("Valor=");
  
   while(TRUE)
   {
      output_toggle(PIN_A5); //para este entretenido el programa y se interumpa
     
   }
}

  • Simulación en Proteus:

DECODIFICADOR DE PULSOS DE CUADRATURA (QEP)

Este programa puede aplicarse a un odómetro, el cual calcula la distancia total o parcial recorrida por un objeto o cosa. El odómetro se armará en parejas y el programa mostrará en centímetros la distancia recorrida en sentido recto y de reversa.
  • Código:
#include <pasos.h>
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
float cuenta=0;
float cm;
#INT_EXT

void  EXT_isr(void)
{
   if (input(PIN_B1)) //reversa
     cuenta=cuenta-1;
  
   else           //B0, directo
      cuenta=cuenta+1;

   cm=(cuenta*1.2)/2;
   lcd_gotoxy(5,2);
   printf(lcd_putc,"%3.1f",cm);
}

void main()
{
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("Susi y Marco");
   lcd_gotoxy(1,2);
   lcd_putc("Cm= ");

   while(TRUE)
   {
     if (input(PIN_B2)) //reset
         cuenta=0;  
   }

}

  • Simulación en Proteus:
  • Armado y ejecución:




CONTROL DE MOTOR CD CON PWM

Este programa puede variar la velocidad de un motor cd con el PWM del PIC, además de que se puede seleccionar el sentido de giro de éste. Para poder dar la intensidad al motor para que funcione se empleará un puente H, para esta práctica, el puente H se hará con transistores Darlington (TIP122 y TIP127).

  • Código:
#include <clase12.h>
//motor CD con PWM
int16 vel;

void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   setup_timer_2(T2_DIV_BY_4,124,1);      //500 us overflow, 500 us interrupt
   setup_ccp1(CCP_PWM|CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
   set_pwm1_duty((int16)248);

   while(TRUE)
   {
      vel=(int16)(read_adc());
      set_pwm1_duty(vel);
      if(input(PIN_B0))
          setup_ccp1(CCP_PWM|CCP_PWM_FULL_BRIDGE); //CW clock wise
      else
         setup_ccp1(CCP_PWM|CCP_PWM_FULL_BRIDGE_REV); //CCW clock contrary wise
         
     
   }

}
  • Simulación en Proteus:
  • Armado y ejecución:


COMUNICACIÓN INFRARROJA



Este programa que pueda realizar una comunicación infrarroja empleando la codificación Manchester.

Además de que se requiere de haya un emisor y un receptor. En esta ocación yo seré el receptor y un compañero será el emisor. Se emplearán un LED infrarrojo y un módulo receptor que pueda modular la señal.
  • Código del receptor:
#include <receptor.h>
//recibe
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
int tecla,i;
#INT_EXT
void  EXT_isr(void) //interrupt service request
{
   delay_us(300); //para estar a la mitad del dato
   output_toggle(Pin_B5);//ve muestreo
   output_toggle(Pin_B5);
   if(!input(PIN_B0))
   {  delay_us(1200);
      for(i=0;i<=7;i++)
      {
         if(!input(PIN_B0))  
            bit_clear(tecla,i); //el 0 de la tecla lo pone en 0
         else 
            bit_set(tecla,i); //el 1 de la tecla lo pone en 1
         output_toggle(Pin_B5);
         output_toggle(Pin_B5);
         delay_us(1200);
        
      }
      if(input(Pin_B0)) tecla='N';//de que no es numero, si es basura muestra N
      lcd_gotoxy(10,2);
      lcd_putc(tecla);
   }
}
void main()
{
   enable_interrupts(INT_EXT);
   ext_int_edge( H_TO_L ); // detecta flancos de bajada
   enable_interrupts(GLOBAL);
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("SUSANA");
   lcd_gotoxy(1,2);
   lcd_putc("Tecla RX= ");
   while(TRUE)
   {
      output_toggle(Pin_B7);//para dejar espacio a la interrupción
   }
}
  • Código del emisor:
#include <clase11.h>
//transmite
#include <KBD.C>
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
int tecla, i, j;
void cero()
{
   //se modula a 600 us, entonces si fsk=38KHz, 600/26 = 23 pulsos
   for (i=0;i<=23;i++)
   {
      output_high(Pin_B0);
      delay_us(10);
      output_low(Pin_B0);
      delay_us(7);
   }
   delay_us(580);
}
void main()
{
   kbd_init();
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("SUSANA");
   lcd_gotoxy(1,2);
   lcd_putc("Dato TX= ");
   while(TRUE)
   {
      while (tecla=='\0')
         tecla= kbd_getc();
        
      lcd_gotoxy(1,2);
      lcd_putc("Dato TX= ");
      lcd_putc(tecla);
      cero();
     
      for(j=0;j<=7;j++)
      {
         if(bit_test(tecla,j))//ve que bit hay TRUE si es 1, FALSE si es 0
            delay_us(1200);
         else
            cero();
      }  
         cero();
         tecla='\0';
      }  
}

  • Simulación en Proteus:
  • Armado y ejecución:


EEPROM

Este programa puede escribir y leer registros en la memoria EEPROM. Los datos serán ingresados mediante el teclado, donde la tecla de # se encarga de escribir el dato en el registro, y la tecla * se encarga de la lectura del dato que haya en el registro ingresado.
  • Código:
#include <clase10.h>
#include <KBD.C>
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
#include <string.h>
#include <stdlib.h>
int tecla, i,dato[4],dir[4];
char a[1],b[1],c[1];
void main()
{
   kbd_init();
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("Susana Lopez");
   lcd_gotoxy(1,2);
   lcd_putc("A="); //numero de registro
   lcd_gotoxy(8,2);
   lcd_putc("D=");   //dato que esta en el registro
   tecla='\0';
   //prueba
   //dir[3]=125;
   //dato[3]=0x18;
  
   while(TRUE)
   {
      while(tecla=='\0')
            tecla=kbd_getc();
      if (tecla!='#' && tecla!='*')
      {for (i=0;i<=2;i++)
      {
         while(tecla=='\0')
            tecla=kbd_getc();
           
        lcd_gotoxy(i+3,2);
        lcd_putc(tecla); 
        dir[i]=tecla-48; //para que el vector sea un numero de mas de 1 cifra
        tecla='\0';
      }
     
      sprintf(a,"%d",dir[0]);
      sprintf(b,"%d",dir[1]);
      sprintf(c,"%d",dir[2]);
      strcat(a,b);
      dir[3]=atoi(a);
      /*
      lcd_gotoxy(14,2);
      printf(lcd_putc,"%d",dir[3]);*/
     
      while(tecla=='\0')
            tecla=kbd_getc();
      if (tecla!='#' && tecla!='*')
      {
      for (i=0;i<=2;i++)
      {
         while(tecla=='\0')
            tecla=kbd_getc();
           
        lcd_gotoxy(i+10,2);
        lcd_putc(tecla); 
        dato[i]=tecla-48;
       
        tecla='\0';
      }
      }}
      sprintf(a,"%d",dato[0]);
      sprintf(b,"%d",dato[1]);
      sprintf(c,"%d",dato[2]);
      strcat(a,b);
      dato[3]=atoi(a);
      /*prueba
      lcd_gotoxy(14,1);
      printf(lcd_putc,"%d",dato[3]);*/
 
     
      while(tecla=='\0')
            tecla=kbd_getc();
      if (tecla=='*')
      {
        dato[3]=read_EEPROM(dir[3]); //lee el dato especificado en dir pos 3
        lcd_gotoxy(10,2);
        printf(lcd_putc,"%3X",dato[3]); //imprime valor en hexadecimal
        tecla='\0';
      }
     
      if (tecla=='#')
      {
        dato[3]=write_EEPROM(dir[3],dato[3]); //escribe el dato en direccion indicada (direccion, dato)
        tecla='\0';
      }
     
   }
}

  • Simulación en Proteus:
  • Armado y ejecución:

“En el registro 010 se escribió el dato 052.”

COMUNICACIÓN SERIAL


Este programa puede enviar un PIC un dato y que se puede recibir en otro PIC, mediante comunicación serial RS-232, donde la conexión de la comunicación se hará con un cable de par trenzado.

Deben estar sincronizados los tiempos, por eso se emplea el uso del cristal de 4 MHz, el cual se conecta al pin 13 y 14 del PIC. Además, para poder visualizar como se ve el dato que se manda de un PIC a otro, se emplea un osciloscopio, configurándolo en el menú de trigger, para poder ver el disparo del dato.

  • Código:
#include <nueve.h>
#include <KBD.C>
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>

int tecla;
#INT_RDA
void  RDA_isr(void)
{
   tecla=getc();
   lcd_gotoxy(9,2);
   lcd_putc("RX=");
   lcd_putc(tecla);
}
void main()
{
   kbd_init();
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("Susana");

   while(TRUE)
   {
        while (tecla=='\0')
         tecla= kbd_getc();
         lcd_gotoxy(1,2);
         lcd_putc("TX=");
         lcd_putc(tecla);
         putc(tecla);
         tecla='\0';
      }
}

  • Simulación en Proteus:
  • Armado y ejecución:


OHMETRO EN LCD

Este programa puede mostrar el efecto de un carácter comiéndose letras de un nombre y después regresarlas, además de que se pudiera visualizar caracteres inventados, con la ayuda de la matriz de 5x8 que tienen los LCD.

Además de que en la segunda línea se puede ver la medición de valores de resistencia mediante un óhmetro, el cual tiene entrada en el canal AN0. El valor de la resistencia se verá variado mediante un potenciómetro de 10 k.
  • Código:
#include <clase7.h>
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
//int flecha[8]={0x04,0x0E,0x1F,0x04,0x04,0x04,0x04,00}; //posiciones en matriz de 5x8
int ch[8]={0b01110,27,28,25,31,14,0};
int ch1[8]={14,27,31,30,31,31,14,0};
int mickey[8]={0b11011,0b11011,0b01110,0b01110,00,00,00,00};
int pacmane[8]={0b01110,0b11011,0b01111,31,31,0b01110,00};
int pacmanr[8]={0b01110,0b11011,0b00111,0b10011,31,0b01110,00};
int music[8]={00,0b01111,0b01001,0b01001,0b11011,0b11011,00};
int i,j;
char nombre[16]="  Susana Lopez  ";
void main()
{
   lcd_init();
   //lcd_set_cgram_char(0,flecha);  //(w,p) w=posicion de RAM, p=nomre de dato
   lcd_set_cgram_char(0,ch);
   lcd_set_cgram_char(1,ch1);
   lcd_set_cgram_char(2,mickey);
   lcd_set_cgram_char(3,pacmane);
   lcd_set_cgram_char(4,pacmanr);
   lcd_set_cgram_char(5,music);
   lcd_gotoxy(3,1);
   lcd_putc("Susana Lopez");
   delay_ms(1000);
   //lcd_putc(0); //imprimira flecha 
   //ciclo de un pacman comiendose las letras
   for(i=1;i<=16;i++)
     {
        lcd_gotoxy(i,1);
        lcd_putc(0);
        delay_ms(200);
        lcd_gotoxy(i,1);
        lcd_putc(1);
        delay_ms(200);
        lcd_gotoxy(i,1);
        lcd_putc(' ');
     }
  
   for(j=16;j>=2;j--)
   {
      lcd_gotoxy(j,1);
      lcd_putc(4);
      printf(lcd_putc,("%c"),nombre[j]);
      delay_ms(200);
      lcd_gotoxy(j,1);
      lcd_putc(3);
      delay_ms(200);
      lcd_gotoxy(j,1);
      lcd_putc(' ');
   }
  
   lcd_gotoxy(1,1);
   lcd_putc(2);
   lcd_gotoxy(16,1);
   lcd_putc(5);
  
}

  • Simulación en Proteus:

  • Armado y ejecución:


ADC, PWM con AC en LCD

Este programa puede además de medir el voltaje de corriente alterna, puede variar el PWM generado por el PIC, el cual se puede ver su variación mediante el uso del osciloscopio.
Para poder medir la corriente alterna sin que se queme el PIC se emplea un circuito externo, para que pueda rectificar la corriente y poder bajarla a 5 volts, mediante un divisor de voltaje. Para el uso del PWM, el cual lo que hace es generar una señal cuadrada, la cual se puede variar para dejar en ciertos tiempos los ciclos de trabajo, ya sea en ON o en OFF.

  • Código:
#include <clase6.h>
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7

#include <lcd.c>
#include <math.h>

float valor,max2,max=0,vol=0; 
float valorp,valorpw;
int i;

void main()
{
   setup_adc_ports(AN0_TO_AN1);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //32.7 ms overflow
   setup_timer_2(T2_DIV_BY_16,249,1);      //2.0 ms overflow, 2.0 ms interrupt, frec. 500Hz

   setup_ccp1(CCP_PWM|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
   //pulse width modulation, envia información de manera analogica
   set_pwm1_duty((int16)498); //configura el pwm, puede ser de 10bits (0-1023), en este caso hara de (0-996)
 
   lcd_init();
   lcd_gotoxy(13,1);
   lcd_putc('M');
   lcd_putc('S');
   lcd_putc('L');
   lcd_putc('A');

   while(TRUE)
   {
      set_adc_channel(0);
      delay_us(10);
                  
     //visualizacion del voltaje AC
     for (i=0;i<50;i++)
     {
       valor=read_adc();
       vol+=valor;
       delay_ms(20);
     }

      vol=vol/50; //para conversion VCA
      lcd_gotoxy(1,1);
      max2=(20*vol)/1023 ;
      printf(LCD_PUTC, "volts=%0.2g", max2); //voltaje
   
      lcd_gotoxy(1,2);
      set_adc_channel(1);
      delay_us(10);
   
    //visualizacion % del pwm
    for (i=0;i<50;i++)
     {
      valorpw=read_adc();
      //if(valorpw>max)
       max+=valorpw;
         delay_ms(20);
     }
          
      max=max/10; //para calculos del PWM
      valorp=((996*max)/1023);
    
      //printf(LCD_PUTC, "VAC=%0.3g ",max/10);
     
     
      set_pwm1_duty((int16)valorpw);
     
      printf(LCD_PUTC, "%%PWM=%0.2g",(valorp/50)-10.67); //PWM
      lcd_gotoxy(10,2);
     
      //printf(LCD_PUTC, "VA=%0.2g",max2); //Volt AC
      //max=0;
   
   }

}

  • Simulación en Proteus:


  • Armado y ejecución:


ADC y LCD en ‘C’



Este programa puede mostrar en un display LCD el valor del voltaje medido mediante el periférico ADC que tiene el PIC18F4550.
  • Código:
#include <clase5.h>
//incluye los pines del LCD
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>  //incializa el LCD, ver arcvhi lcd.c para comandos para usar LCD
float valor;  //ocupa 2 byte
float valorn;
void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   lcd_init(); //iniciar lcd
   //los comandos ya hacen los tiempos por la funcion
   lcd_gotoxy(7,1); //cursor se posiciona en col 5 linea 1
   lcd_putc('M'); //envia caracter M al LCD
   lcd_putc('S');
   lcd_putc('L');
   lcd_putc('A');
  
   //lcd_set_cgram_char(0,mi);   comando para caracter
   while(TRUE)
   {
      valor=read_adc(); //lectura al adc, lectura canal 0, valores del 000 al 3FF
      //buscar en built in fuctions printf
      //para mostrar un valor con formato en especifico
      valorn=((5*valor)/1023);
      lcd_gotoxy(3,2);
      //ejemplo para que ponga: valor=0033
      printf(LCD_PUTC, "volts=%0.3g", valorn); //mostrara el valor con 4 cifras en hexadecial 
      //lcd_gotoxy(1,1);
      //printf(lcd_putc,"%c",0);    instrucciones para imprimir caracter
      //delay_ms(5000);
     
   }
}

  • Simulación en proteus:

  • Armado y ejecución:


DISPLAY LCD


Este programa que pueda mostrar un mensaje en un display LCD. Para poder usar el LCD fue necesario realizar unas configuraciones para poder empezar a mandar mensajes a éste para y para que se pudieran visualizar.

Las configuraciones necesarias de tiempos y de valores iniciales se pueden encontrar en el datasheet del LCD. Por medio de funciones se puede programar fácilmente los tiempos, además de que el mensaje o las letras que se quieran mandar al LCD no tienen por qué ponerse en su valor hexadecimal, simplemente se pone entre comillas simple.
  • Código:
#include <clase4.h>
//procedimiento de flanco de bajada
#include <lcd.c>
int mi[8]={
               0b11011,
               0b11011,
               0b01110,
               0b01110,
               0b00100,
               0b01110,
               0b01110,
               0b00000
           };
void main()
{
   lcd_init();
  
  
   lcd_set_cgram_char(0, mi);
   lcd_set_cgram_char(1, mi);
   lcd_set_cgram_char(2, mi);
   lcd_set_cgram_char(3, mi);
   lcd_set_cgram_char(4, mi);
   lcd_set_cgram_char(5, mi);
   lcd_set_cgram_char(6, mi);
   lcd_set_cgram_char(7, mi);
   lcd_set_cgram_char(8, mi);
   lcd_gotoxy(2,1);
   lcd_putc("m");
  
   while(TRUE)
   {
      lcd_gotoxy(2,1);
     
     
    lcd_putc("m");
      //las letras van a parpadear
     // output_bit(PIN_C0, 0); //RS=0  write command
      //output_D(0x08);    
      //pulso();
      //delay_ms(300);
      //output_D(0x0C);     
      //pulso();
      //delay_ms(300);
     
   }
}

  • Simulación en Proteus:

  • Armado y ejecución:


CONVERTIDOR ANALOG-DIGITAL (EN LENGUAJE ENSAMBLADOR)



Es un programa que por medio de los pines A/D (análogo digital) se pueda leer señales analógicas y poder mostrarlas en forma digital (por medio de los displays).

Todo esto mediante el uso del módulo conversor de analógico a digital (A/D), el cual tiene 13 entradas en los PIC de 40/44 pines. Este módulo permite la conversión de una señal de entrada analógica a un número digital de 10 bits.
  • Código:
#include <clase3.h>
#define Dir_C 0xF94
#define Dir_D 0xF95
#define Puerto_C 0xF82
#define Puerto_D 0xF83
#define T0CON 0xFD5     //REGISTRO DE CONTROL DEL TIMER
#define TMR0 0xFD6      //REGISTRO DE CONTROL DEL TMR0
#define PRODL 0xFF3     //REGISTRO DEL MULTIPLICADOR
#define PCL 0xFF9     //REGISTRO BAJO DEL CONTADOR DE PROGRAMA
#define ADCON2 0xFC0 
#define ADCON1 0xFC1    //REGISTROS del ADC
#define ADCON0 0xFC2
#define ADRESH 0xFC4

int temp;
void main()
{
#asm
   inicio:
            movlw    0x00
            movwf    Dir_C    //configurado como salida
            movlw    0x00
            movwf    Dir_D    //configurado como salida
            movlw    0x01
            movwf    ADCON0  //ADCON0 <- 01 se activa el ADC
            movlw    0x0E  
            movwf    ADCON1  //ADCON1 <- 01 se configura AN0 como analogica
            movlw    0x07
            movwf    ADCON2  //justificación (izquierda o derecha) y reloj
                   
   
      ciclo:
         ADC:
            bsf      ADCON0, 1  //GO=1
            btfsc    ADCON0, 1   //hace la pregunta de si ADCON0 es un 1, si es uno se brinca la linea
            bra      ADC
    
            bsf      Puerto_C, 1
            movf     ADRESH, 0
            andlw    0x0F 
            call     display
            movwf    Puerto_D
            bcf      Puerto_C, 0
            call     tiempo
            swapf    ADRESH, 0  
            andlw    0x0F
            call     display
            bsf      Puerto_C,0
            movwf    Puerto_D
            bcf      Puerto_C, 1
            call     tiempo
            bra      ciclo   
  
   display:
            mullw    0x02    
            movf     PRODL,0 
            addwf    PCL     
            retlw    0x40  //CERO
            retlw    0x79  //UNO
            retlw    0x24  //DOS
            retlw    0x30  //TRES
            retlw    0x19  //CUATRO
            retlw    0x12  //CINCO
            retlw    0x02  //SEIS
            retlw    0x78  //SIETE
            retlw    0x00  //OCHO
            retlw    0x18  //NUEVE
            retlw    0x08  // A
            retlw    0x03  // B
            retlw    0x46  // C
            retlw    0x21  // D
            retlw    0x06  // E
            retlw    0x0E  // F     
           
   tiempo:
            decfsz   temp
            bra      tiempo
            retlw    0
  #endasm
}


  • Simulación en Proteus:

  • Armado y ejecución:

CONTADOR (EN LENGUAJE ENSAMBLADOR)

El programa es capaz de contar los pulsos que le lleguen al pin 6 (donde se encuentra el timer0 external clock input).  Además de que se pueda visualizar el conteo por medio de dos displays, los cuales se verá el conteo desde 00 hasta FF.
  • Código:
#include <clase2.h>
#define Dir_C 0xF94
#define Dir_D 0xF95
#define Puerto_C 0xF82
#define Puerto_D 0xF83
#define T0CON 0xFD5     //REGISTRO DE CONTROL DEL TIMER  para configurar timer0
#define TMR0 0xFD6      //REGISTRO DE CONTROL DEL TMR0 
#define PRODL 0xFF3     //REGISTRO DEL MULTIPLICADOR
#define PCL 0xFF9     //REGISTRO BAJO DEL CONTADOR DE PROGRAMA
int temp;

void main()
{
#asm
   inicio:
         movlw    0x00 //a {w}<-0
         movwf    Dir_C //(TRISC)<-{w} configuramos como salida
         movlw    0x00 //dato
         movwf    Dir_D // (TRISD)<-{w} conf como salida
         //para config el timer0 CON ver pag. 127 del manual = E8
         movlw    0xE8
         movwf    T0CON //conf timer0 como contador de 8 bits
        
   ciclo:
            //para utilidad de ejemplo se quiere mostrar la explicacion para que los 2 displays muestren A5
            //el timer en RA4 se le dran pulsos y contara de 00 a FF
            //se debe partir en 2
            bsf      Puerto_C, 1 //bit set file RC1=1, pone a ese pin en 1, despues de la coma va el # de pin
           //display con 02 en hex = 6 decimal
           // movlw    0x02
            //movwf    Puerto_D
            //bcf      Puerto_C, 0 //bit clear file RC0=0, pone a ese pin en 0
            //call     tiempo
            //1° display con 24 en hex = 2 decimal
            //bsf      Puerto_C, 0
            movf     TMR0, 0 //W<- Timer00
            andlw    0x0F  //and    (multiplica para quitar la A y dejar el bit)  w <- w and 0xoF,
            //si queremos un A5, le quitara la A y dejara el 05  (A5*0F)=05
            call     display //llama a display (ver etiqueta de display
            //el puerto D manda dato al display y el puerto C manda voltaje para activar display
            movwf    Puerto_D // ahora vale w=12
            bcf      Puerto_C, 0 //activamos digito y muestra el 5
            call     tiempo
            swapf    TMR0,0   //intercambio, se tenia A5, con swapf da 5A
            andlw    0x0F  // queda 0A
            call     display
            bsf      Puerto_C,0
            movwf    Puerto_D
            bcf      Puerto_C, 1
            call     tiempo
            bra      ciclo   
  
   display:
            //se tiene primero 5
            //luego se tiene la A
            //recordar que el contador de programa va de 2 en 2
            mullw    0x02     //multiplica w por 2,  5*2= 0A
            movf     PRODL,0  //w= 0A el resultado de la multiplicacion se almacena en PRODL
            addwf    PCL      //el contador del programa tiene un num que es 4C
            // se suma lo de w + 4C + 2 = 4C + 0A + 2 = 58, se va al registro 58, en el cual esta retlw con el dato 0x12 = 5 en display
            retlw    0x40  //CERO
            retlw    0x79  //UNO
            retlw    0x24  //DOS
            retlw    0x30  //TRES
            retlw    0x19  //CUATRO
            retlw    0x12  //CINCO
            retlw    0x02  //SEIS
            retlw    0x78  //SIETE
            retlw    0x00  //OCHO
            retlw    0x18  //NUEVE
            retlw    0x08  // A
            retlw    0x03  // B
            retlw    0x46  // C
            retlw    0x21  // D
            retlw    0x06  // E
            retlw    0x0E  // F
           
           
   tiempo:
            decfsz   temp //decfsz ocupa de 2 ciclos
            bra      tiempo
            retlw    0

  #endasm
}

  • Simulación en proteus:

  • Armado y ejecución:

Ultima entrada ingresada

SISTEMA DE RIEGO AUTOMÁTICO CON MÚSICA

El objetivo era hacer un programa que pueda activar una bomba de agua en la noche, y que por las mañanas reproduzca música para las plantas....