Fuente SMPS con MC34063

Este integrado, es un conversor DC/DC StepUP, StepDown o Inversor de tensión, es decir, puede funcionar como fuente elevadora de tensión, reductora de tensión o bien inversora de tensión.
En este caso se utilizara la configuración elevadora de tensión que es la que realice en la práctica ya que necesitaba extraer 12V a partir de 5V, en este blog van a encontrar otras fuentes similares con el integrado LM2577 o 555, ambas funcionan bien, la que utiliza el 2577 es integrada de potencia pero es la mas costosa por el integrado que utiliza. La que utiliza el timer 555 es la más barata y configurable pero carece de realimentaciones y pwm, etc.…. Por ultimo la que menciono en ese post es similar a la del 2577 pero no es de potencia, es decir, el integrado 34063 solo proporciona 100mA en su salida como máximo pero es posible aumentar esa potencia con un transistor externo, de esta forma le he podido extraer 200mA sobre 12V, lo cual nos permite alimentar algunos dispositivos de baja señal.
Nótese que he mencionado que solo le extraje 200mA esto es porque esta alimentado con el puerto USB, el cual según normas IEEE nos proporciona unos 500mA como estándar en notebooks y desktops por lo que la limitación esta en el USB, si en cambio lo alimentáramos con 6V desde 4 pilas podríamos extraer mas potencia de salida con ese transistor.
El calculo del choque de RF lo dejare para otro post ya que no viene al caso, la bobina L1 esta construida en un núcleo toroidal de 20mm de diámetro exterior y 15mm de diámetro interior, en el cual se arrollan 20 vueltas de alambre AWG 20 (0,8mm), de esta forma su inductancia ronda los 100uHy claramente se puede comprar el choque ya construido.
La tensión de salida de esta fuente será función de la realimentación del integrado que ingresa por el pin #5 en su interior hay un comparador en donde el mismo integrado posee una tensión de referencia de 1,25V, por ende compara la tensión ingresada en el pin #5 con los 1,25V internos, nótese que si la tensión en este pin es menor a 1,25 la fuente aumentara el ciclo útil del pwm para enviar mayor tensión a la salida, lo mismo pasa en el caso contrario, si la tensión en el pin #5 es mayor a la de referencia reducirá la salida de tensión.
Entonces tendremos que jugar con estos valores de R3 y R4 para lograr la tensión de salida deseada.
El calculo para la tensión en la entrada del comparador es 1,25(1+(R4/R3)).




Matriz de LED con RTOS

En este nuevo proyecto, se ha tomado como base el proyecto de http://electgpl.blogspot.com.ar/2012/05/control-de-matriz-estatica.html al cual se ha modificado para que funcione con RTOS, como vimos en la introducción a RTOS http://electgpl.blogspot.com.ar/2012/12/rtos-sistema-operativo-en-tiempo-real.html ahora se le quito la interrupción por desbordamiento del TIMER0 y directamente se realizaron dos tareas que correrán mediante el sistema operativo, la primera tarea se encargara de sensar las columnas o multiplexar las columnas y la segunda tarea se encargara del barrido de caracteres, si bien ambas funciones tienen que funcionar a una velocidad tal que no se detecten parpadeos en la matriz, nótese que la tarea del barrido de caracteres posee un tiempo de 30ms (30 veces mas lenta que la tarea de multiplexado), de esta forma se logra ver el movimiento de los caracteres formando la palabra "ELECTGPL".
El circuito es el mismo que se ha utilizado en la versión sin RTOS, y el único cambio es el mencionado sistema operativo, el cual nos ha dado mejores resultados tras la ejecución.



El código fuente es el siguiente:

#include<16F883.h>
#use delay(int=4000000)
#fuses XT,NOWDT


#use rtos(timer=0,minor_cycle=1ms)


//Definicion de variables
int fila[5],letra=0;


//Definicion de la primera tarea (sensado de columnas)
#task(rate=1ms,max=1ms)

void funcion1();
 

//Definicion de la segunda tarea (barrido de caracteres)
#task(rate=30ms,max=1ms)
void funcion2();
 

//Inicio del programa
void main(){
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
   rtos_run();
}


//Funcion de sensado de columnas
void funcion1(){
   output_a(0b00000001);
   output_c(~fila[0]);
   delay_ms(10);
   output_a(0b00000010);           
   output_c(~fila[1]);
   delay_ms(10);
   output_a(0b00000100);           
   output_c(~fila[2]);
   delay_ms(10);
   output_a(0b00001000);           
   output_c(~fila[3]);
   delay_ms(10);
   output_a(0b00010000);
   output_c(~fila[4]);
   delay_ms(10);
}


