Suonerie Atmega8. Sirene sonore semplici su MK AVR. Utilizzando il modulo sonoro

L'articolo descrive i principi della sintesi musicale su un AVR. Il software incluso ti consente di convertire qualsiasi file midi in fonte in C per microcontrollori AVR per aggiungere la riproduzione di frammenti musicali a sviluppi già pronti. Viene considerato un esempio di utilizzo del software in un carillon.

Innanzitutto, un breve video di come funziona:

Cosa consente il software

Il software per PC consente di ottenere una sorgente C per CodeVision AVR, che riproduce il file midi selezionato:

1. Collega common\hxMidiPlayer.h, common\hxMidiPlayer.c al tuo progetto. Copia i modelli ATMega8Example\melody.h, ATMega8Example\melody.c, ATMega8Example\hxMidiPlayer_config.h e connettiti.
2. Avvia MidiToC.exe
3. Caricare il file Midi.
4. Configurare il lettore: frequenza di campionamento, numero di canali, forma d'onda, ecc. Il software riproduce la melodia nello stesso modo in cui la riprodurrà l'AVR.
5. Fare clic su "Crea configurazione lettore" e incollare la sorgente in hxMidiPlayer_config.h.
6. Fai clic su "Crea codice melodia" e incolla la fonte in melody.c
7. Nel nostro progetto, implementiamo il metodo Player_Output() per emettere il suono tramite PWM o un DAC esterno.
8. Imposta il timer sulla frequenza di campionamento e chiama Player_TimerFunc() dall'interrupt.
9. Chiama Player_StartMelody(&s_melody, 0).

La melodia viene riprodotta dall'interruzione del timer. Ciò significa che durante la riproduzione anche il microcontrollore può svolgere un lavoro utile.

Come funziona

Nel resto dell’articolo cercherò di spiegare brevemente come viene attuato tutto ciò. Purtroppo non sarà molto breve: il materiale è molto. Se non sei interessato puoi andare subito alle sezioni “Descrizione del software” e “API del lettore”.

Cos'è la musica

La musica è una sequenza di suoni di varie frequenze e durate. La frequenza dell'armonica fondamentale di un suono deve corrispondere alla frequenza di una certa nota. Se la frequenza di vibrazione dei suoni differisce dalle frequenze delle note, ci sembra che il musicista sia “stonato”.

Tavolo. Notare le frequenze, Hz.

Tutte le note sono divise in ottave, 7 note ciascuna + 5 semitoni (tasti neri del pianoforte). Le frequenze delle note nelle ottave adiacenti differiscono esattamente di 2 volte.

Il lettore musicale più semplice contiene una tabella con la sequenza delle note (nota + durata) di una melodia e una tabella con le frequenze delle note. Per sintetizzare il suono, viene utilizzato uno dei canali del timer, che forma un meandro:

Sfortunatamente, un suonatore così primitivo ha una forma d'onda fissa (onda quadra), che non è molto simile ai veri strumenti musicali, e può suonare solo una nota alla volta.

Una vera melodia contiene almeno due parti (assolo + basso) e, quando viene suonata al pianoforte, la nota precedente continua a suonare anche quando inizia quella successiva. Questo è facile da capire ricordando la struttura di un pianoforte: ogni nota corrisponde a una corda separata. Possiamo far suonare più corde contemporaneamente facendo scorrere le mani sui tasti.

Alcuni microcontrollori hanno più canali timer, che possono essere utilizzati per riprodurre più note contemporaneamente. Ma solitamente questi canali sono una risorsa preziosa e non è consigliabile utilizzarli tutti. A meno che, ovviamente, non stiamo semplicemente costruendo un carillon.
In totale, per ottenere polifonia e vari suoni di strumenti musicali, è necessario utilizzare la sintesi del suono.

Sintesi del suono su AVR

hxMidiPlayer utilizza la sintesi audio e può riprodurre la polifonia con diverse forme d'onda. Il lettore calcola l'ampiezza del segnale di uscita nel gestore dell'interruzione del timer con una frequenza di 8-22 KHz (quanta potenza del processore è sufficiente; dipende anche dalla forma d'onda e dal numero di canali).

Il principio della sintesi del suono può essere spiegato usando l'esempio della sintesi sinusoidale.

Prendiamo una tabella di dimensione 64, in ciascuna cella della quale i valori dell'ampiezza sinusoidale sono scritti nei punti indice * 2 * PI / 64 (un periodo):

Statico const flash uint8_t s_sineTable[ 64 ] = ( 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x93, 0x93, 0x94, 0x95, 0x95, 0 x95, 0x95, 0x95, 0x94 , 0x93, 0x93, 0x91, 0x90, 0x8F, 0x8D, 0x8C, 0x8A, 0x88, 0x86, 0x84, 0x82, 0x80, 0x7E, 0x7C, 0x7A, 0x78, 0x76, 0x74, 0x73, 0x71, 0x70, 0x6F, 0x6D, 0x6D, 0x6C, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6C, 0x6D, 0x6D, 0x6F, 0x70, 0x71, 0x73, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E);

128 (0x80) corrisponde a zero, 255 (0xff) al punto positivo più grande, 0 al punto negativo più grande.

Ora diciamo che trasmetteremo i valori dalla tabella a un DAC esterno in un timer di interruzione chiamato a una frequenza di 1000 Hz:

Statico uint8_t s_index = 0; // Confronto uscita timer1 Una routine di servizio di interruzione interrupt void timer1_compa_isr(void) ( SetDac(s_sineTable[ s_index]); if (s_index == 63) ( s_index = 0; ) else ( s_index++; ) )

Cosa otterremo di conseguenza? Otterremo oscillazioni sinusoidali con frequenza di 1000/64 Hz.

Ora aumentiamo l'indice nell'interrupt non di 1, ma di due.
Ovviamente la frequenza di oscillazione in uscita sarà già 1000/64*2 Hz.

In generale, per ottenere la frequenza F è necessario incrementare l’indice presente in tabella di:
aggiungi = F/1000 * 64

Questo numero può essere frazionario, ma per ottenere un'alta velocità viene utilizzata l'aritmetica in virgola fissa.

Il numero di voci nella tabella e la frequenza del timer influiscono sulla qualità del suono sintetizzato. Nel nostro caso sono sufficienti 64 voci nella tabella per periodo e la frequenza del timer è 12kHz. La frequenza minima accettabile del timer è 8 kHz, l'ideale è 44 kHz.

