Tutorial, enviar comando (para encender/apagar TV LG por ejemplo) a 38kHz

Buenos días, hace ya algunas semanas adquirí un launchpad de texas instruments, en el cual veían 2 mcu (MSP430G2452 y MSP430G2553), tras haber hecho ya algunos ejemplos, quisiera hacer un transmisor de infrarrojos a 38khz con los siguientes requisitos:

* CHIP MSP430G2452
* Uso del DCO interno
* 940nm IR led
* Modular la frecuencia a 38khz para el uso del protocolo NEC, SIN usar timers

**Las referencias que he codigo están adjuntos en el PDF

Ahora Expongo mi codigo y lo que he ido haciendo
Código:
#include <msp430.h>
#include <stdint.h>
#include <delay.h> //Liberia a incluir

//#define CPU_CLOCK 16000000
#define F_CPU 16000000UL

void parpadeoLed();
void generar38khz(int useg);
void enviarTrama(int trama[8]);
void sendNec();

//Hacemos un parpadeo de un led que lo utilizamos para ver si el micro esta
//funcionando, el pin usado es el P2.2
void parpadeoLed(){
	P2DIR |= 0x04;				// Set P2.2 to output direction
    P2OUT ^= 0x04;				// Toggle P2.2 using exclusive-OR
}

//Modulamos una frecuencia de 38khz
void generar38khz(int useg) {
 unsigned int i=0;
 P1DIR = 0x40; //Habilitamos la direccion del pin 1.6

 //Calculamos el numero de pulsos que tenemos que enviar
 //Como unsigned int solo llega hata 65 mil y pico
 // tenemos que operar un poco para no desbordarlo
 useg = useg/10;
 unsigned mult = (useg*38.2); //useg * 38khz
 unsigned res  = (mult/100);

 for(i=0;i<res;i++){
      P1OUT = 0x40;  //Ponemos como salida el pin 1.6 en HIGH
      _delay_us(7);  //Redondeamos el delay de 1/4 del duty_cycle
      P1OUT = 0x00;  //Ponemos como salida el pin 1.6 en LOW
      _delay_us(19); //Redondeamos el delay de 1/4 del duty_cycle
  }


}

void enviarTrama(int trama[8]){
	 unsigned char i = 0;

	    // Recorermos el array verificando si tenemos que enviar un
	    // 0 logico o 1 logico
	    while (i < 8) {

	        // Transmitimos un 1
	        if (trama[i] == 1) {
	            generar38khz(560);
	            _delay_us(1690);
	        }else {
	         // Transmitimos un 0
	            generar38khz(560);
	            _delay_us(560);
	        }

	        i++;
	    }

}

void sendNec(){

	//Segun la teoria del protocolo NEC, primero debemos
	//enviar una cabecera modulada de 9ms + 4.5 de delay
	//un 1 logico son 560 us + 1690 us de delay
	//un 0 logico son 560 us + 560 us de delay
	//Bit de parada 560 us + 4708 us de delay
	//
	//Tambien sabemos que la trama se envía de LSB a MSB
	//Desde el bit menos significativo al mas

	//Mandamos una cabecera, mandamos una direccion y despues un comando

	int addr2[8]  = {0,0,0,0,0,1,0,0}; // => 0x20 = 00100000 -> lo invertimos por LSB a MSB -> 00000100
	int naddr2[8] = {1,1,1,1,1,0,1,1}; //el negado de lo anterior
	int cmd2[8]   = {0,0,0,0,0,0,1,0}; //0x40 -> comando vol_UP
	int ncmd2[8]  = {1,1,1,1,1,1,0,1}; //negado del comando

	//Cabecera
	generar38khz(9000); //PWN 38khz 9ms
	_delay_us(4500); //delay 4.5ms

	//Address
    enviarTrama(addr2); //Trama normal
    enviarTrama(naddr2); //Trama negada

    //Command
    enviarTrama(cmd2); //Trama normal
    enviarTrama(ncmd2); //Trama negada

    //Bit de parada
    generar38khz(560); //bit parada
    _delay_us(4708); //bit parad
}


///FUNCION PRINCIPAL DEL MICRO///////
////////////////////////////////////
int main(void) {
 	WDTCTL = WDTPW +WDTHOLD;                  // Stop Watchdog Timer

      //Calibramos el micro a 16Mhz
	  BCSCTL1 = CALBC1_16MHZ;                   // Set range
	  DCOCTL = CALDCO_16MHZ;                    // Set DCO step + modulation*/

	  //All values to cero as INPUT Pines del P1_0 al P1_6
	  //Pines as INput P2_0 al P2_6
	  P1DIR = 0x00;
	  P2DIR = 0x00;

    	for(;;) { //Bucle infinito
           parpadeoLed();//Parpadeamos el led para saber que el micro está funcionando
           _delay_ms(500);
           sendNec();     //Mandamos un comando NEC
           _delay_ms(500);
    	}
	
}
 

