from machine import Pin, ADC, SoftI2C
import time
import ssd1306
from encoder import Encoder # Импортируем класс Encoder из файла encoder.py
# Функция для форматирования частоты
def format_frequency(frequency):
frequency = round(frequency / 10) * 10
megahertz = frequency // 1000000
kilohertz = (frequency % 1000000) // 1000
hertz = (frequency % 1000) // 10
return f"{megahertz}.{kilohertz:03}.{hertz:02}"
# Функция для форматирования шага
def format_step(step):
return f"{step}Hz"
# Инициализация OLED
i2c = SoftI2C(scl=Pin(21), sda=Pin(20))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# Инициализация энкодера
encoder = Encoder(pin_a=16, pin_b=15, base_frequency=14100000, step=50)
# Инициализация кнопок
button_step = Pin(4, Pin.IN, Pin.PULL_UP) # Кнопка STEP (GPIO4)
button_mode = Pin(5, Pin.IN, Pin.PULL_UP) # Кнопка MODE (GPIO5)
button_rit = Pin(6, Pin.IN, Pin.PULL_UP) # Кнопка RIT (GPIO6)
# Инициализация выходного пина
output_pin = Pin(18, Pin.OUT) # GPIO18 настроен как выход
# Инициализация ADC для S-meter
adc_s_meter = ADC(Pin(14)) # GPIO14 для S-meter
# Инициализация ADC для RIT
adc_rit = ADC(Pin(13)) # GPIO13 для RIT
adc_rit.atten(ADC.ATTN_11DB) # Установка диапазона 0–3.3 В
# Инициализация пина для режима TX/RX
tx_rx_pin = Pin(9, Pin.IN, Pin.PULL_UP) # GPIO9 для режима TX/RX
# Инициализация пина для светодиода TX
tx_led_pin = Pin(2, Pin.OUT) # GPIO2 для светодиода TX
# Переменная для хранения текущего шага
current_step_index = 0
steps = [50, 100, 200] # Возможные значения шага
# Переменная для хранения текущего режима
modes = ["CW ", "SSB"] # Режимы CW и SSB (добавлен пробел к CW)
current_mode_index = 0
# Флаг для режима RIT
rit_enabled = False
# Хранение базовой частоты для RIT
base_frequency = encoder.get_frequency()
# Предыдущее значение S-meter для оптимизации обновления OLED
prev_s_meter_value = None
# Основной цикл программы
while True:
# Обработка кнопки STEP для изменения шага
if button_step.value() == 0: # Кнопка нажата (активный уровень 0)
if not rit_enabled: # Шаг изменяется только если режим RIT выключен
current_step_index = (current_step_index + 1) % len(steps) # Циклический выбор шага
new_step = steps[current_step_index]
encoder.set_step(new_step) # Устанавливаем новый шаг
time.sleep_ms(200) # Дебаунсинг кнопки
# Обработка кнопки MODE для изменения режима
if button_mode.value() == 0: # Кнопка нажата (активный уровень 0)
if not rit_enabled: # Режим CW/SSB меняется только если RIT выключен
current_mode_index = (current_mode_index + 1) % len(modes) # Циклический выбор режима
current_mode = modes[current_mode_index].strip() # Убираем пробел для логики
# Устанавливаем значение на выходном пине
output_pin.value(0 if current_mode == "CW" else 1)
# Логирование в консоль
print(f"Changed to: {current_mode}, Output signal: {output_pin.value()}")
# Явное обновление OLED
oled.fill(0) # Очистка экрана
frequency = encoder.get_frequency()
formatted_frequency = format_frequency(frequency)
current_step = encoder.get_step()
formatted_step = format_step(current_step)
oled.text(formatted_frequency, 0, 0) # Вывод частоты
# Сдвиг шага или RIT влево на 16 пикселей
oled.text("RIT" if rit_enabled else formatted_step, 128 - len("RIT") * 8 - 16, 0) # Шаг или RIT сдвинут влево
# Вывод S-meter слева и режима справа во второй строке
mode_text = modes[current_mode_index] # Берем текст с пробелом для CW
s_meter_text = f"S-meter {prev_s_meter_value}"
oled.text(s_meter_text, 0, 20) # S-meter слева
# Сдвиг режима влево на 8 пикселей
oled.text(mode_text, 128 - len(mode_text) * 8 - 8, 20) # Режим сдвинут влево
oled.show() # Обновление дисплея
time.sleep_ms(200) # Дебаунсинг кнопки
# Обработка кнопки RIT для включения/выключения режима RIT
if button_rit.value() == 0: # Кнопка нажата (активный уровень 0)
rit_enabled = not rit_enabled # Переключаем флаг режима RIT
if rit_enabled:
# Сохраняем базовую частоту при включении RIT
base_frequency = encoder.get_frequency()
print("RIT mode enabled")
else:
# Сбрасываем частоту до исходной при выходе из RIT
encoder.set_frequency(base_frequency)
print("RIT mode disabled")
# Явное обновление OLED
oled.fill(0) # Очистка экрана
frequency = encoder.get_frequency()
formatted_frequency = format_frequency(frequency)
current_step = encoder.get_step()
formatted_step = format_step(current_step)
oled.text(formatted_frequency, 0, 0) # Вывод частоты
# Сдвиг шага или RIT влево на 16 пикселей
oled.text("RIT" if rit_enabled else formatted_step, 128 - len("RIT") * 8 - 16, 0) # Шаг или RIT сдвинут влево
# Вывод S-meter слева и режима справа во второй строке
mode_text = modes[current_mode_index] # Берем текст с пробелом для CW
s_meter_text = f"S-meter {prev_s_meter_value}"
oled.text(s_meter_text, 0, 20) # S-meter слева
# Сдвиг режима влево на 8 пикселей
oled.text(mode_text, 128 - len(mode_text) * 8 - 8, 20) # Режим сдвинут влево
oled.show() # Обновление дисплея
time.sleep_ms(200) # Дебаунсинг кнопки
# Проверка режима TX/RX
tx_mode = tx_rx_pin.value() == 0 # TX активен, если пин замкнут на землю
if tx_mode:
# В режиме TX загорается светодиод
tx_led_pin.value(1)
# В режиме TX игнорируем частоту RIT и используем базовую частоту
if rit_enabled:
encoder.set_frequency(base_frequency)
print("TX mode: Using base frequency")
else:
# В режиме RX гаснет светодиод
tx_led_pin.value(0)
# В режиме RX восстанавливаем частоту RIT, если он включен
if rit_enabled:
adc_value = adc_rit.read_u16() # Чтение значения ADC (0–65535)
voltage = adc_value * 3.3 / 65535 # Преобразование в напряжение (0–3.3 В)
frequency_offset = int((voltage - 1.65) * (1000 / 1.65)) # Линейное преобразование ±1 кГц
new_frequency = base_frequency + frequency_offset
encoder.set_frequency(new_frequency) # Установка новой частоты
# Чтение значения ADC для S-meter и масштабирование
adc_value = adc_s_meter.read_u16() # Чтение значения ADC (0–65535)
voltage = adc_value * 3.3 / 65535 # Преобразование в напряжение (0–3.3 В)
s_meter_value = 5.0 + (voltage / 3.3) * 0.9 # Масштабирование к диапазону 5.0–5.9
s_meter_value = round(s_meter_value, 1) # Округление до одного знака после запятой
# Обновление OLED только при изменении значений
if s_meter_value != prev_s_meter_value or encoder.update_oled:
prev_s_meter_value = s_meter_value
frequency = encoder.get_frequency()
formatted_frequency = format_frequency(frequency)
current_step = encoder.get_step()
formatted_step = format_step(current_step)
oled.fill(0) # Очистка экрана
oled.text(formatted_frequency, 0, 0) # Вывод частоты
# Сдвиг шага или RIT влево на 16 пикселей
oled.text("RIT" if rit_enabled else formatted_step, 128 - len("RIT") * 8 - 16, 0) # Шаг или RIT сдвинут влево
# Вывод S-meter слева и режима справа во второй строке
mode_text = modes[current_mode_index] # Берем текст с пробелом для CW
s_meter_text = f"S-meter {prev_s_meter_value}"
oled.text(s_meter_text, 0, 20) # S-meter слева
# Сдвиг режима влево на 8 пикселей
oled.text(mode_text, 128 - len(mode_text) * 8 - 8, 20) # Режим сдвинут влево
oled.show() # Обновление дисплея
encoder.update_oled = False # Сбрасываем флаг
time.sleep(0.1) # Небольшая задержка для снижения нагрузки на процессор