Ovviamente, con una frequenza del timer di 12 kHz, possiamo generare un massimo di onde quadre da 6 kHz, poiché dobbiamo effettuare almeno due commutazioni per periodo. Tuttavia, le frequenze più alte saranno ancora riconoscibili se lo stato di uscita viene calcolato correttamente ad ogni tick del timer.

È possibile inserire nella tabella i valori per il periodo delle oscillazioni non sinusoidali e ottenere un suono diverso.

Attenuazione

Se uno strumento musicale è basato su corde (ad esempio un pianoforte), dopo aver premuto un tasto il suono svanisce dolcemente. Per ottenere un suono del sintetizzatore più naturale, è necessario ridurre gradualmente l'ampiezza delle vibrazioni dopo l'inizio della nota (“avvolgere” le vibrazioni in una forma di attenuazione – “involucro”).

Il lettore contiene una tabella di decadimento che utilizza per ridurre l'ampiezza della sinusoide (o altra forma d'onda) dal momento in cui inizia la nota.
"Sine" "avvolto" in un tale guscio ricorda il suono di un carillon meccanico.

Sintesi dei meandri

La particolare forma dell'onda meandro consente di semplificare notevolmente la sintesi. In questo caso non vengono utilizzate le tabelle. È sufficiente calcolare quale stato (1 o 0) dovrebbe avere l'uscita ad una determinata frequenza al momento del tick del timer corrente. Questo viene fatto utilizzando l'aritmetica dei numeri interi e funziona molto rapidamente, il che spiega la popolarità dell'uso di un'onda quadra per riprodurre brani su set-top box a 8 bit.

Esempio: dichiarazione di un contatore:

Statico uint16_t s_counter = 0;

che aumenteremo di 0x8000 in ogni interruzione del timer e il bit più significativo del contatore verrà inviato alla porta:

// Confronto uscita timer1 Una routine di servizio di interruzione interrupt void timer1_compa_isr(void) ( PORTA.0 = (s_counter >> 15) & 1; s_counter += 0x8000; )

Poiché 0x8000 + 0x8000 = 0x10000, la variabile s_counter va in overflow, il 17° bit viene scartato e 0x0000 viene scritto nella variabile.
Pertanto, con una frequenza del timer di 8 KHz, l'uscita sarà un'onda quadra da 4 KHz.
Se aumenti il ​​contatore di 0x4000, ottieni un'onda quadra da 2 KHz.

In generale si ottiene la frequenza F sommando:
aggiungi = F/8000 * 0x10000

Ad esempio, per ottenere un'onda quadra con una frequenza di 1234Hz, è necessario aggiungere 0x277C. La frequenza effettiva sarà leggermente diversa da quella indicata, poiché stiamo arrotondando il termine a un numero intero. Questo è accettabile in un sintetizzatore.

Sintesi di suoni di strumenti reali

Puoi digitalizzare il suono della nota Prima del pianoforte (utilizzando un ADC per archiviare in memoria i valori dell'ampiezza del suono a intervalli regolari):
e quindi riprodurre l'audio (utilizzando il DAC per emettere i valori registrati a intervalli regolari).

In generale, per sintetizzare la batteria, è necessario registrare i suoni della batteria e riprodurli al momento giusto. Nelle console a 8 bit, viene utilizzato il “rumore bianco” al posto dei suoni di batteria. I valori di ampiezza del “rumore bianco” si ottengono utilizzando un generatore numeri casuali. I costi di memoria sono minimi.
hxMidiPlayer utilizza il "rumore bianco" per la sintesi della batteria.

Miscelazione dei canali

L'ampiezza del suono ad un dato tick del timer viene calcolata separatamente per ciascun canale. Per ottenere il valore di ampiezza finale, è necessario sommare i valori di tutti i canali. Esattamente, è necessario aggiustare la somma, poiché il volume percepito obbedisce a una dipendenza logaritmica, ma in un sintetizzatore così semplice dovrai accontentarti di una semplice addizione. Pertanto, l'ampiezza massima di ciascun canale è 255/N.

Emissione del suono dall'AVR

Dopo aver eseguito tutti i calcoli necessari, il lettore riceve il livello del segnale che deve essere convertito in analogico. A tal fine è possibile utilizzare un DAC o PWM esterno.
Va notato qui che in entrambi i casi è consigliabile filtrare il segnale ricevuto - per rimuovere il rumore ad alta frequenza derivante dalla bassa frequenza di sintesi e arrotondamento.

Uscita al DAC parallelo esterno

Poiché non ha senso utilizzare chip DAC precisi, tali progetti di solito si accontentano di una matrice R2R:

Con questo schema, inviamo semplicemente l'ampiezza calcolata alla porta:

PORTAB = campione;

Screpolatura:
1) anche l'output della matrice R2R lo è segnale debole, è obbligatorio l'uso di un amplificatore analogico;
2) è necessario utilizzare almeno 5 pin (e preferibilmente 8);
Questo metodo è giustificato solo quando non sono presenti canali PWM liberi.

(per risparmiare pin è possibile utilizzare un ADC esterno con interfaccia SPI).

PWM

Se è disponibile un canale PWM gratuito, il modo più semplice è utilizzare questo metodo.

Inizializzazione PWM (ATMega8):

// Inizializzazione timer/contatore 2 // Sorgente orologio: orologio di sistema // Valore orologio: 20.000.000 kHz // Modalità: PWM veloce top=0xFF // Uscita OC2: PWM non invertito ASSR=0x00; TCCR2=0x69; CTNT2=0x00; OCR2=0x00; E l'output di esempio: void Player_Output(uint8_t sample) ( OC2 = sample. )

La pratica comune per l'utilizzo del PWM prevede il livellamento del segnale di uscita utilizzando un filtro RC:

Sfortunatamente, dopo il filtraggio il segnale si indebolisce troppo, quindi è necessario realizzare un amplificatore analogico per collegare l'altoparlante.

Per semplificare il circuito è meglio restare “digitali” fino all'altoparlante stesso. Poiché un altoparlante economico non è ancora in grado di riprodurre frequenze superiori a 30 kHz, non è necessario filtrarle. Il diffusore stesso “filtrerà” le alte frequenze PWM.

Se hai bisogno di più corrente, puoi utilizzare un amplificatore a transistor. R1 è selezionato per fornire la corrente richiesta all'altoparlante.

Ecco come puoi collegare piccoli altoparlanti dai giocattoli:

Per gli altoparlanti più grandi è meglio assemblare l'unità utilizzando 2 transistor e installare un filtro LC per rimuovere il rumore:

Il condensatore C1 serve a limitare la corrente attraverso l'altoparlante quando il PWM non funziona. Inoltre, grazie all'inclusione di un condensatore in serie, un segnale simmetrico rispetto allo zero raggiunge l'altoparlante. Pertanto, il cono dell'altoparlante si sposterà rispetto alla posizione centrale “rilassata”, il che ha un effetto positivo sulla qualità del suono.
In questo caso, i transistor funzionano in modalità di commutazione, quindi non è necessario compensare l'offset di base.

PWM, connessione a due pin

Lo svantaggio dei primi due circuiti è che l'altoparlante viene alimentato con corrente in una direzione. Se cambiamo la direzione della corrente, il volume può essere aumentato di 2 volte senza superare la potenza consentita. Per fare ciò, l'altoparlante è collegato a due pin del microcontrollore: non invertito e invertito, ad esempio OC1A e /OC1A. Se non è presente un'uscita non invertita, è possibile utilizzare il secondo canale in modalità invertita (OC1B):

// Inizializzazione timer/contatore 1 // Sorgente clock: orologio di sistema // Valore clock: 24500.000 kHz // Modalità: PWM veloce top=0x00FF // Uscita OC1A: Non-Inv. // Uscita OC1B: invertita // Eliminazione del rumore: disattivata // Acquisizione ingresso su fronte di discesa // Interruzione overflow timer1: disattivata // Interruzione acquisizione ingresso: disattivata // Interruzione confronto corrispondenza A: Disattivato // Interruzione confronto corrispondenza B: Disattivato TCCR1A =0xB1; TCCR1B=0x09; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; void Player_Output(uint8_t campione) ( OCR1A = campione; OCR1B = campione; )

PWM, due pin, amplificatore di classe D

Lo svantaggio dei circuiti proposti è il consumo di corrente durante il silenzio.
Il "silenzio" per noi corrisponde a un livello di segnale di 128, ovvero PWM con riempimento del 50%: la corrente scorre sempre attraverso l'altoparlante!

Modificando leggermente il software, è possibile ottenere un amplificatore di classe D software e hardware abbastanza potente:

