Programmare un ATtiny13 come un oscillatore audio con frequenza variabile e larghezza di impulso


8

Voglio creare un semplice oscillatore ad onda quadra simile a quello che si farebbe con un 555, ma voglio usare il supporto PWM basato su interrupt per controllare la larghezza e la frequenza degli impulsi.

Ho studiato il foglio dati, le API AVR e qualsiasi esempio PWM riesca a trovare, ma non sono riuscito a mettere tutto insieme.

È possibile creare un tale oscillatore con la funzionalità PWR AVR integrata e, in tal caso, come? Un mio amico ha fatto qualcosa di simile con un PIC a 8 pin.

Il mio ragionamento è che otterrò suoni interessanti cambiando l'ampiezza dell'impulso e quindi la forma d'onda ad una data frequenza. Simile a come funziona la console Punk Atari, ma si spera in un modo più stabile, ovvero cambiando la larghezza degli impulsi, ma lasciando la frequenza costante o viceversa.


2
potresti chiarire qual è la tua domanda?
Jason S,

Non sono sicuro di quanto saranno interessanti, ma è facile da provare e puoi giudicare. Man mano che il polso si restringe, l'ampiezza delle armoniche aumenta. Continua a restringere il polso e otterrai rumore bianco. Penso che avresti opzioni più interessanti facendo un oscillatore a controllo numerico. È possibile modificare le forme d'onda caricate nella wavetable.
jluciani,

Risposte:


5

Questi dovrebbero portarti abbastanza lontano e il resto che puoi fare con il foglio dati. Inizia a costruire pezzo per pezzo, da blinky a forma d'onda a forma d'onda che cambia nel tempo in toni. Alcune fonti potrebbero aiutare con il filtraggio e il pilotaggio delle uscite audio (LPF attivo potrebbe fare entrambe le cose in modo ordinato).

Suggerisco di tornare con domande più specifiche.


4

Il periodo del PWM è determinato dalla velocità di overflow del timer. Ci sono molte impostazioni nella sezione Modalità di funzionamento a cui pensare. Se tutto ciò che vuoi fare è generare un'onda quadra a periodo costante, con ciclo di lavoro variabile, penso che vorrai utilizzare la modalità CTC (Clear Timer on Compare Match). L'idea di base è impostare OCR0A sul numero di tick del timer fino a quando non si desidera che il pin passi al successivo, e utilizzare l'interruzione Confronta confronto per modificare quel valore per la volta successiva. Quindi in avr-gcc sarebbe simile a:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0; 


void setup_timer(double p_ms, double duty){
  TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
  TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100

  // ... do some stuff based on your CPU frequency
  // to define the csxx_bits of TCCR0B when the timer is running
  // and consequently, to set on_time_ticks and off_time_ticks
  OCR0A = on_time_ticks;
  TCCR0B |= your_settings_here;
}


void start_timer(){
  //start the timer running at the desired rate
  TCCR0B |= csxx_bits; 
}


int main(int argc, char **argv){
  double period_ms, duty_cycle;
  setup_timer(period_ms, duty cycle);
  start_timer();  
  for(;;){
    //spin or sleep or whatever
  }
}


ISR(TIM0_COMPA_vect){
  if(OCR0A == on_time_ticks){
    OCR0A = off_time_ticks;
  }
  else{
    OCR0A = on_time_ticks;
  }
}

Attenzione, questo è un codice non testato ma penso che l'idea sia giusta. Non è nemmeno questo l' unico modo per farlo.

A proposito, c'è una cosa che dovresti sapere su ATTiny13. L'oscillatore RC interno è garantito per essere preciso solo entro il 10% dal piano di fabbrica. Esiste un processo di calibrazione utente che puoi seguire (descritto da una nota di atmel ) che ti porterà alla precisione del 2% per ATTiny13. Se vuoi fare di meglio, probabilmente dovrai utilizzare un chip che ospita un cristallo esterno ...


1
La tua risposta mi ha aiutato a chiarire qualcosa di simile con cui stavo avendo problemi - grazie. Solo un punto (per chiunque legga così a lungo dopo il thread originale): la scelta di 0b100 per WGM0 [2,1,0] non imposterà la modalità CTC. (In effetti imposterà una modalità riservata da Atmel.) Il foglio dati ATtiny13 afferma che la modalità CTC necessita del valore 2; invece hai assegnato per errore bit_number 2 (ovvero valore 4). Per questo motivo è anche necessario non solo modificare (cioè cancellare) WGM02 in TCCR0B ma anche impostare i bit WGM01 e WGM00 rispettivamente su 1 e 0. Quei bit sono in TCCR0A, quindi non è sufficiente impostare TCCR

3

Non è una risposta diretta alla tua domanda, ma potrebbe essere un suggerimento e fornire alcuni suggerimenti:

Ho appena creato un oscillatore a controllo numerico (NCO) usando un ATmega uC e un DAC. Un array di numeri interi viene utilizzato per memorizzare un ciclo di una forma d'onda (wavetable). Un accumulatore di fase (int lungo) viene utilizzato per determinare l'indirizzo dei dati di uscita nella tabella wavetable. Ogni interruzione del timer aumenta l'accumulatore di fase di un valore fisso. L'incremento di fase determina la frequenza.

Nella mia applicazione ho usato un wavetable a 64 byte che conteneva un ciclo di un'onda sinusoidale. È facile estendere il wavetable e aggiungere più risoluzione ai campioni. La mia nota di applicazione è su http://wiblocks.com/docs/app-notes/nb1a-nco.html


1

Fondamentalmente un PWM non cambia la frequenza. Le PWM sono usate principalmente per controllare l '"intensità" di un segnale.

Per generare un interrupt per frequenze diverse suggerirei di utilizzare il timer in modalità CTC.

Verrà eseguito sul valore di confronto, attiva / disattiva un interruzione, cancella e riavvia se stesso - fino a quando non viene eseguito nuovamente sul valore di confronto ...

Ad ogni interruzione puoi cambiare una o più porte e il resto del tempo (il timer continua a funzionare automaticamente) puoi guardare i tuoi input di qualsiasi tipo ...

Puoi ancora "modulare" la tua onda quadra con un PWM per controllare il "guadagno". Ma uno di questi deve essere fatto "a mano" perché ATtiny13 ha un solo timer hardware ...


1
la maggior parte delle periferiche hardware PWM consente di selezionare la frequenza; se mantieni costante il ciclo di lavoro, PWM può comunque darti il ​​controllo a frequenza variabile
Jason S

1
La modifica della larghezza degli impulsi non cambia la frequenza fondamentale ma cambia le armoniche.
jluciani,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.