/*
https://chat.qwen.ai/c/guest
https://www.duinocodegenerator.com/
Generar una onda por modulación de ancho de pulso senoidal de 120 incrementos, 255 Valor máximo para el cuarto de seno, en PB1 con un
microcontrolador Attiny85 de reloj 8 MHz, al mismo tiempo generar una onda cuadrada sincronizada a PB1 de fase invertida en PB0 de 60 Hz
y a su vez poseer intercepción por interrupción de cruce de cero para añadir un tiempo muerto de 5us para evitar coalición en la fase de
la onda cuadrada, poseer una entrada de realimentación de voltaje (1 a 4.5 )en PB4 con una lectura analógica de prescaler de 8 para
controlar la modulación del ancho de pulso senoidal. optimizar memoria y depurar el código probando que el microcontrolador funcione.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
// Definiciones
#define F_CPU 8000000UL // Reloj de 8 MHz
#define QUARTER_SINE_LEN 128
#define MAX_PWM 255
// Array de cuarto de ciclo de seno normalizado a 255
const uint8_t quarter_sine[QUARTER_SINE_LEN] PROGMEM = {
0, 1, 3, 6, 9, 12, 16, 20, 25, 30, 35, 40, 45, 50, 56, 61,
67, 73, 79, 85, 91, 97, 103, 109, 115, 121, 127, 133, 139, 145, 150, 156,
161, 166, 171, 176, 181, 186, 190, 195, 199, 203, 207, 211, 215, 218, 222, 225,
228, 231, 234, 237, 239, 241, 243, 245, 247, 248, 249, 250, 251, 252, 253, 254,
255, 254, 253, 252, 251, 250, 249, 248, 247, 245, 243, 241, 239, 237, 234, 231,
228, 225, 222, 218, 215, 211, 207, 203, 199, 195, 190, 186, 181, 176, 171, 166,
161, 156, 150, 145, 139, 133, 127, 121, 115, 109, 103, 97, 91, 85, 79, 73,
67, 61, 56, 50, 45, 40, 35, 30, 25, 20, 16, 12, 9, 6, 3, 1
};
volatile uint8_t pwm_index = 0;
volatile uint8_t adc_value = 0;
// ISR para cruce de cero (para añadir tiempo muerto)
ISR(TIMER0_COMPA_vect) {
static uint8_t square_wave_state = 0;
// Añadir tiempo muerto antes de cambiar la fase
if (square_wave_state == 0) {
_delay_us(5); // Tiempo muerto de 5 µs
PORTB |= (1 << PB0); // Subir PB0 (invertido respecto a PB1)
square_wave_state = 1;
} else {
_delay_us(5); // Tiempo muerto de 5 µs
PORTB &= ~(1 << PB0); // Bajar PB0 (invertido respecto a PB1)
square_wave_state = 0;
}
}
// Configuración inicial
void setup() {
// Configurar puertos
DDRB = (1 << PB1) | (1 << PB0); // PB1 y PB0 como salida
PORTB = 0; // Apagar todos los pines
// Configurar Timer0 para generar onda cuadrada de 60 Hz
TCCR0A = 0; // Modo normal
TCCR0B = (1 << CS02); // Prescaler de 256
OCR0A = 207; // (8 MHz / 256) / 60 Hz = 208 -> 207 para ajuste
TIMSK = (1 << OCIE0A); // Habilitar interrupción en comparación
// Configurar ADC para lectura en PB4
ADMUX = (1 << REFS0) | (0 << ADLAR) | (4 << MUX0); // Referencia Vcc, canal 4
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); // Prescaler 64
sei(); // Habilitar interrupciones globales
}
// Función principal
int main(void) {
setup();
while (1) {
// Leer ADC
ADCSRA |= (1 << ADSC); // Iniciar conversión
while (ADCSRA & (1 << ADSC)); // Esperar fin de conversión
adc_value = ADCH; // Obtener valor alto
// Calcular escala PWM basada en ADC
uint8_t pwm_scale = (adc_value * MAX_PWM) >> 8; // Escalar 0-255
// Generar PWM senoidal en PB1
uint8_t sine_val = pgm_read_byte(&quarter_sine[pwm_index]);
if (sine_val > pwm_scale) {
PORTB &= ~(1 << PB1); // Bajar PB1
} else {
PORTB |= (1 << PB1); // Subir PB1
}
// Incrementar índice PWM
pwm_index++;
if (pwm_index >= QUARTER_SINE_LEN) {
pwm_index = 0;
}
// Ajustar retraso para mantener frecuencia de 720 Hz
_delay_us(1388); // ~1/720 segundos
}
}