Void Player_Output(uint8_t sample) ( if (sample >= 128) ( TCCR2=0x21; //normale, cancella la corrispondenza di confronto TCCR2=0x21 | 0x80; //CLEAR OC2 PORTC.0 = 0; TCCR2=0x69; //non -inversione PWM OCR2 = (campione-128) * 2; ) else // if (campione< 128) { TCCR2=0x31; //normal, set on compare match TCCR2=0x31 | 0x80; //SET OC2 PORTC.0 = 1; TCCR2=0x79; //inverting PWM OCR2 = (128-sample) *2; } }

In questo caso, una coppia di transistor è collegata all'uscita PWM, la seconda all'uscita digitale normale.

Come puoi vedere dal codice, consideriamo un segnale superiore a 128 come una corrente diretta in una direzione e un segnale inferiore a 128 come una corrente diretta nell'altra direzione. A 128, entrambi i pin degli altoparlanti sono collegati allo stesso pin dell'alimentatore e non c'è corrente. Quando si devia dal livello 128, il riempimento PWM aumenta e attraverso l'altoparlante scorre una corrente della polarità corrispondente.

Un punto importante nell'implementazione è la commutazione forzata dell'uscita PWM nello stato desiderato al momento della commutazione del secondo pin (digitale normale) (PORTC.0). La scrittura nel registro OCR2 viene bufferizzata per eliminare i problemi PWM. Dobbiamo commutare immediatamente l'uscita PWM, senza attendere la fine del periodo.

Quest'ultimo circuito è secondo me l'opzione migliore in termini di semplicità, risparmio energetico e potenza erogata.

Uscita audio con forma d'onda SquareWave

Quando si sintetizza un meandro, vengono utilizzati algoritmi semplificati.

Ciascun canale (inclusa la batteria) emette 0 o 1. Pertanto, un giradischi a 3 canali emette valori nell'intervallo 0..3. Pertanto, quando si utilizza PWM, la procedura di output è simile a:

Void Player_Output(uint8_t campione) ( OCR2 = campione * (255 / HXMIDIPLAYER_CHANNELS_COUNT); )

Se non si utilizza PWM, per emettere una melodia a 3 canali sono sufficienti due normali uscite digitali e una matrice R2R a 2 bit.

Formato MIDI

Se guardi il codice della melodia risultante, puoi facilmente vedere che l'array utilizza numeri ripetuti da un intervallo piccolo. Ciò è comprensibile: la melodia utilizza un numero limitato di note entro 1-2 ottave, il tempo della melodia è fisso - ritardi uguali, il numero di canali è compreso tra 0 e 15.
Tutto ciò significa che l'array risultante può essere notevolmente ridotto applicando un qualche tipo di algoritmo di compressione.
Algoritmi come ZIP forniscono una buona compressione, ma richiedono anche molta memoria per funzionare (dizionario ZIP - 64Kb). Possiamo utilizzare un metodo di compressione molto semplice che non richiede praticamente memoria, la cui essenza è la seguente.

In un byte, tutti i numeri sono distribuiti uniformemente nell'intervallo 0...255 e ciascun numero è rappresentato da 8 bit. Nel nostro caso, alcuni numeri sono molto più comuni di altri. Se codifichi i numeri che ricorrono frequentemente con meno bit e quelli che ricorrono meno frequentemente con di più, puoi ottenere un guadagno di memoria.

Scegliamo un metodo di codifica fisso: le combinazioni di bit 000.001 e 010 (lunghezza - 3 bit) rappresenteranno i 3 numeri che ricorrono più frequentemente. Combinazioni di bit 0110, 0111 (lunghezza – 4 bit) – i successivi 2 numeri più comuni, ecc.:

//000..010 - 0..2 //011 x 3..4 //100 xx 5..8 //101 xxx 9..16 //110 xxx 17..24 //111 immediato

La combinazione che inizia con 111 (lunghezza – 11 bit) codificherà tutti gli altri numeri.
Il metodo di codifica bit potrebbe essere diverso. Ho provato diversi metodi e ho scelto questo perché fornisce i migliori risultati su tali dati.

La procedura di compressione è simile alla seguente:
1. Calcola il numero totale del numero X nel flusso per X = .
2. Ordina per frequenza decrescente di apparizione nel flusso.
3. Prendi i primi 25 numeri. Saranno codificati in meno bit.
4. Codificare il flusso di input.

L'output è un array dei 25 numeri che ricorrono più frequentemente e un flusso di bit.
Questa compressione consente di ottenere una compressione del 50% con costi minimi di memoria e prestazioni. Sfortunatamente, questo aumenta il codice del lettore, quindi la compressione non è consigliata per melodie brevi.

Memorizzazione delle frequenze delle note

È piuttosto costoso memorizzare le frequenze di tutte le note in una tabella dalla memoria. Esiste infatti una formula per determinare la frequenza di una nota in base al suo numero midi:

F = 2^((N - 69)/12) * 440, Hz

Ma calcolare il potere frazionario è piuttosto difficile. Invece, il lettore memorizza 12 frequenze di note nell'ottava superiore. Le frequenze delle note nelle ottave inferiori vengono determinate diminuendo la frequenza di altre 2^Y volte, dove Y è il numero di ottave inferiori.

Ulteriore sviluppo della compressione

La melodia contiene spesso frammenti ripetuti ("ritornelli", "versi"). Trovando frammenti ripetuti e presentando la melodia sotto forma di frammenti, puoi ridurre la melodia di un altro 50%, spendendo quasi pochissimo tempo RAM e produttività. Non ho implementato un tale algoritmo per non complicare il progetto.

Descrizione del software

Finestra principale del programma di conversione:

Il pulsante Carica Midi consente di caricare un file midi. Il programma inizia immediatamente a riprodurre il file con i parametri attualmente selezionati, simulando il suono che sarà presente nell'hardware.

La finestra delle informazioni (4) visualizza:
– Lunghezza – lunghezza del frammento della melodia selezionato in ms;
– Canali sintetizzatore attivi massimi: numero massimo di canali del sintetizzatore attivi simultaneamente;
– Max canali di batteria attivi – il numero massimo di canali del sintetizzatore attivi simultaneamente che riproducono “batteria”;
– Max active stereo notes – numero massimo di canali che riproducono la stessa nota (vedi sotto);
– Dimensione stimata, byte – dimensione della melodia in byte. Nella modalità “Custom Sample”, la dimensione viene visualizzata come A+B, dove A è la dimensione della melodia, B è la dimensione del campione. La dimensione del codice giocatore non è specificata qui.

La finestra di avanzamento visualizza la posizione di riproduzione corrente.
È possibile fare clic sulla barra di avanzamento per avviare la riproduzione dal punto specificato.
Le caselle di input a sinistra e a destra consentono di specificare l'inizio e la fine del frammento della melodia in ms.

L'etichetta rossa "Canali insufficienti per riprodurre la melodia" indica che non ci sono abbastanza canali del sintetizzatore per riprodurre la melodia con le impostazioni correnti. Se il lettore non trova un canale libero spegne la nota più vecchia. In molti casi funzionerà bene. Ha senso aumentare il numero di canali solo quando la melodia suona in modo errato all'orecchio.

Le impostazioni possono essere suddivise in impostazioni del lettore e impostazioni di elaborazione del file midi. Il lettore sarà in grado di riprodurre il codice della melodia risultante se la configurazione del lettore e il codice della melodia sono stati creati con le stesse impostazioni del lettore. Inoltre, il lettore potrà riprodurre una melodia il cui codice è stato creato per un lettore con un numero di canali inferiore (ma non maggiore).

Le impostazioni hardware del lettore includono:

– Frequenza di campionamento – frequenza di sintesi. La frequenza massima di fusione viene determinata sperimentalmente. Basato su Atmega 16 MHz, puoi iniziare a 12000 Hz per un lettore a 6 canali e aumentarlo a piacere fino a quando la distorsione della melodia diventa evidente a orecchio nel lettore hardware. La frequenza massima dipende dal numero di canali, dalla forma d'onda e dalla complessità della melodia stessa.

– Forma d'onda – forma d'onda:
– Onda quadra – meandro;
– Seno – seno;
– Sine + Envelope – seno con attenuazione;
– Forma d'onda * + Inviluppo – varie opzioni per onde non sinusoidali con e senza attenuazione;
– Campione personalizzato: utilizza un campione dello strumento.

Il pulsante "Carica campione" consente di caricare un campione da un file WAV. Il file WAV deve essere in formato PCM mono a 8 bit, 4173 Hz, C-5. Suggerimento: puoi aumentare la frequenza e abbassare la nota, ma modificare l'altezza nelle impostazioni del player. Non ci sono controlli sul formato: se il formato è diverso, l'audio non verrà riprodotto correttamente.
Intonazione: consente di modificare l'intonazione del suono. Ad esempio, per suonare 1 ottava più alta, è necessario impostare Pitch +12.

Usa compressione: usa la compressione della melodia.
Abilita sintetizzatore batteria – abilita il sintetizzatore batteria.

Canali del lettore: il numero di canali del sintetizzatore (il numero massimo di note che suoneranno simultaneamente).

Le impostazioni di elaborazione dei file midi includono:

In genere, tale messa a punto non è necessaria. Queste impostazioni possono essere lasciate come predefinite.

API del giocatore

L'implementazione del player si trova nei file Common\hxMidiPlayer.c e Common\hxMidiPlayer.h. Questi file devono essere inclusi nel progetto. È inoltre necessario creare un file hxMidiPlayer_config.h, nel quale inserire la configurazione.
Il lettore è scritto in C senza inserti di assemblaggio, il che ne facilita il trasporto su altri microcontrollori.

Extern void Player_StartMelody(const flash TMelody* _pMelody, uint16_t _delay);

Inizia a suonare la melodia. _delay imposta il ritardo iniziale prima della riproduzione, 255 unità = 1 secondo.

Void Player_Stop();

Smetti di suonare la melodia.

Extern bool Player_IsPlaying();

Restituisce false se la melodia ha finito di suonare.

Extern void Player_WaitFinish();

Attendere fino al termine della riproduzione della melodia.

Extern void Player_TimerFunc();

Questa funzione deve essere richiamata in un interrupt del timer alla frequenza di campionamento specificata nella configurazione. Una volta terminata la riproduzione della melodia, non è necessario effettuare alcuna chiamata.

Extern void Player_Output(uint8_t campione);

Deve essere implementato dall'utente. Chiamato dal lettore quando è necessario emettere il campione successivo.

Extern void Player_Started();

Deve essere implementato dall'utente. Chiamato quando il lettore inizia a riprodurre una melodia. Può essere utilizzato per configurare gli interrupt del timer.

Extern void Player_Finish();

Deve essere implementato dall'utente. Chiamato quando il giocatore ha finito di riprodurre la melodia. Può essere utilizzato per disabilitare le interruzioni del timer o per avviare la riproduzione di un altro brano.

//#define NOTES_TO_EEPROM //#define SINETABLE_TO_EEPROM //#define ENVELOPE_TO_EEPROM

Queste righe devono essere decommentate nel file hxMidiPlayer_config.h se la tabella delle note, la tabella del seno e la tabella dell'attenuazione devono essere posizionate nell'eeprom.

Progetti di esempio

ATMega644Esempio: progetto per ATMega644, 25 MHz, uscita PWM su PB3.

Requisiti di memoria

Tavolo. Dimensioni del lettore e melodie in flash.

*quando si aggiunge un giocatore a un progetto esistente non vuoto, la dimensione del codice sarà inferiore

**non ci sono abbastanza canali per la normale riproduzione della melodia

Melodia 1: bach_minuet_in_g.mid, 35 sec
Melodia 2: yiruma-river_flows_in_you.mid, 165 secondi
Melodia 3: Franz Schubert – Serenata.metà, 217 sec

Come puoi vedere dalla tabella, nella configurazione minima puoi inserire una melodia abbastanza lunga anche nell'ATTiny2313. La compressione può ridurre la melodia di più di due volte, ma la dimensione del codice del lettore aumenta di ~600 byte.

Le tabelle delle note seno e decadimento possono essere inserite nella EEPROM, risparmiando rispettivamente circa 16, 50 e 100 byte di flash.

Quando si utilizza un campione da un file wav, è necessario aggiungere la dimensione del campione in byte alla dimensione del codice del lettore.

Esempio di utilizzo

Come esempio dell'utilizzo di un lettore, consideriamo il processo di creazione di un carillon.

Prendiamo una scatola MDF già pronta:

Come microcontrollore, prendiamo ATTiny85 nel pacchetto SO-8 come il più economico con una quantità di memoria sufficientemente grande. Lo overclockeremo a 27 MHz per ottenere una frequenza di sintesi di 18 KHz con 4 canali Sine+Envelope.

L'amplificatore sarà di classe D con 4 transistor per risparmiare batterie.

I transistor funzionano in modalità di commutazione e possono essere di qualsiasi tipo. L'induttore L1 e il condensatore C6 sono selezionati in base al gusto per ottenere un suono senza rumore ad alta frequenza. R1 e R2 possono essere aumentati fino a 2K per abbassare il volume e ridurre il rimbalzo degli altoparlanti.

Il finecorsa dell'unità disco si adatta perfettamente, come se fosse stato creato appositamente per la scatola (funziona per aprire - quando si apre il coperchio, la scheda viene alimentata):

Le sorgenti del firmware si trovano nella directory ATTiny85MusicBox.

8Kb si adatta:
1) lettore: 18000Hz, 4 canali, Sine+Envelope, Pitch+12, compressione, riproduce le melodie una per una (l'ultima è memorizzata nella EEPROM)
2) Yiruma – Il fiume scorre dentro di te
3) Franz Schubert – Serenata
4) PI Čajkovskij “Ottobre”