Adjuntos

  • referencias.pdf
    93.6 KB · Visitas: 4
Última edición:
Porque no usas un 555 como oscilador de 38 Khz y manipulas el 555 con el Microcontrolador MSP430?,
Asi de este modo le quitas carga al microcontrolador. Yo lo hice hace mucho con un PIC16 usando el UART a 1200 baud y me funciono de maravilla, lastima que perdi el codigo :cry: ,

Saludos!
 
Ya, con un pic y arduino lo habia conseguido hacer, pero quería probar a usar el msp430 modulando la frecuencia sin timers, para ver como respondía y compararlo con los otros, ya que el voltaje de trabajo es de 1.8 v a 3.3v y eso si es bastante interesante a la hora de hacer proyectos simples
 
Pues no se pero me parece que debajo de los 3V no es recomendable hacer correr el CPU a 16MHz, ¿ya viste la gráfica de voltaje de alimentación vs frecuencia del sistema? pierdes mucha corriente así y aparte puedes comenzar a estar inestable si la pila comienza a descargarse.
 
TUTORIAL ENVIAR COMANDO NEC (PARA ENCENDER/APAGAR TV LG por ejemplo) a 38KHZ
-------------------------------------------------------------------------------------

Requisitos minimos:

* Launchpad MSP430 (contiene 1 MSP430G2553 + 1 MSP430G2452)
* Chip (MCU) MSP430G2553 o MSP430G2452 insertado en el launchpad
* Protoboard
* Cables de conexion hembra-macho y macho-macho
* Transistor 2N2222 (se pueden utilizar otros)
* Leds IR de 940nm
* Uso del Code Composer Studio proporcionado en su web por Texas Instruments

1. Preparación del hardware y conexionado

Con un polímetro medimos el voltaje entre el PIN 2.3 y GND, para saber que voltaje nos proporciona el MCU cuando ponemos dicho pin como salida

Dependiendo del polímetro usado nos dará que el valor es en torno 3.40 V

Con el conexionado de la imagen debemos hacer que entre el PIN2.3 y GND se nos vayan esos 3.40V, de los que el transistor se lleva 0.7 V, y cada led IR 940nm se lleva 1.5, en total:

(1.5V * 2 leds )+ (0,7V * 1 transistor) = 3,7 V

Perdemos un poco de potencia por el camino pero para este ejemplo nos da igual, no hace falta ser muy exactos

Ver imagen eskema1_bb.jpg

2. Programación del MCU con Code Composer Studio

Despues de concectar nuestro launchpad por usb al ordenador (previamente debemos tener algunosde los MCU insertado en el launchpad), copiamos el código que se proporciona aquí y lo programamos

* El código manda el comando VOL_UP a un televisor LG estandar

Código:
#include <msp430.h>
#include <delay.h> //Liberia a incluir

//#define CPU_CLOCK 16000000
#define F_CPU 16000000UL

void generar38khz(int useg);
void enviarTrama(int trama[32]);
void sendNec();

//Modulamos una frecuencia de 38khz
void generar38khz(int useg) {
 unsigned int i=0;
 P2DIR = 0x08; //Habilitamos la direccion del pin 2.3

 //Calculamos el numero de pulsos que tenemos que enviar
  //Como unsigned int solo llega hata 65 mil y pico
  // tenemos que operar un poco para no desbordarlo
  useg = useg/10;
  unsigned mult = (useg*38); //useg * 38khz
  unsigned res  = (mult/100);

  //Lo aconsejable por teoría seria enviar la trama con un duty_cycle de 1/4 pero lo vamos a enviar al 50%
 for(i=0;i<res;i++){ //Desde 0 hasta el numero de pulsos que tenemos que enviar para una onda de 38khz
      P2OUT = 0x08;  //Ponemos como salida el pin 2.3 en HIGH
      _delay_us(13);  //Hacemos un duty_cycle de 50%(la mitad del pulso lo tenemos encendido)
      P2OUT = 0x00;  //Ponemos como salida el pin 2.3 en LOW
      _delay_us(13); //Hacemos un duty_cycle del 50%(la otra mitad del pulso lo tenemos apagado)
  }


}

void enviarTrama(int trama[32]){
	 int i = 0;

	    // Recorermos el array verificando si tenemos que enviar un
	    // 0 logico o 1 logico
	    while (i < 32) {

	        // Transmitimos un 1
	        if (trama[i]==1) {
	            generar38khz(560);
	            _delay_us(1690);
	        }else {
	         // Transmitimos un 0
	            generar38khz(560);
	            _delay_us(560);
	        }

	        i++;
	    }

}

