Generátor tónov
Zo stránky SensorWiki
Záverečný projekt predmetu MIPS / LS2026 - Oliver Szabo
Zadanie
Cieľom projektu bolo vytvoriť generátor tónov, ktorého frekvencia je riadená potenciometrom. Hodnota získaná z analógového vstupu mikrokontroléra pomocou A/D prevodníka sa spracuje programom a následne sa použije na generovanie zvukového signálu na bzučiaku.
Používateľ môže otáčaním potenciometra plynule meniť frekvenciu generovaného tónu.

Literatúra:
Analýza a opis riešenia
Pri realizácii projektu bola použitá vývojová doska ACROB s mikrokontrolérom ATmega328P, potenciometer a piezo bzučiak.
Potenciometer slúži ako analógový ovládací prvok. Zmenou polohy potenciometra sa mení napätie privádzané na vstup A4, ktoré je následne prevádzané A/D prevodníkom na digitálnu hodnotu v rozsahu 0 až 1023.
Bzučiak je pripojený na digitálny výstup D6 (PD6). Program podľa nameranej hodnoty z potenciometra vypočíta frekvenciu tónu v rozsahu približne 100 Hz až 2000 Hz.

Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.

Algoritmus a program
Program najprv nastaví pin D6 ako výstup pre bzučiak. Následne v nekonečnej slučke vykonáva meranie hodnoty potenciometra pomocou A/D prevodníka na vstupe A4. Nameraná hodnota ADC sa lineárne prepočíta na frekvenciu v rozsahu približne 100 Hz až 2000 Hz. Ak je hodnota potenciometra veľmi nízka, bzučiak zostáva vypnutý. V opačnom prípade sa na výstupe D6 generuje tón zodpovedajúcej frekvencie.
Zdrojový kód obsahuje dve hlavné funkcie:
- read_adc() – zabezpečuje meranie analógovej hodnoty z potenciometra. - tone_sw() – generuje tón softvérovým prepínaním výstupu D6.
/*
* projekt.c
*
* Created: 5. 6. 2026 10:56:31
* Author: Oliver Szabo
*/
#include <avr/io.h>
#include <util/delay.h>
// Bzuciak na D6 = PD6, breadboard
#define BUZZER_DDR DDRD
#define BUZZER_PORT PORTD
#define BUZZER_PIN PD6
// freq_hz = frekvencia, duration_ms = ako dlho bzuci (napr. 50)
void tone_sw(uint16_t freq_hz, uint16_t duration_ms) {
if (freq_hz == 0) {
BUZZER_PORT &= ~(1 << BUZZER_PIN); // Ticho
_delay_ms(50);
return;
}
// Polovicna perioda v mikrosekundach
// T = 1/f, polovica = 500000/f [us]
uint16_t half_period_us = 500000UL / freq_hz;
// Pocet toggleov za duration_ms
// Jeden toggle = half_period_us mikrosekund
// Celkovy cas = duration_ms * 1000 us
uint16_t toggles = (uint32_t)duration_ms * 1000 / half_period_us;
for (uint16_t i = 0; i < toggles; i++) {
BUZZER_PORT ^= (1 << BUZZER_PIN); // Toggle pin
// Cakaj half_period_us mikrosekund
uint16_t t = half_period_us;
while (t--) {
__asm__("nop"); // 1 nop = 1 cyklus = 62.5ns pri 16MHz
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop"); // 16 nop = ~1 mikrosekunda pri 16MHz
}
}
}
// Precita ADC hodnotu z kanala, vracia 0..1023
uint16_t read_adc(uint8_t channel) {
ADMUX = (1 << REFS0) | (channel & 0x07);
ADCSRA = (1 << ADEN) | (1 << ADSC)
| (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
while (ADCSRA & (1 << ADSC));
return ADC;
}
int main(void) {
BUZZER_DDR |= (1 << BUZZER_PIN); // D6 ako vystup
while (1) {
uint16_t adc = read_adc(4); // Citaj A4 - potenciometer
if (adc < 10) {
tone_sw(0, 50); // Ticho
} else {
// ADC 0..1023 -> 100..2000 Hz
uint16_t freq = 100 + (uint32_t)adc * 1900 / 1023;
tone_sw(freq, 50); // Bzuci 50ms na danej frekvencii
}
}
}
#include <avr/io.h>
void adc_init(void); // A/D converter initialization
unsigned int adc_read(char a_pin);
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:
Zdrojový kód: zdrojaky.zip
Overenie
Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku hotového zariadenia.

Video:
Čo by som urobil inak
Zamyslite sa spätne nad problémom, ktorý ste riešili a napíšte, čo sa vám nepodarilo a nabudúce by ste spravili inak.
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.