Risultato nel video:

Ulteriori sviluppi

In linea di principio, il lettore può essere ulteriormente sviluppato, trasformandolo in un lettore Midi o MOD a tutti gli effetti. Personalmente penso che per ottenere una melodia di alta qualità sarebbe più semplice collegare una scheda SD e riprodurre qualsiasi file WAV da essa con molto di più migliore qualità di quanto sia generalmente possibile ottenere mediante sintesi software. E un lettore del genere è molto più semplice nel software e nell'hardware. La nicchia di hxMidiPlayer è aggiungere un buon suono ai progetti già pronti quando rimangono un paio di gambe e un po' di spazio nel flash. Gestisce questo compito in modo “eccellente” già nella sua forma esistente.

Penso che questo possa risolvere il problema della creazione di tutti i tipi di carillon/campane su AVR :)

Il seguito della lezione è durato molto tempo, il che è comprensibile; ho dovuto padroneggiare il lavoro con schede di memoria e file Sistema FAT. Tuttavia, è successo, la lezione è pronta, in effetti, il miracolo di Capodanno.

Per non sovraccaricare l'articolo di informazioni, non descriverò la struttura del formato file wav, le informazioni sono più che sufficienti nei motori di ricerca. Basti dire che se apri un file con una sorta di editor esadecimale, i primi 44 byte contengono tutte le informazioni sul tipo di file, frequenza di campionamento, numero di canali, ecc. Se hai bisogno di analizzare il file, leggi questo intestazione e sarai felice.

I dati del carico utile iniziano a 44 byte, contenenti essenzialmente i livelli di tensione che compongono il suono. Dei livelli di tensione abbiamo già parlato nell'ultima parte della lezione. Pertanto, tutto è semplice, è necessario trasmettere questi passaggi all'altoparlante alla frequenza di campionamento del file.

Come far tremare fisicamente un altoparlante? È necessario emettere questi livelli di tensione utilizzando PWM o utilizzare R2R. In ogni caso è molto semplice da usare, leggere il numero, inserirlo in OCR o PORTx. Poi, trascorso un certo tempo, ho sostituito il valore successivo e così via fino alla fine del file.

Esempio, un certo file wav, i dati provengono dai byte 44=0x2C, lì è scritto il numero 0x80, riproduciamo il suono, ad esempio, tramite PWM del primo timer, scriviamo OCR1A=0x80; Diciamo che la frequenza di campionamento del campione è 8 kHz, quindi l'interruzione dovrebbe essere impostata sulla stessa frequenza. Nell'interruzione, sostituire il valore successivo 0x85 dopo 1/8000 = 125 µs.

Come impostare l'interruzione su 8kHz? Ricordiamo che se il timer funziona alla frequenza di 250 kHz, allora il registro di confronto degli interrupt deve essere sostituito (250/8)-1=31-1 o 0x1E. Anche con PWM tutto è semplice: maggiore è la frequenza con cui funziona, meglio è.

Affinché il firmware funzioni, concorderemo che l'unità flash sia formattata in FAT32, utilizzando la libreria PetitFat della lezione 23.2. Il file è in formato wav, 8kHz o 22.050kHz, mono. Nome del file 1.wav. Analizziamo il firmware.

