Buenas a todos,
Me presento soy un estudiante de Ingeniería electrónica que esta terminando la carrera, y estoy realizando como trabajo fin de titulo un Inversor trifásico microcontrolado con una placa Arduino.
He trabajado bastante con el proyecto aunque todavía tengo algunos fallos que espero que ustedes me puedan ayudar con ellos. Y una vez terminado el proyecto colgar aquí la memoria para que otras personas puedan nutrirse de ella y mejorarla.
Bueno el objetivo de mi proyecto consiste en tomar una tensión continua de una batería, fuente de alimentación, etc. Y transformarla en una señal trifásica de unos 100 V de tensión y 50Hz de frecuencia. Se usara una tensión de 100V debido a que voy a fabricar un prototipo (ya he pedido todos los componentes) que tendrá una función didáctica en mi universidad, y para cumplir con la normativa y evitar el riesgo de accidente se ha elegido esa tensión.
La placa que voy a utilizar para este proyecto es una placa Arduino uno R3. Utilizaré las 6 salidas PWM de la placa para controlar la activación/desactivación de 3 pares de transistores MOSFET, los cuales generarán la alternancia de la señal continua.
En mi código la principal premisa que sigo es la de la velocidad, ya que configuraré las PWM para que oscilen a 31250 Hz; lo que me obliga a realizar las operaciones lo más rápidamente posible. Lo que he hecho ha sido crear una tabla con 625 valores con los distintos duty cycle que tomarían las PWM para generar una senoidal de 50 Hz. Y me movería a lo largo de la tabla con punteros (1 por cada PWM ). La tabla contiene todos los duty cycles necesarios a lo largo de un período de una señal de 50Hz, podrían ser menos valores pero he decidido hacerlo así a priori para conseguir una senoidal lo más perfecta posible.
¿Por qué son 625 valores? Bueno, el período de una señal de 50 Hz es 20 ms (20 000us). Y el período de las PWM de 31250Hz es 32 us. Si dividimos: 20 000 us / 32 us = 625 valores, de esta forma sé que cada 32 us tengo que modificar cada duty cycle y me aseguro de que cuando se haya recorrido todos los valores de la tabla habré completado 20 ms y por tanto la señal de salida será de 50 Hz.
Bueno, voy a explicar un poco por encima como he realizado el código aunque esta bastante bien comentado.
He realizado el código usando los registros de control del micro Atmega ya que así modifico los timers y actúo de manera más rápida sobre los registros de comparación para evitar sumar tiempos en cada operación.
He creado unos retardos para evitar cortocircuitos entre pares de transistores de la misma rama usando ensamblador ya que no puedo usar la función delay () porque he modificado el timer0 del cual depende este retardo.
El código lo pongo en el siguiente post porque excedo las palabras por post, I'm sorry.
¿Qué problemas tengo ?
- Bueno el principal problema que tengo consiste en que cuando simulo este código en el programa Proteus 8, la salida que me obtengo en los piner que corresponden al timer 1 se me genera un 0 durante un largo período (63 ms) de tiempo pero no encuentro el problema ni la posible causa. En un principio pensé que podría ser la configuración del timer por ser de 16 bits pero no creo que esté mal configurado.
Efecto del 0:
Efecto del 0 ampliado:
link a la página:
http://subefotos.com/ver/?951e00da44d4992bf942a90cc0e1396bo.png
- El segundo problema que he tenido ha sido cuando he realizado las pruebas de los retardos en ensamblador, los cuales me generan un retardo correcto dos veces y una tercera vez me realizan el retardo el doble de grande y así de manera continuada. Este hecho solo ocurre cuando los timers son modificados pero no ocurre cuando se mantiene la configuración normal.
Este es el código de prueba del retardo:
void setup() {
pinMode (13, OUTPUT);
TCCR0A = 0xA1; // Habilitamos las dos salidas en modo Fast PWM - 8 bits. Pre-escaler = 1.
TCCR0B = 0xC1;
TCCR1A = 0xA1; // Habilitamos las dos salidas en modo Phase-correct - 8 bits. Pre-escaler = 1.
TCCR1B = 0xC1;
TCCR2A = 0xA1; // Habilitamos las dos salidas en modo Phase-correct - 8 bits. Pre-escaler = 1.
TCCR2B = 0xC1;
}
void loop() {
PORTB = 0x20;
asm volatile ( // Este es un retardo de 6.5 us
"clr r16 \n" // 1 ciclo de reloj.
"ldi r16, 0x1A \n" // 1 ciclo de reloj. 80 vueltas cargadas.
"1: dec r16 \n" // 1 ciclo de reloj
"brne 1b \n" // 2 ciclos de reloj para retornar y 1 para salir
);
PORTB = 0x00;
asm volatile (
"clr r16 \n"
"ldi r16, 0x1A \n"
"2: dec r16 \n"
"brne 2b \n"
}
Efecto doble del retardo:
link a la página por si se ve muy pequeña la imagen:
http://subefotos.com/ver/?90c8eb8024752dcf2396598f58df0585o.png
Imagen con configuración normal (mismo codigo pero sin poner los TCCxR):