void sendNec(){

	//Segun la teoria del protocolo NEC, primero debemos
	//enviar una cabecera modulada de 9ms + 4.5 de delay
	//un 1 logico son 560 us + 1690 us de delay
	//un 0 logico son 560 us + 560 us de delay
	//Bit de parada 560 us + 4708 us de delay
	//
	//Tambien sabemos que la trama se envía de LSB a MSB
	//Desde el bit menos significativo al mas


	//Cabecera
	generar38khz(9000); //PWN 38khz 9ms
	_delay_us(4500); //delay 4.5ms


	//Enviamos una trama de 32 bits que usa el protocolo NEC, en concreto
	// 0x20DF40BF --> Comando VOL_UP(0x40) con direccion de dispositivo (0x20)
	//Para más información del protocolo ver fichero de referencia adjunto
	//Direccion 0x20 | Direccion negada 0xDF
	//Comando 0x40   | Comando negado 0xBF
	// 0x20DF40BF --> 00100000110111110100000010111111
	int tramaDatos[32]={0,0,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,1};
	enviarTrama(tramaDatos);

    //Bit de parada
    generar38khz(560); //bit parada
    _delay_us(4708); //bit parad
}


///FUNCION PRINCIPAL DEL MICRO///////
////////////////////////////////////
int main(void) {
 	WDTCTL = WDTPW +WDTHOLD;                  // Stop Watchdog Timer

      //Calibramos el micro a 16Mhz
	  BCSCTL1 = CALBC1_16MHZ;                   // Set range
	  DCOCTL = CALDCO_16MHZ;                    // Set DCO step + modulation*/

	  //All values to cero as INPUT Pines del P1_0 al P1_6
	  //Pines as INput P2_0 al P2_6
	  P1DIR = 0x00;
	  P2DIR = 0x00;

	  P1DIR |= 0x01;
	  P1OUT |= 0x01; //Cambiamos sólo el bit 1 y lo ponemos como output
	                 //Es decir enecendemos el led rojo del launchpad para ver que funciona

    	for(;;) { //Bucle infinito
           sendNec();     //Mandamos un comando NEC
           _delay_ms(1000); //Hacemos un paro de 1 segundo
    	}
	
}

*Libreria delay.h

Código:
// delay.h - delay library providing macros for MSP430 delays. These are for
// convenience and shouldn't be considered 100% accurate, especially if timing
// is important. For the most accurate delays, make sure F_CPU matches the
// operating frequency of your MSP430 device.

#pragma once

// F_CPU should be defined to the frequency to base delays upon before sourcing
// the delay library as follows:
// Example for 16MHz
// #define F_CPU 16000000UL
// Example for 25MHz
// #define F_CPU 25000000UL

// Delay Functions
#define _delay_ns(__ns) \
  if((unsigned long) (F_CPU/1000000000.0 * __ns) != F_CPU/1000000000.0 * __ns)\
        __delay_cycles((unsigned long) ( F_CPU/1000000000.0 * __ns)+1);\
  else __delay_cycles((unsigned long) ( F_CPU/1000000000.0 * __ns))
#define _delay_us(__us) \
  if((unsigned long) (F_CPU/1000000.0 * __us) != F_CPU/1000000.0 * __us)\
        __delay_cycles((unsigned long) ( F_CPU/1000000.0 * __us)+1);\
  else __delay_cycles((unsigned long) ( F_CPU/1000000.0 * __us))
#define _delay_ms(__ms) \
  if((unsigned long) (F_CPU/1000.0 * __ms) != F_CPU/1000.0 * __ms)\
        __delay_cycles((unsigned long) ( F_CPU/1000.0 * __ms)+1);\
  else __delay_cycles((unsigned long) ( F_CPU/1000.0 * __ms))
#define _delay_s(__s) \
  if((unsigned long) (F_CPU/1.0 * __s) != F_CPU/1.0 * __s)\
        __delay_cycles((unsigned long) ( F_CPU/1.0 * __s)+1);\
  else __delay_cycles((unsigned long) ( F_CPU/1.0 * __s))

3. Notas y referencias para entender un poco el código

** Adjunto como PDF, donde encontrarás como funciona el protocolo, lista de comandos que se deben enviar, librería delay.h, conversor de binario/hexadecimal, codigo para usar con un PIC
 

Adjuntos

  • eskema1_bb.jpg
    eskema1_bb.jpg
    68 KB · Visitas: 9
  • referencias_utiles.pdf
    99 KB · Visitas: 8
Última edición:
Atrás
Arriba