Ondas senoidales con arduino

Me encunetro intentando generar ondas senoidales con Arduino.
Los conocimientos que tengo es que se puede conseguir mediante una lookup table, generando una señal PWM que varía su Duty Cycle.
Necesito un código que genere dicha señal a la frecuencia de 440 hz. Además necesito que esta pueda variarse.
El código que tengo es el siguiente:

const int tableSize = 256; // Tamaño de la tabla de búsqueda
int waveform[tableSize]; // Tabla de búsqueda para almacenar los valores de la onda senoidal

int phase = 0; // Fase actual de la onda
float increment = 440 * tableSize / 1000.0; // Incremento de la fase para obtener una frecuencia de 440 Hz
const int outputPin = 9; // Pin digital utilizado para generar la señal

void setup() {
  // Llenar la tabla de búsqueda con los valores de la onda senoidal
  for (int i = 0; i < tableSize; i++) {
    waveform[i] = 128 + int(127 * sin(2 * PI * i / tableSize));
  }
  
  pinMode(outputPin, OUTPUT); // Configurar el pin como salida
}

void loop() {
  // Generar la onda senoidal utilizando la tabla de búsqueda
  int sample = waveform[phase];

  // Enviar la muestra al pin de salida
  analogWrite(outputPin, sample);

  // Actualizar la fase para modificar la frecuencia
  phase += increment;

  // Verificar los límites de la fase
  if (phase >= tableSize) {
    phase = 0;
  }

  delayMicroseconds(1000); // Retardo entre muestras para controlar la frecuencia
}

Al conectar el osciloscopio al pin definido, no consigo los valores deseados.
Además, la placa que estoy usando es Arduino Nano.

El valor de la variable "incremento" en su programa se calcula de la siguiente manera:
float increment = 440 * tableSize / 1000.0;
Dado que 440 y "tableSize" son números enteros, se realiza el cálculo entero de 440*tableSize, lo que hace que se desborde, dando un -18432 anómalo que, a su vez, dividido por 1000 (esta vez float) es igual a -18.432!
Debe cambiar el cálculo de esta manera para forzar el uso del float en la primera multiplicación:
float increment = 440.0 * tableSize / 1000.0;

Trasladado a la categoría específica de español.... Por favor, publique en la categoría de idioma correcta la próxima vez.

Moderador:
Por favor, lee las Normas del foro
Si posteas en el foro en inglés usa idioma inglés para expresarte.
Si escribes en español debes usar el foro Arduino en español.
Este mensaje lo envío porque tu hilo fue movido del foro en inglés.

Cuando quieres hacer algo como lo que propones, no puedes estar haciendo cuentas.
Las cuentas insumen tiempo y no dispones de tiempo habitualmente.
Lo que se haces es poner todo en una planilla de calculo, llevar los valores a enteros, crear una tabla 0 a 255 si esa es la resolución de PWM como es tu caso y entonces solo te mueves dentro de dicha tabla cambiando el indice del vector que tiene la lookup table.
La frecuencia se la das con el TIMER, estableciendo cuantas muestras presentaras y lo haces a intervalos que te den el período de tu señal de 440hz.
Período T = 1/F = 1/440Hz = 2.27mseg = 2272 useg
Si tienes 256 valores o muestras que presentar entonces
Tu Timer debe tener una rutina de interrupción o tick cada 2272useg/256 = 8.875useg u 8875 nseg
Cada vez que se invoque dicha rutina devuelve un valor correspondiente a la tabla
y mueves el indice a la posicion siguiente y si llega a 255 entonces el siguiente será 0 o sea
modulo 256
Es muy fácil cuando entiendes esto.
Aca no hay calculos de ningún tipo.
El micro trabaja aliviado y en el loop solo muestra el comando analogWrite(valor) siendo valor un dato que se extrae de la tabla comprendido entre 0 y 255.
A esto se le deben incorporar algunas cuestiones extra microprocesador.
Tu senoide esta desplazada o sea tiene un offset de 2.5V (si usas un micro de 5V) por lo que tendras que agregar un operacional con filtro pasabajos que garantice algo suave. Y tambien quitarle los 2.5 para tener una senoide mas o menos prolija.
Es mejorable? Claro.
Un DAC de 12bits minimo o mejor.

¿Lo que propones es calcular los valores de las tablas fuera del código?
Y con el tema del timer, buscando información solo he encontrado que con ellos generas una señal cuadrada, y lo que se busca en mi proyecto es un pwm que cambie de Duty Cycle. Puedo estar equivocada con esta información por supuesto.
Agradecería mucho la ayuda.

No lo puse pero usa cualquier planilla de cálculo.

Siempre hablamos de señales cuadrada pero si modificas el PWM (ancho del pulso) logras lo que quieres.
Una señal de X frecuencia con 0.1% de PWM estará muy cercana a 0 y una señal al 99% estará cercana al máximo de tu senoide.
Este tema no es fácil. Hay documentación y muchos códigos en internet. Solo busca.
Yo he respondido en el pasado en varios hilos similares.
Hay casos trifásico y monofásicos.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.