Декодер медленного телевидения (SSTV), часть 2
Jоn Dаwsоn
https://101-things.readthedocs.io/en/latest/sstv_decoder_part2.html
Новые режимыВ первой части этого проекта продемонстрирован очень простой декодер SSTV, использующий Raspberry Pi Pico (RP2040) и недорогой TFT-дисплей ILI9341. Проект вызвал большой интерес, и я получил множество запросов и предложений, включая добавление новых режимов и функций. В этом обновлении я улучшил декодер SSTV, добавив более продвинутые функции, такие как кодировщик, поддержка SD-карт и меню-ориентированный пользовательский интерфейс. Проект вырос из простого скетча для Arduino в библиотеку функций SSTV, которую можно использовать в других проектах, с набором примеров схем для начала работы.Наиболее востребованными режимами являются PD120 и PD180. Именно эти режимы используются МКС для периодических передач из космоса. Это были первые новые режимы, которые были реализованы. Разрешение этих режимов значительно выше, чем у существующих режимов Мартина/Скотти, поэтому их пришлось уменьшить, чтобы они поместились на дисплее ILI9341.
На сайте Spacecomms можно скачать ряд аудиофайлов , которые были должным образом протестированы с помощью декодера Pico SSTV.
Некоторые режимы было довольно просто реализовать, внеся изменения в существующие режимы. Режимы SC2 и ScottieDX можно было реализовать, изменив временные параметры существующих режимов. Режимы Robot24, Robot36 и Robot72 сложнее. В этих режимах используется кодирование yCrCb. Режим Robot 36 особенно сложно декодировать с использованием текущей архитектуры, поскольку компоненты Cr и Cb передаются попеременно в строках развертки. Дополнительная синхронизация (вроде бы) в 1500 Гц указывает на то, что строка развертки содержит информацию Cr, а 2300 Гц — на то, что строка развертки содержит информацию Cb. Благодарность Франциску Капуцци (IS0JSV) за его остроумный метод обнаружения и правильного декодирования цветности в этих режимах. В дополнение к цветным режимам Robot, декодер теперь также поддерживает черно-белые режимы Robot. Библиотека
![]()
Оригинальный декодер SSTV использовал очень простую схему, и код был предоставлен в виде простого скетча. Я хотел добавить ряд новых функций, для которых потребуется другое (дополнительное) оборудование. Я хотел создать программное обеспечение, поддерживающее существующее оборудование, а также новое оборудование с более полным набором функций.
Я решил, что наилучшим подходом будет переход от скетча Arduino к созданию библиотеки Arduino. Одно из преимуществ библиотек Arduino — возможность включать множество примеров кода. Я решил использовать эту функцию, чтобы предоставить несколько различных примеров проектов, от самых простых до более полных.
sstv_receive_tft — Аналогично оригинальной конструкции, поддерживает оригинальное оборудование, но с новыми режимами.
sstv_recieve_sd — добавляет в базовую конструкцию простую функцию автоматической записи данных на SD-карту.
sstv_transmit_basic — минимальный пример только для передачи. Передает изображение с SD-карты.
sstv_full — Функции приема и передачи, хранение данных на SD-карте и полнофункциональный пользовательский интерфейс с меню.
Я надеялся, что преобразование проекта SSTV в библиотеку позволит повторно использовать код в других проектах и ??на различных аппаратных платформах. Проект Wio Terminal SSTV Франциску Капуцци (IS0JSV) представляет собой действительно замечательное устройство SSTV и является отличным примером того, как можно использовать библиотеку.
Если вы следили за развитием проекта Pi Pico Rx , вам может быть интересно узнать, что теперь приемник включает в себя встроенный декодер, основанный на этой библиотеке.
![]()
![]()
Пример встроенного SSTV-декодера в приемник Pi-Pico RXХранение изображений на SD-карте
![]()
Схема подключения SD-картыSDCARD_MISO 4 SDCARD_MOSI 7 SDCARD_CS 5 SDCARD_SCK 6Одна из самых востребованных функций — хранение данных на SD-карте. Это значительно повышает удобство использования устройства, поскольку позволяет автоматически сохранять полученные изображения, а значит, декодер можно оставлять без присмотра. Я оставлял свой декодер работать на несколько дней подряд и периодически проверяю, что пришло.
Хотя можно приобрести держатели для SD-карт, я решил использовать держатель, встроенный в большинство дисплеев ILI9341. Для подключения шины SPI к SD-карте требуется всего несколько дополнительных проводов. Я выбрал библиотеку SDFS, входящую в состав ядра Arduino Pico. Кроме того, библиотека VFS позволяет получать доступ к SD-карте с помощью стандартных функций библиотеки C.
Для хранения изображений я написал очень простую библиотеку, которая позволяет загружать и сохранять изображения в формате .bmp. Преимущество хранения на SD-картах заключается в том, что они позволяют сохранять изображения в полном разрешении, даже если их приходится уменьшать для отображения на TFT-дисплее.
SSTV-кодер (передатчик)
![]()
Схема подключения для передачи данныхПо сравнению с декодером, кодер относительно прост в реализации. Аудиосигнал генерируется с помощью ШИМ, после чего используется фильтр и конденсатор, блокирующий постоянный ток. Код для обработки ШИМ-сигнала был заимствован из других проектов.
Процесс кодирования всегда начинается с фиксированной последовательности, состоящей из двух 300-миллисекундных импульсов с частотой 1900 Гц. Функция generate_tone принимает два параметра: частоту и длительность. Я использую 16 бит дробной части для представления длительности в миллисекундах. Высокое разрешение необходимо для поддержания точных временных параметров на протяжении всего времени передачи изображения. После этого кодирование изображения зависит от режима передачи.
void c_sstv_encoder :: generate_sstv(e_sstv_tx_mode mode) { generate_tone(1900, 300 << 16); generate_tone(1200, 10 << 16); generate_tone(1900, 300 << 16); generate_vis_code(mode); //... generate_martin(mode); }Процесс кодирования обрабатывает изображение построчно. Каждая строка состоит из импульса для каждого цвета (RGB в случае Мартина). Каждый пиксель состоит из короткого импульса с частотой от 1500 Гц до 2300 Гц, с интервалом в 1500 Гц между цветами. В конце каждой строки отправляется горизонтальный синхронизирующий импульс с частотой 1200 Гц.
void c_sstv_encoder :: generate_martin(e_sstv_tx_mode mode) { uint16_t width, height; float colour_time_ms; switch(mode) { case tx_martin_m1: width = 320; height = 240; colour_time_ms = 146.320; break; case tx_martin_m2: width = 320; height = 240; colour_time_ms = 73.216; break; default: return; } uint32_t hsync_pulse_ms_f16 = 4.862 * (1<<16); uint32_t colour_gap_ms_f16 = 0.572 * (1<<16); uint32_t pixel_time_ms_f16 = (colour_time_ms*(1<<16))/width; //send rows for(uint16_t row=0u; row < height; ++row) { generate_tone(1500, colour_gap_ms_f16); for(uint16_t col=0u; col < width; ++col) generate_tone(get_pixel(width, height, row, col, 1), pixel_time_ms_f16); generate_tone(1500, colour_gap_ms_f16); for(uint16_t col=0u; col < width; ++col) generate_tone(get_pixel(width, height, row, col, 2), pixel_time_ms_f16); generate_tone(1500, colour_gap_ms_f16); for(uint16_t col=0u; col < width; ++col) generate_tone(get_pixel(width, height, row, col, 0), pixel_time_ms_f16); generate_tone(1500, colour_gap_ms_f16); generate_tone(1200, hsync_pulse_ms_f16); } }Функция generate_tone преобразует значение времени в миллисекундах с фиксированной запятой в значение количества отсчетов с фиксированной запятой. Если количество отсчетов имеет дробную часть, мы округляем в меньшую сторону, но сохраняем дробную часть. Дробные части накапливаются, чтобы их можно было компенсировать позже для поддержания точных долговременных временных характеристик.
void c_sstv_encoder :: generate_tone(uint16_t frequency, uint32_t time_ms_f16) { uint32_t samples_exact_f16 = (m_Fs_Hz*time_ms_f16/1000) + m_residue_f16; uint32_t samples = samples_exact_f16 >> 16u; m_residue_f16 = samples_exact_f16-(samples << 16u); output_samples(frequency, samples); }Сами тоны генерируются с помощью простого фазового аккумулятора. Фазовый аккумулятор имеет высокое разрешение. 10 старших битов фазового аккумулятора управляют таблицей поиска, предварительно запрограммированной 16-битной синусоидальной волной. Сгенерированный сэмпл затем отправляется на ШИМ-аудиомодуль для вывода.
void c_sstv_encoder :: output_samples(uint32_t frequency, uint16_t samples) { uint32_t step = (static_cast<uint64_t>(frequency)<<32)/m_Fs_Hz; for(uint16_t idx = 0; idx < samples; ++idx) { output_sample(m_sin_table[m_phase >> 22]); m_phase += step; } }Полный пример - Кодировщик/декодировщик с меню
В то время как базовые примеры предоставляют минимальный код, необходимый для приема или передачи сигнала SSTV, этот пример более полный и включает в себя многие функции, присущие программному обеспечению SSTV для ПК. Помимо функций передачи и приема, этот пример предлагает более расширенные возможности, включая пользовательский интерфейс, позволяющий просматривать файлы и настраивать параметры.
Схема подключения для передачи данныхПользовательский интерфейс использует дополнительные 4 кнопки для управления меню, а схема во многом похожа на конструкцию планетария . Меню позволяет пользователю переключаться между режимами передачи, приема, просмотра файлов (слайд-шоу), а также предоставляет меню настроек, позволяющее настраивать конфигурацию декодера.
В состав ядра Arduino Pico входит библиотека для эмуляции EEPROM с использованием встроенной флэш-памяти Pi Pico. Эта функция используется для хранения пользовательских настроек и их восстановления после каждого выключения и включения питания.
Элемент
Количество
Пример URL
Примечания
Дисплей ILI9341 или ILI9342 с разрешением 320x240 (SPI)
1
Для получения изображений
Raspberry Pi Pico
1
Микроконтроллер Резистор 10 кОм
2
Для получения изображений
Керамический конденсатор 100 нФ
2
1 для передачи, 1 для приема
Резистор 100 Ом
2
Для передачи изображений
Керамический конденсатор 470 нФ
1
Для передачи изображений
Стереоразъем 3,5 мм
1
1 для передачи, 1 для приема
Тактильные кнопки 6 мм
4
Для интерфейса с меню
SD-карта
1
Примеры использования SD-карт
Корпус, напечатанный на 3D-принтере
1
(Примечание: ссылки приведены в иллюстративных целях и не обязательно являются рекомендациями.)
Подключение дисплея (распиновка) показана ниже:
Сигнал
Номер пина
ДисплеяНомер пина Пико
Номер Pico
GPIOVcc
1
36 (3v3 out)
NA
GND
2
18 (GND)
NA
CS
3
17
13
RESET
4
36 (3v3 out)
NA
DC
5
15
11
MOSI
6
20
15
SCK
7
19
14
LED
8
36 (3v3 out)
NA
Четыре кнопки, используемые для навигации по меню, подключаются между контактом GND и свободным контактом GPIO:
Сигнал
Номер пина Пико
Номер Pico GPIO
Gnd
23 (GND)
NA
UP_BTN
22
26 (17)
DOWN_BTN
26
20
RIGHT_BTN
27
21
LEFT_BTN
29
22
Режим слайд-шоу
Файловый браузер изображений просматривает все изображения в корневой папке SD-карты. Навигация по изображениям осуществляется с помощью кнопок «Далее» и «Назад». Файловый браузер также работает в режиме слайд-шоу, переходя к следующему изображению по истечении заданного времени ожидания. Если во время работы слайд-шоу получено изображение, декодер автоматически переключается в режим приема.
Текстовое наложение
Функция наложения текста позволяет добавлять к изображению текстовый баннер, определяемый пользователем, перед передачей. Это позволяет встраивать позывные и другие сообщения непосредственно в изображение.
Наложение текста реализовано с использованием буфера кадров, который позволяет отображать текст и графические примитивы в определенной области памяти. Код буфера кадров был повторно использован из проекта pico planetarium .
Хотя я мог бы использовать сенсорный экран для ввода текста, мне хотелось обеспечить поддержку несенсорных TFT-дисплеев, и на данном этапе я не хотел добавлять дополнительное оборудование. Я выбрал простую схему ввода текста с помощью 4 кнопок. Я использую трехуровневое дерево, которое позволяет вводить все буквы и цифры всего тремя нажатиями клавиш. Как только вы привыкнете к принципу работы, после небольшой практики ввод текста станет достаточно быстрым.
Корпус, напечатанный на 3D-принтере
Конструкция корпуса, напечатанного на 3D-принтере, была переработана для обеспечения расширенной функциональности. В качестве отправной точки я использовал дизайн планетария , который уже предусматривает размещение 4 кнопок и TFT-дисплея.
Корпус обеспечивает легкий доступ к USB-порту Pico, а также позволяет использовать кнопку загрузки, не снимая ее с места, что упрощает процесс программирования через USB.
Я постарался спроектировать корпус максимально гибким, предусмотрев несколько различных передних панелей для размещения TFT-дисплеев разных размеров, от 2,4 до 3,2 дюймов. Доступ к разъему для SD-карты TFT-дисплея осуществляется через прорезь в верхней части корпуса. Стенки корпуса в этой области истончены, чтобы слот для SD-карты можно было обрезать под конкретный дисплей.
Корпус включает в себя ряд настраиваемых элементов для размещения выключателей питания и аудиоразъемов. Их можно обрезать с помощью дрели или канцелярского ножа.
Для портативной работы корпус включает в себя вместительный батарейный отсек. Если вы хотите изучить возможность работы Pi Pico от батарей, в разделе 3.1 в техническом описании представлены несколько вариантов. Pico оснащен эффективным импульсным стабилизатором напряжения и может работать от 1,8 В до 5,5 В. Pico может работать от 2 или 3 батареек типа AA или AAA, или от одной литиевой батареи 3,7 В.
Корпус позволяет установить 4 тактильных переключателя размером 6 мм. Они припаиваются к предварительно нарезанной и просверленной макетной плате. Макетная плата крепится к панели с помощью плавких крепежных элементов, встроенных в переднюю панель. Те же плавкие крепежные элементы используются для крепления TFT-дисплея.
![]()
![]()
![]()
![]()
Передняя панель и крышка батарейного отсека крепятся саморезами M3x6 с потайной головкой.
Заключение
В этой версии декодер Pi Pico SSTV был расширен и превращен в более функциональное портативное устройство с поддержкой самых популярных режимов. Мы добавили интерфейс с меню, хранилище на SD-карте и браузер файлов образов.
Мне пока не очень везет с приемом SSTV с Международной космической станции, и я, кажется, постоянно пропускаю предстоящие события. Мне бы очень хотелось наладить это, поэтому я буду продолжать искать возможности.
В будущем я хотел бы достичь еще многого. В частности, я хотел бы расширить код, добавив поддержку небольшой камеры. Также я хотел бы расширить декодер, включив в него другие цифровые режимы, такие как FT8, PSK31 и RTTY. Кроме того, я хотел бы заняться разработкой функциональности CW. Следите за обновлениями!
Примечание от RA3TOX.
Собрал вариант полнофункционального декодера, скомпилировав файл sstv_full_web.ino из архива с примерами.Монтаж выполнил на макетной плате 70х50 мм. С одной стороны платы находится микроконтроллер, с другой - дисплей и кнопки управления. Дисплей и МК установлены на разъёмных планках.
![]()
![]()
![]()
Для желающих я сделал разводку платы в программе Sprint Layot 5.0.
![]()
Файл разводки sstv-dek1.lay
Вид со стороны микроконтроллера (кликабельно)
[ На главную ] [ В раздел ] [ Декодер SSTV - часть 1 ]