#includere #include "diskio.h" #include "pff.h" buffer di caratteri senza segno[ 512 ] ; /* buffer in cui vengono copiate le informazioni dalla chiavetta */ conteggio degli interi volatili senza segno; //contatore dati copiati interruzione [TIM2_COMP] void timer2_comp_isr(void) //interrupt in cui i valori vengono sostituiti(OCR1A = buffer[conteggio]; // invia l'audio all'altoparlante se (++ conteggio >= 512) //incrementa il contatore conteggio = 0; //se 512 viene reimpostato) void main(void) ( unsigned int br; /* contatore di lettura/scrittura del file */ carattere senza segno buf = 0; //variabile che definisce quale parte del buffer viene letta FATFS fs; /* Area di lavoro (oggetto file system) per unità logiche */ PORTAB= 0x00 ; DDRB=0x02; //salta shim ocr1a // Inizializzazione del timer/contatore 1// Sorgente clock: orologio di sistema // Valore clock: 8000.000 kHz // Modalità: PWM veloce top=0x00FF // Uscita OC1A: Non-Inv. TCCR1A= 0x81 ; TCCR1B=0x09 ; CTNT1= 0x00 ; OCR1A=0x00; // Inizializzazione timer/contatore 2// Sorgente orologio: orologio di sistema // Valore orologio: 250.000 kHz // Modalità: CTC top=OCR2 TCCR2= 0x0B ; CTNT2= 0x00 ; //OCR2=0x1E; //imposta il registro di confronto per 8kHz OCR2=0xA; //per 22kHz #asm("sei") // Inizializzazione degli interrupt di timer/contatori/contatori se (disk_initialize() == 0 ) //inizializza l'unità flash(pf_mount(&fs) ; //montare file system pf_open("1.wav" ) ; //apro una discussione pf_lseek(44) ; //sposta il puntatore su 44 pf_read(buffer, 512,& br) ; //per la prima volta inghiottiamo 512 byte contemporaneamente TIMSK= 0x80 ; //accendi la musica mentre (1) ( if (! buf && count> 255 ) //se vengono riprodotti più di 255 byte,( pf_read(& buffer[ 0 ], 256 ,& br) ; //poi leggiamo le informazioni dall'unità flash nella prima metà del buffer bu=1; se (br< 256 ) //se il buffer non contiene 256 valori, significa la fine del file rottura ; ) if (buff && count< 256 ) { pf_read(& buffer[ 256 ] , 256 ,& br) ; // legge la seconda parte del buffer dall'unità flash bu = 0 ; se (br< 256 ) break ; } } TIMSK = 0x00 ; //глушим все pf_mount(0x00 ) ; //smontare il velo) mentre (1 ) ( ) )

#includere #include "diskio.h" #include "pff.h" buffer di caratteri senza segno; /* buffer in cui vengono copiate le informazioni dall'unità flash */ volatile unsigned int count; //contatore dei dati copiati interrupt void timer2_comp_isr(void) //interrupt in cui i valori vengono sostituiti ( OCR1A = buffer; //emette l'audio all'altoparlante se (++count >= 512) //aumenta il conteggio del contatore = 0; //se 512 reset ) void main(void) ( unsigned int br; /* contatore di lettura/scrittura file */ unsigned char buf = 0; //variabile che definisce quale parte del buffer viene letta FATFS fs; /* Funzionante area (oggetto file system) per unità logiche */ PORTB=0x00; DDRB=0x02; //salta lo shim ocr1a // Inizializzazione timer/contatore 1 // Sorgente orologio: orologio di sistema // Valore orologio: 8000.000 kHz // Modalità: PWM veloce top=0x00FF // Uscita OC1A: non inv. TCCR1A=0x81; TCCR1B=0x09; TCNT1=0x00; OCR1A=0x00; // Inizializzazione timer/contatore 2 // Sorgente orologio: orologio di sistema // Valore orologio : 250.000 kHz // Modalità: CTC top= OCR2 TCCR2=0x0B; TCNT2=0x00; //OCR2=0x1E; //impostare il registro di confronto per 8kHz OCR2=0xA; //per 22kHz #asm("sei") // Timer(i)/Contatore(i) Interrupt(i) inizializzazione if(disk_initialize()==0) //inizializza l'unità flash ( pf_mount(&fs); //monta il file system pf_open("1.wav"); //apro il ramo pf_lseek(44); //sposta il puntatore su 44 pf_read(buffer, 512,&br); //per la prima volta ingoiamo 512 byte alla volta TIMSK=0x80; //accendi la musica while(1) ( if(!buf && count>255) //se sono stati riprodotti più di 255 byte, ( pf_read(&buffer, 256,&br);//poi leggi le informazioni dalla flash guidare nella prima metà del buffer buf=1 ; se (br< 256) //если буфер не содержит 256 значений значит конец файла break; } if(buf && count<256) { pf_read(&buffer, 256,&br); // читаем во вторую часть буфера с флешки buf = 0; if (br < 256) break; } } TIMSK = 0x00; //глушим все pf_mount(0x00); //демонтируем фат } while (1) { } }

Per verificare, colleghiamo un altoparlante al pin OCR1A tramite un condensatore da 100uF, “+” al pin del microcontrollore, “-” all'altoparlante. “-” altoparlante a terra, “+” al condensatore.

Non aspettarti un segnale forte in uscita; hai bisogno di un amplificatore per suonare forte. Questo è chiaramente visibile nel video. Per il test ho caricato il gallo con 8 kHz e la traccia con 22 kHz.

Chi lo desidera può tranquillamente aumentare la frequenza del timer2 per riprodurre file a 44 kHz; gli esperimenti dimostrano che è possibile ottenere una qualità del suono abbastanza buona. Nel video l'audio è debole e la qualità è scarsa, ma in realtà ciò è dovuto al fatto che l'ho filmato con una telecamera.

Sto anche postando materiale gentilmente fornito da Apparatchik: il codice sorgente per GCC, da cui è stato scritto il firmware per CAVR.

E video con riproduzione a 44kHz.

Colgo l'occasione per congratularmi con tutti per il nuovo anno, auguro che tutti i firmware e i dispositivi funzionino per voi :)

progetto del lettore wav su Atmega8

Ho scritto un modulo software che ti consente di aggiungere la funzione di riprodurre melodie o sequenze di suoni a quasi tutti i progetti sul microcontrollore AVR.

Caratteristiche del modulo:

Facile integrazione con un progetto già pronto

Viene utilizzato solo il timer t2 a 8 bit, mentre resta possibile utilizzarlo per il polling o per la formazione di intervalli di tempo

Il modulo è regolabile su quasi tutte le frequenze del generatore di clock

L'altezza delle note è specificata come costanti simboliche (C0, A2, ecc.) o in Hertz

Le durate sono specificate in forma standard (quarti, ottavi, ecc.) o in millisecondi

È possibile impostare il tempo di riproduzione della melodia e il numero delle sue ripetizioni

Durante la riproduzione, la melodia può essere messa in pausa


Collegamento di un modulo sonoro

1. Copia tutti i file del modulo (tone.h, sound.h, sound.c) nella cartella del progetto.

2. Collegare il file sound.c al progetto.