//Funcion de muestreo de caracteres
void funcion2(){
   switch(letra){
      case 0: fila[0]=0b01000001;
              fila[1]=0b01000001;
              fila[2]=0b01001001;
              fila[3]=0b01001001;
              fila[4]=0b01111111;
              letra++;
              break;
      case 1: fila[0]=0b00000001;
              fila[1]=0b00000001;
              fila[2]=0b00000001;
              fila[3]=0b00000001;
              fila[4]=0b01111111;
              letra++;
              break;
      case 2: fila[0]=0b01000001;
              fila[1]=0b01000001;
              fila[2]=0b01001001;
              fila[3]=0b01001001;
              fila[4]=0b01111111;
              letra++;
              break;
      case 3: fila[0]=0b01000001;
              fila[1]=0b01000001;
              fila[2]=0b01000001;
              fila[3]=0b01000001;
              fila[4]=0b00111110;
              letra++;
              break;
      case 4: fila[0]=0b01000000;
              fila[1]=0b01000000;
              fila[2]=0b01111111;
              fila[3]=0b01000000;
              fila[4]=0b01000000;
              letra++;
              break;
      case 5: fila[0]=0b00000110;
              fila[1]=0b01001001;
              fila[2]=0b01001001;
              fila[3]=0b01000001;
              fila[4]=0b00111110;
              letra++;
              break;
      case 6: fila[0]=0b00110000;
              fila[1]=0b01001000;
              fila[2]=0b01001000;
              fila[3]=0b01001000;
              fila[4]=0b01111111;
              letra++;
              break;
      case 7: fila[0]=0b00000001;
              fila[1]=0b00000001;
              fila[2]=0b00000001;
              fila[3]=0b00000001;
              fila[4]=0b01111111;
              letra++;
              break;
      case 8: fila[0]=0b00000000;
              fila[1]=0b00000000;
              fila[2]=0b00000000;
              fila[3]=0b00000000;
              fila[4]=0b00000000;
              letra = 0;
              break;
   }       
}


Multiple I2C Virtual

Al igual que el puerto serial se puede utilizar el comando STREAM para definir el nombre de los puertos.
Comúnmente para un solo puerto configuramos el mismo de la siguiente forma:

#use i2c(MASTER,SDA=PIN_C1,SCL=PIN_C0)

De esta forma se define el protocolo, puertos, etc...
Luego se procederá a enviar o recibir el dato por i2c por ejemplo:

i2c_start();
i2c_write(DATO);
i2c_write(DATO);
i2c_write(DATO);
i2c_stop();


Donde iniciamos el protocolo tras la función i2c_start(); y luego escribimos los byte correspondientes según necesite el dispositivo a comandar mediante la función i2c_write(); y luego se procede a cerrar el protocolo con la función i2c_stop();.

Si quisiéramos incluir otro puerto i2c en el microcontrolador deberíamos utilizar el comando STREAM el cuál nos indicara una etiqueta para la configuración del puerto y esta misma será la que utilizamos para diferenciar entre un protocolo o el otro.

#use i2c(MASTER,SDA=PIN_C1,SCL=PIN_C0,STREAM=I2C1)
#use i2c(MASTER,SDA=PIN_B1,SCL=PIN_B0,STREAM=I2C2)


Donde podemos ver que en el primer puerto será STREAM=I2C1 y el segundo puerto será STREAM=I2C2. El comando dentro de las funciones start, write y stop quedara de la siguiente forma.

i2c_start(I2C1);
i2c_write(I2C1,DATO);
i2c_write(I2C1,DATO);
i2c_write(I2C1,DATO);
i2c_stop(I2C1);

i2c_start(I2C2);
i2c_write(I2C2,DATO);
i2c_write(I2C2,DATO);
i2c_write(I2C2,DATO);
i2c_stop(I2C2);


Tener en cuenta que el protocolo I2C del MCU por Hardware será uno solo, esta forma de crear puertos es netamente virtual por ende los tiempos del procesador será más lento, es recomendable para procesadores de gama media alta.

Multiple UART Virtual



Como utilizar mas de un puerto de comunicación serial.
No es de lo más común pero es posible que se quieran utilizar más de un puerto serial en el mismo micro.
Comúnmente para un solo puerto configuramos el mismo de la siguiente forma:

#use RS232(BAUD=9600, XMIT=PIN_C1, RCV=PIN_C2,FORCE_SW)

De esta forma le decimos la velocidad y los pines que utilizaremos como TX y RX, luego para enviar un dato por serial utilizamos la función printf(); por ejemplo:

printf(“VALOR1: %d\n”,valor1);

donde mostramos el valor1 en la salida serial.
Ahora si queremos incluir otra salida serial podríamos hacerlo de la siguiente forma:

#use RS232(BAUD=9600, XMIT=PIN_B1,RCV=PIN_B2,FORCE_SW)

Aquí vemos que es igual a la otra forma pero cambiamos los pines C1 y C2 por B1 y B2, pero hay algo que sigue quedando mal, cuando llamemos a la función printf(); para que nos muestre el valor2 será:

printf(“VALOR2: %d\n”,valor2);

pero esto por que puerto saldrá? Bueno aquí esta la diferencia, para que podamos incluir mas de un puerto de transmisión debemos incluir en su configuración la directiva STREAM donde la igualaremos al nombre del puerto, por ejemplo: STREAM=SERIAL1, ahora ambas directivas quedaran de la siguiente forma:

#use RS232(BAUD=9600, XMIT=PIN_C1,RCV=PIN_C2,FORCE_SW,STREAM=SERIAL1)
#use RS232(BAUD=9600, XMIT=PIN_B1,RCV=PIN_B2,FORCE_SW,STREAM=SERIAL2)

Y para terminar esto los llamados a la función printf(); quedaran:

fprintf(SERIAL1,"VALOR1: %d\n”,valor1);
fprintf(SERIAL2,"VALOR2: %d\n”,valor2);

Y esto se repetirá según la cantidad de puertos a utilizar.

Tener en cuenta que el protocolo SPI/EUSART del MCU por Hardware será uno solo, esta forma de crear puertos es netamente virtual por ende los tiempos del procesador será más lento, es recomendable para procesadores de gama media alta.

RTOS - Sistema Operativo en Tiempo Real



RTOS, Sistema Operativo en Tiempo Real (Real Time Operating System).
Como lo dice su nombre es un sistema operativo en tiempo real, para que sirve?, sencillo supongamos que necesitamos realizar tareas múltiples (Multi Tasking) como por ejemplo Leer un puerto, mientras enviar datos por serie, mientras realizar cálculos, mientras mostrar mensajes en un LCD, etc… Todo esto al mismo tiempo. Sabemos que por ejemplo cuando leemos el canal ADC este mismo funciona por interrupción, es decir, cuando termina la lectura nos permite volcar su dato a una variable, esto demora un tiempo que se puede setear pero supongamos que el tiempo que demora es 200ms, el resto del microcontrolador estará inactivo 200ms hasta que el ADC envíe el valor y devuelva el control al programa principal, si por ejemplo realizáramos otras tareas mientras transcurren esos 200ms?, es aquí donde entra el RTOS, no es mas que un kernel multiplataforma que en este caso sobre CCS para PICmicro nos permite optimizar el tiempo y el procesador, de esta forma nuestro procesador se vuelve mas eficiente y podemos sacarle el mayor provecho.
La forma de funcionar de este RTOS es muy sencilla se basa en algunas directivas y funciones las cuales no comentare todas porque seria muy extenso pero si les comentare las mas comunes y sencillas.
La estructura es la siguiente:

1) Se inicializa el RTOS
#use rtos(timer = 0, minor_cycle = 100ms)

2) Las tareas a realizar puede ser una o más de una
#task(rate=100ms,max=100ms)

Solo con estas dos funciones podemos implementar en nuestro programa un RTOS.

Detalle:
#use rtos(timer = 0, minor_cycle = 1ms)
Esto nos dice que usaremos rtos mediante el timer0 y con un tiempo mínimo de ejecución de cada tarea de 1ms

#task(rate=1s,max=100ms)
Esto nos dice que usaremos una task (tarea) que se ejecutara cada 1s y que como máximo la ejecución tardara 100ms.

Estos valores pueden ser diferentes, va en función de la necesidad de cada tarea.

Un ejemplo de utilización en código C (CCS)

#include<rtos.h>
#use rtos(timer = 0, minor_cycle = 1ms)
#task (rate=1s, max=10ms) //Ejecuta cada 1 segundo, dura máximo 10ms  
void func1();//Llama a la función func1();
#task (rate=2s, max=10us) //Ejecuta cada 2 segundos, dura máximo 10us  
void func2();//Llama a la función func2();

main(){
 
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); //TMR0 para el RTOS
   rtos_run();//Función que ejecuta el RTOS
}  
void func1(){  
   printf("Ejecuta primera task\n");  
}  
void func2(){
   printf("Ejecuta segunda task\n");  
}

Bueno esta es la forma de utilizar RTOS, nótese que se utilizaron dos funciones donde dentro de ellas se puede poner la tarea que uno quiera, pero podrían haber sido mas de dos tareas, o bien también puede no utilizarse funciones y se puede incluir el código directamente de bajo de la definición de las tarea del rtos.

A este programa le faltan las directivas del microcontrolador que utilizaran en su proyecto, como librería, configuraciones, etc… Es solo a modo informativo de cómo se utiliza el RTOS.

NOTA: existen otras funciones mas específicas como para interrupciones especiales, o retornos de datos según el funcionamiento, es posible configurar las task por ejemplo para que nos devuelva un valor si la tarea fue realizada correctamente o no, entre otras cosas.