from machine import Pin, ADC, PWM
from time import sleep_ms
import math # Додано для математичних обчислень
# ==============================================================================
# НАЛАШТУВАННЯ ПЕРИФЕРИИ
# ==============================================================================
volume_pot = ADC(Pin(34))
volume_pot.atten(ADC.ATTN_11DB)
volume_pot.width(ADC.WIDTH_12BIT)
BUZZER_PIN = 18
TONE_FREQUENCY = 1000
buzzer = PWM(Pin(BUZZER_PIN), freq=TONE_FREQUENCY, duty_u16=0)
LED_PIN = 19
LED_FREQUENCY = 1000
led = PWM(Pin(LED_PIN), freq=LED_FREQUENCY, duty_u16=0)
# ==============================================================================
# ДОПОМІЖНІ ФУНКЦІЇ
# ==============================================================================
def read_average(adc, samples=10):
total = 0
for _ in range(samples):
total += adc.read()
sleep_ms(2)
return total // samples
def map_value(value, input_min, input_max, output_min, output_max):
return int((value - input_min) * (output_max - output_min) / (input_max - input_min) + output_min)
def map_volume_log(value, input_max=4095, max_duty=32768):
"""
Перетворює лінійне значення потенціометра (0-4095) в експоненційну
криву ШІМ (0-32768) для компенсації логарифмічного слуху.
"""
if value < 50:
return 0
# Обчислюємо коефіцієнт від 0.0 до 1.0
normalized = value / input_max
# Експоненційна крива: x^3 або x^4 дає найкращий ефект для слуху
log_duty = int((normalized ** 3) * max_duty)
return log_duty
# ==============================================================================
# ОСНОВНИЙ ЦИКЛ ПРОГРАМИ
# ==============================================================================
print("Проєкт «Логарифмічний регулятор гучності» запущено")
while True:
pot_value = read_average(volume_pot)
# Відсоток гучності залишаємо лінійним для красивого відображення (0–100%)
volume_percent = map_value(pot_value, 0, 4095, 0, 100)
# ЗАСТОСОВУЄМО КОРЕКЦІЮ ГУЧНОСТІ ДЛЯ БУЗЕРА
buzzer_duty = map_volume_log(pot_value)
# Для світлодіода залишаємо звичайне плавне регулювання
led_duty = map_value(pot_value, 0, 4095, 0, 65535)
if pot_value < 50:
buzzer.duty_u16(0)
led.duty_u16(0)
volume_percent = 0
else:
buzzer.duty_u16(buzzer_duty)
led.duty_u16(led_duty)
# Виводимо також реальне значення Duty для відстеження різниці
print(f"Потенціометр: {pot_value:4d} | ШІМ бузера: {buzzer_duty:5d} | Гучність: {volume_percent:3d}%")
sleep_ms(100)