Per IAR `a: fare clic con il pulsante destro del mouse nella finestra dell'area di lavoro e selezionare Aggiungi > Aggiungi file...

Per WINAVR è più o meno lo stesso, solo sound.c deve essere aggiunto al makefile:

SRC = $(TARGET).c suono.c

3. Includere il file di intestazione sound.h nel modulo corrispondente. Ad esempio, in main.c

#include "suono.h"

4. Definire le impostazioni del modulo nel file sound.h

//se commenti, la durata delle note sarà

//calcolato dal BPM specificato nella melodia

//se lasciato, quindi dal valore specificato di seguito

//#definisce SUONO_BPM 24

//frequenza di clock μ

#define SUONO_F_CPU 16U

//output del microcontrollore su cui verrà generato il suono

#define PORT_SOUND PORTB

#define PINX_SOUND 0

//numero di melodie specificate.

#define SUONO_AMOUNT_MELODY 4

5. Aggiungi le tue melodie a sound.c e scrivi i nomi delle melodie nell'array delle melodie.

Aggiunta di suonerie

La melodia è una matrice di numeri a 16 bit e ha la seguente struttura

BPM (quarti di note al minuto)è una costante utilizzata per calcolare la durata delle note e determina la velocità con cui viene suonata la melodia.

I BPM possono variare da 1 a 24, che corrispondono rispettivamente a 10 e 240 semiminime al minuto.

Se la durata delle note/suoni è specificata in millisecondi, il BPM scritto nell'array dovrebbe essere uguale a 1.

Se la costante SOUND_BPM è commentata nel file header sound.h, la durata delle note viene calcolata durante l'esecuzione del programma in base al BPM specificato nell'array. Se SOUND_BPM non viene commentato, la durata delle note viene calcolata in fase di compilazione, in base al valore di questa costante, e tutte le melodie verranno riprodotte allo stesso tempo. Ciò limita la funzionalità, ma consente di risparmiare alcuni byte di codice.

Numero di ripetizioni. Può assumere i valori 1...254 e LOOP (255). LOOP - significa che la melodia verrà ripetuta all'infinito finché non verrà dato il comando SOUND_STOP o SOUND_PAUSE.

Durata della nota– il tempo durante il quale viene generato un determinato tono sonoro o viene mantenuta una pausa. Può essere specificato in ms, utilizzando la macro ms(x), o come valori di nota standard: ottavi, sedicesimi, ecc. Di seguito è riportato un elenco delle durate supportate. Se sono necessarie durate esotiche, è sempre possibile aggiungerle nel file tone.h

n1 - nota intera

n2 - mezza nota

n4 - trimestre

n8 - ottavo

n3 - ottava terzina

n16 - sedicesimo

n6 - sestole

n32 - trentaduesimo

Nota intonazione viene specificato utilizzando le costanti simboliche descritte nel file tone.h, ad esempio C2, A1, ecc. Inoltre, l'altezza delle note può essere specificata in Hertz utilizzando la macro f(x).

Il programma ha restrizioni sulla frequenza sonora minima e massima!

Indicatore di fine melodia. Il valore dell'ultimo elemento dell'array deve essere zero.

Utilizzando il modulo sonoro

All'inizio di main, devi chiamare la funzione SOUND_Init(). Questa funzione imposta il pin di uscita del microcontrollore, configura il timer T2 e inizializza le variabili del modulo.

Quindi è necessario impostare il flag di abilitazione dell'interrupt - __enable_interrupt(), poiché il modulo utilizza l'overflow del timer T2 e gli interrupt di coincidenza.

Successivamente, puoi iniziare a suonare le melodie.

Ad esempio, in questo modo:

SUONO_ImpostaCanzone(2);

SUONO_Com(SUONO_RIPRODUZIONE); //suona la melodia

//imposta il puntatore sulla seconda melodia

//e avvia la riproduzione

SUONO_RiproduciCanzone(2);

La riproduzione della melodia può essere interrotta in qualsiasi momento emettendo il comando SOUND_STOP.
Puoi anche mettere in pausa la melodia usando il comando SOUND_PAUSE. La successiva emissione del comando SOUND_PLAY riprende la riproduzione della melodia dal punto in cui era stata interrotta.

In linea di principio, questa funzionalità non è particolarmente necessaria (l'ho appena inventata) e quando si lavora con il modulo è sufficiente la funzione SOUND_PlaySong(unsigned char numSong);

File

Puoi scaricare esempi di utilizzo del modulo sonoro dai link sottostanti. Non ho disegnato uno schema perché lì è tutto semplice. collegato al pin PB0, il pulsante di avvio delle melodie è collegato al pin PD3. Ci sono 4 melodie definite nei progetti. Premendo il pulsante viene avviata ogni volta una nuova melodia. Viene utilizzato il microcontrollore atmega8535. Inizialmente volevo occuparmi di un progetto con quattro pulsanti: PLAY, STOP, PAUSE e NEXT, ma poi ho pensato che non fosse necessario.

PS: il modulo non è stato sottoposto a test approfonditi e viene fornito "così com'è". Se ci sono proposte razionali, finalizziamole.

In questo articolo vedremo come suonare i toni e impareremo come suonare una melodia monofonica.

Preparazione per il lavoro

Il programma dichiara due array. Matrice con note Appunti contiene un semplice elenco di note. Queste note sono abbinate alla durata del suono nell'array batte. La durata nella musica è determinata dal divisore di una nota rispetto all'intera nota. Il valore preso come nota intera è 255 . Dividendo questo numero si ottengono metà, quarti, ottavi.
Tieni presente che la durata della prima nota non si ottiene dividendo 255 per una potenza di due. Qui dovrai passare alla teoria musicale. È possibile visualizzare le note della melodia originale. Queste note sono combinate in terzine. Se combinati in questo modo, tre crome suonano come una nota da un quarto. Pertanto la loro durata relativa è 21.
L'utente deve inoltre specificare esplicitamente il numero di note nella sequenza con la direttiva:

# definisce SEQU_SIZE 19

Nel programma principale vengono innanzitutto ricalcolati gli array di frequenze e la durata in periodi dei segnali e la durata delle note.
Con periodi di segnale (array periodo_segnale) tutto è semplice. Per ottenere la durata del periodo in microsecondi, dividi semplicemente 1.000.000 per la frequenza del segnale.
Per calcolare la durata assoluta del suono delle note è necessario che sia indicato il tempo dell'opera musicale. Ciò avviene tramite direttiva

# definisce il TEMPO 108

Il tempo nella musica è il numero di semiminime al minuto. In linea

# definisce WHOLE_NOTE_DUR 240000 / TEMPO

Viene calcolata la durata di un'intera nota in millisecondi. Ora è sufficiente ricalcolare i valori relativi dall'array utilizzando la formula batte all'array assoluto nota_durata.
Nel ciclo principale, la variabile tempo trascorso viene incrementato dopo ogni periodo del segnale riprodotto della durata di questo periodo finché non supera la durata della nota. Vale la pena prestare attenzione a questa voce:

while(tempo_trascorso< 1000 * ((uint32_t) note_duration[ i] ) )

Variabile tempo trascorso 32 bit e gli elementi dell'array note_durata 16 bit. Se un numero a 16 bit viene moltiplicato per 1000, è garantito un overflow e la variabile tempo trascorso sarà paragonato alla spazzatura. Modificatore (uint32_t) converte un elemento dell'array note_durata[i] in un numero a 32 bit non c'è overflow.
Puoi vedere un'altra funzionalità nel loop audio. Non sarà possibile utilizzare la funzione _delay_us(), poiché il suo argomento non può essere una variabile.
Per creare tali ritardi, utilizzare la funzione VarDelay_us(). In esso, un ciclo con un ritardo di 1 μs viene fatto scorrere un numero specificato di volte.

void VarDelay_us(uint32_t takt) ( while (takt- - ) ( _delay_us(1 ) ; ) )

Quando si suona una melodia, vengono utilizzati altri due ritardi. Se le note vengono suonate senza pause, si fonderanno in una sola. Per fare ciò viene inserito tra loro un ritardo di 1ms, specificato dalla direttiva:

# definisce NOTE_PAUSA 1

Dopo ogni ciclo completo di riproduzione della melodia, il programma si ferma per 1 secondo e riprende la riproduzione.
Di conseguenza, abbiamo ricevuto un codice in cui è facile cambiare il tempo, regolare la durata o riscrivere completamente la melodia. Per fare ciò basterà trasformare solo la parte del programma contenente direttive e dichiarazioni di variabili.

Compiti individuali

  1. Nella melodia proposta, prova a cambiare il tempo e fai una pausa di 5 secondi tra una ripetizione e l'altra.
  2. Elementi della matrice batte accetta solo valori da 0 a 255. Modifica la larghezza in bit degli elementi dell'array e guarda nell'output del compilatore per vedere come ciò influisce sulla quantità di memoria occupata dal programma.
  3. Ora prova a cambiare tu stesso la melodia. Ad esempio, ecco "Imperial March" dallo stesso film: int notes = ( A4, R, A4, R, A4, R, F4, R, C5, R, A4, R, F4, R, C5, R, LA4, RE, MI5, RE, MI5, RE, MI5, RE, FA5, RE, DO5, RE, SOL5, RE, FA5, RE, DO5, RE, LA4, RE); battiti interi = ( 50 , 20 , 50 , 20 , 50 , 20 , 40 , 5 , 20 , 5 , 60 , 10 , 40 , 5 , 20 , 5 , 60 , 80 , 50 , 20 , 50 , 20 , 50 , 20, 40, 5, 20

    Se la tua auto non ha una sirena sonora installata e non riesci ancora a decidere quale acquistare e installare, allora questo articolo fa proprio al caso tuo. Perché acquistare allarmi costosi se puoi assemblarli tutti da solo in modo abbastanza semplice?

    Ne presento due circuiti semplici sui microcontrollori AVR ATmega8 e Attiny2313, o meglio lo stesso circuito è semplicemente implementato per funzionare su questi due microcontrollori. A proposito, nell'archivio troverai due versioni del firmware per il microcontrollore Atmega8, di cui la prima riproduce un suono simile a allarme dell'auto, e il secondo suono è simile all'allarme di sicurezza dell'edificio (segnale veloce e acuto).

    Potete scaricare tutti i firmware qui sotto nell'archivio (sono tutti firmati), nell'archivio troverete anche una simulazione dei circuiti in Proteus, questo significa che dopo aver ascoltato tutti i brani potrete scegliere dalla lista quello che vi piace di più .

    Di seguito è riportato il diagramma di segnalazione per Atmega8

    Elenco dei componenti radio utilizzati nel circuito Atmega8

    U1- Microcontrollore AVR ATmega8-16PU a 8 bit, quantità. 1,
    R1- Resistenza da valore nominale di 47 Ohm, n. 1,
    R2, R3 - Resistore da valore nominale di 270 Ohm, n. 2,
    D2,D3-LED, n. 2,
    Altoparlante LS1, n. 1,
    Sensore S1.

    E nel circuito di segnalazione su Attiny2313 è stato modificato solo MK.
    U1- Microcontrollore AVR 8 bit ATtiny2313-20PU, quantità. 1.

    Scheda a circuito stampato per Atmega8 assomiglia a questo:

    Come puoi vedere, il circuito è molto semplice, c'è solo un microcontrollore, 3 resistori, 2 LED e un altro altoparlante. Invece di un pulsante, puoi utilizzare un interruttore reed o un altro contatto.

    Il principio di funzionamento è il seguente. Non appena diamo alimentazione, il LED (nel circuito D3) si accende immediatamente o inizia a lampeggiare (a seconda del firmware) e se non tocchiamo il sensore l'allarme sarà silenzioso. Ora, se il sensore viene attivato, funzionerà anche la sirena, anche il LED lampeggerà, ma D2.

    Se vuoi che i fari dell'auto lampeggino quando l'allarme è in funzione, per fare ciò devi collegare il pin del microcontrollore 24 PC1 al relè tramite un transistor e il relè stesso ai fari. Per disattivare la sirena è necessario spegnere e riaccendere il dispositivo oppure semplicemente premere il pulsante. Per far funzionare il microcontrollore è necessario un oscillatore interno da 8 MHz,

    Se vuoi migliorare in qualche modo il suono dell'allarme, puoi assemblare un amplificatore con transistor e collegarlo al circuito. Questo è esattamente quello che ho fatto, ma non l’ho rappresentato in questo diagramma.

    Passiamo al circuito dell'Attiny 2313, come ho detto prima, ha tutti gli stessi dettagli e lo stesso principio di funzionamento, è stato cambiato solo il MK e di conseguenza i pin collegati. Questo microcontrollore funziona da un oscillatore interno da 4 MHz, sebbene possa essere flashato a 1 MHz.

    Di seguito lo schema di collegamento già presente su Attiny2313

    Per questo MK ho scritto solo una versione del firmware, ho assemblato tutto sul circuito, l'ho controllato, funziona tutto bene.
    E i fusibili devono essere impostati come mostrato di seguito:





Superiore