PDA

Просмотр полной версии : Программа - имитатор PMR радио



RN6LIQ
15.04.2020, 16:55
Наконец то дорос до микроконтроллеров, среди задач которые хочется на них реализовать, есть в том числе задача передавать и принимать звук через интернет. Для разных целей, таких например как сделать дешевый IP телефон на Arduino, что бы не зависеть от VoIP монстров с их перегруженными серверами, или что бы принимать сигнал удаленного радиоприемника, но не ставить для этого "тяжелое" железо. Задач может быть множество, но решать их что было бы максимум на микрокомпьютере, типа RspberryPI или OrangePI, а лучше на микроконтроллере. Есть конечно готовые какие то решения, но когда делаешь сам, то можно отбросить лишнее и не тащить за собой "паровоз" излишнего исходного кода и лишних возможностей. Процесс этот творческий и требует постоянного тестирования, вот соответственно для тех кто проводит такие же эксперименты предлагаю уже готовую программу под Windows которую сделал специально для осуществления звуковой связи с экспериментальными поделками. Ее конечно можно использовать и для связи между собой. Она сделана в виде PMR радиостанции и имеет всего 8 каналов для общения, но так как в ней можно выставить почтовый индекс, то 8 каналов можно умножить на миллион разных групп, на одной из которых можно спокойно общаться или тестировать.
Саму программу можно скачать по ссылке 255929. Выглядит она примерно вот так
255937
Для тех кто хочет разобраться как это работает прикрепляю пример 255928 для Linux, тестировал на OrangePI. Используется библиотека ALSA. Исходники на Си, кодировка UTF8. Постарался максимально написать комментарии.
По поводу самой программы под Windows..., с кнопками все понятно, кликаем по ним левой клавишей мыши и получаем тот же результат как на настоящей радиостанции (канал Г служит для проверки звука на себя, никого другого в канале нет). Кликая по динамику выставляем режим приема/передачи. Правым кликом по кнопке выключения вызываем меню и настраиваем программу под свои возможности и хотелки. И еще, если нужно запустить несколько экземпляров программы, то нужно каждый экземпляр запускать из своего отдельного каталога.
Ну и самое главное, с удовольствие пообщаюсь на этой ветке со всеми теми, кого интересует данная тема.

P.S.
Свои эксперименты мы делаем вместе с Владимиром, RZ6AT

Refraktor
15.04.2020, 18:01
Скачал, запустил, никого не услышал, не совсем понял что и как настроить. :) Есть к софту хелп или еще в стадии разработки? Пожелания будт позже после тестирования. :)
Удачи с проектом!

RN6LIQ
15.04.2020, 19:33
Более подробное описание можно почитать по ссылке https://ok.ru/profile/100058109188/statuses/151288934564612

Попробую скопировать текст от туда.

Программа маленькая, портабельна, не требует установки, имеет очень простое управление. Виртуально имитирует PMR радиостанцию. Всего 5 кнопок управления. Как известно PMR радиостанция имеет 8 каналов для общения, но в данной программе можно указать почтовый индекс и тогда общение будет происходить только между теми у кого установлен одинаковый номер, а это миллион различных комбинаций. Почтовый индекс поселка, где вы окончили школу, отделит ваше голосовое общение от других групп. Переключение каналов производиться кликанием левой кнопкой мыши по кнопкам слева. Канал Г (ниже первого) имеет особый статус, на нем можно проверить работоспособность рации, услышать свой голос, но общаться там нельзя. Верхней левой кнопкой производиться вызов в канале. Нижняя левая выключает программу. Щелкая мышкой по динамику осуществляется переключение между приемом и передачей. Если щелкнуть правой кнопкой мыши по кнопке выключения виртуальной радиостанции, то появиться дополнительное меню.
255972
В нем можно выбрать микрофон и устройство воспроизведения. По умолчанию используются те, что установлены в Windows основными. Приемом/передачей можно управлять клавишами клавиатуры. По умолчанию используется клавиша пробела. Поочередное ее нажатие производит переключение. Клавиши Ctrl работают по другому, передача производиться между нажатием клавиш и их отжатием. В программе отсутствует перехват нажатий клавиш Windows (что бы не раздражать различные антивирусные программы), поэтому при управлении с клавиатуры программа должна иметь активное окно, то есть быть на переднем плане. Режим симплекс позволяет общаться без помех (заводки звука), если используется не гарнитура, а динамики компьютера.
Ну и главная изюминка программы:
255973
Для того что бы менять цифры надо навести курсор мыши на нужное место и щелкнуть правой или левой кнопкой мыши. Колесико мыши также работает. Изменения вступают в силу после закрытия диалогового окна с почтовым индексом. Для того, что бы запустить несколько экземпляров данной программы необходимо ее запускать из разных каталогов, из одной и той же папки запустить несколько экземпляров невозможно. Ну и в заключении несколько слов о том почему не Скайп или что то подобное?
Потому что данная программа предназначена именно для общения голосом небольших групп пользователей, она маленькая и не требует больших умений. Надо просто скачать и извлечь архив в нужное место. После первого запуска программа практически готова к использованию, единственное действие которое нужно сделать, это обменяться в "личке" с нужными людьми единым номером, почтовым индексом, после чего ввести его в программу. Единственный дополнительный файл который создает программа, это файл в котором программа хранит настройки. Никаких записей в реестр или тайные места. Не понравилась программа, достаточно просто ее удалить. В ней нет модераторов. Но единственный вариант избавиться от мешающих общению, это использовать такой почтовый индекс про который никто кроме вас не знает.

R2DO
15.04.2020, 21:27
Василий, спасибо!
Попробовал, работает :s7: Один комп включил через мобильный и-нет, второй - штатно, через домашний роутер. Практически без задержки...
А режим "конфиденциальности" в ней как-нибудь можно будет всё-таки предусмотреть?

RN6LIQ
16.04.2020, 04:13
Режим "конфиденциальности" есть, он выставляется почтовым индексом, миллион вариантов. Сервер не позволяет сканировать эти варианты с большой скоростью, а значит можно более или менее надежно затеряться среди этих шести десятичных цифр.

RN6LIQ
16.04.2020, 09:58
Наверное я не всеми был правильно понят. Достоинство именно этой программы в простоте протокола. Ведь возможности микроконтроллеров часто мизерны и на них организовать полноценный обмен сложными протоколами бывает непросто, а то и не возможно. Как правило сами устройства находятся за NAT серверами и к ним невозможен прямой доступ без программы ( сервера ) посредника, у которой есть белый IP. Задача сервера связать несколько программ с минимальными настройками. Когда я делал прямой IP телефон на Arduino, для связи с родительским домом, то возможностей этой платы, совместно с Ethernet модулем W5100, хватило только на работу с 8 битным звуком и на реагирование на действия - трубка поднята, трубка опущена. Ну еще остался один контакт который сигнализировал о приеме вызова. И на этом все, вся память занята, все контакты заняты, ну кроме разве еще A2-A5. ( ЦАП был реализован по схеме R2R, на что ушло 8 контактов, остальное забрал SPI ). По сути функционал как у проводного телефона. Вот тут остальное взял на себя сервер (а точнее VDS, арендованный на RUWEB ), который при поднятии трубки давал непрерывной гудок в этот телефон. Когда абонент несколько раз стучит по отбойнику (на который кладется трубка), то сервер давал или короткие гудки, в случае отсутствия на связи вызываемого абонента, или начинал давать длинные гудки с одновременным посылом вызова до поднятия с той стороны трубки. Без простенького сервера просто было бы не организовать такой проект. Это к тому, что ждать от меня добавления к PMR новых функций не стоит, тогда уже не будет все так просто. Но и так как есть, программой можно пользоваться в том числе и для оперативной связи небольших групп пользователей. А если мой коллега, Анатолий, р/л позывного у него нет, все таки сделает версию под Android, то это еще будет лучше.
Но у меня есть другой проект, посмотреть можно по ссылке (http://tiparadio.ru/index.php?p=ptp). В общих чертах. Или более подробно на этом форуме (http://www.cqham.ru/forum/showthread.php?36653-%CA%E0%F7%E5%F1%F2%E2%E5%ED%ED%FB%E9-%E7%E2%F3%EA-%F7%E5%F0%E5%E7-%E8%ED%F2%E5%F0%ED%E5%F2-%EF%EE-%ED%E0%EF%F0%E0%E2%EB%E5%ED%E8%FE-(%F2%EE%F7%EA%E0-%F2%EE%F7%EA%E0)&highlight=%F2%EE%F7%EA%E0-%F2%EE%F7%EA%E0). Вот там можно работать без сервера. То есть сервер первоначально нужен, он как STUN сообщает программам их внешние IP адреса и порты, а затем они работают напрямую. Есть возможность больших битрейтов, если позволит интернет между вами. Дело в том, что при передаче больших объемов данных увеличивается размер UDP пакетов, а их не всегда правильно разбирают до значения MTU и собирают до прежнего размера различные роутеры и шлюзы. Есть видео, правда низкого качества. Можно передавать файлы размером до 4 Гбайт, одновременно до 8 штук. Не всегда правда получается установить прямую связь, не все роутеры это позволяют. Но тогда есть хотя бы возможность работать через сервер, как этот проект PMR. Как альтернатива подобным программам почему бы нет. Не раз бывало когда не работала связь по скайп или WhatsApp( рвало звук, временно пропадало все ), тогда переходили на эту программу и отлично общались. Видео выставляли поскромнее, черно-белое, звук с меньшим битрейтом, а то и на GSM кодек переходили, но пусть с потерей качества, но общение все же было приемлемо комфортным.

Refraktor
16.04.2020, 11:45
Всем доброго дня!
В первую очередь хочется поблагодарить автора, а так же Владимира (RZ6AT) за интересную разработку, пожелать дальнейшего продвижения и конечно же побольше пользователей.
Софт тестировался на OS Win7 SP1 Pro x64, оптика - полет нормальный. :p-up: Программа мгновенно запускается сразу из коробки после распаковки архива. Имеет мизерный вес (404кб.), отлично дружит с кириллицей в именах, полностью портабельна, можно таскать с собой на любых носителях, отлично справляется с любым размещением в каталогах на жестком диске и имеет приятный глазу интерфейс. Разобраться с программой можно за пару минут. Все до элементарности просто и доступно. Если в канале пусто, из-за полной тишины, может появится первое впечатление что PMR не работает, но это не так. :s7:
При первом запуске в своем каталоге создает единственный файл настроек (68б.) и просит разрешения у сетевого экрана на передачу. Настройки практически не требует и не привязывается к системе. Кому интересно, антивирус тоже молчит.
Особенно порадовал выбор одного из режимов работы дуплекс или симплекс, вызывной тональник, самоконтроль и залипание клавиши пробела. Качество связи на отличном уровне, но конечно многое будет еще зависеть от используемого микрофона. Задержки и замирания на всем протяжении связи не наблюдались. Ощущение что оператор находится рядом в комнате.
В процессе тестирования появились пару хотелок, не настаиваю, но было бы замечательно если автор учтет это тоже. Сидя за компьютером мы обычно всегда чем то заняты. Маленькая проблема возникает с PMR когда окно не активно. Нет возможности оперативного пользования. По возможности для удобства хорошо бы добавить в меню функцию выбора постоянно оставаться активным на переднем плане, а так же выбора свободной горячей клавиши на передачу. Можно будет сразу нажатием этой клавиши отвечать не отвлекаясь от работы. И второе, хотелось бы видеть в доступе серверную часть, если конечно не планируется в будущем коммерческая основа. Это сильно продлит жизнь самого проекта и даст желающим помимо прямого общения реализовать и другие возможности, например подключение к своему трансиверу на 144мГц.
Как вариант, можно сделать и английскую версию, думаю людям не владеющим языком будет тоже интересен проект.
В остальном же тестирование прошло на ура. В ближайшем будущем буду пробовать на других OS, а так же со своими разнесенными домочадцами. Ну и конечно же хочется услышать в канале дальних операторов. Интересно как поведет себя дальняя связь. :s7:
На низких скоростях инета проверить пока что не получается, нет такой возможности.
В итоге программа заняла постоянное почетное место на жестком диске и в архиве полезных программ. :s7: Давно искал что то подобное но увы, то что есть не совсем устраивало. В виду своей простоты и мобильности для меня этот вариант намного удобней всех скайпов, агентов, ватсапов и прочих "болталок" вместе взятых.
Команде удачи, всех благ и крепкого здоровья!

UT4UCM
16.04.2020, 12:33
А если мой коллега, Анатолий, р/л позывного у него нет, все таки сделает версию под Android, то это еще будет лучше.Вот это действительно будет бомба, т.к. подобные вещи просто просятся под мобильные устройства. Автору - СПАСИБО! Буду пробовать.

Refraktor
16.04.2020, 13:24
Василий добрый день!


возможности микроконтроллеров часто мизерны
Зато "они" умеют делать большие дела и это главное! :ха-ха:


мой коллега, Анатолий, р/л позывного у него нет
:var: А вот это не порядок и должно быть стыдно оставаться в тени! Срочно делать ему свой позывной. Страна должна знать своих героев! :p-up: :)

Ну и по теме. Хочется в дополнение отметить так же возможность визуального контроля численности операторов в канале. Очень удобно!

RA9UEK
16.04.2020, 14:26
Для тех кто хочет разобраться как это работает прикрепляю пример example2.zip для Linux, тестировал на OrangePI.
RN6LIQ, там бинарный файл лежит. Должен запускаться?
У меня происходит вот это:


./pmr
bash: ./pmr: не удаётся запустить бинарный файл: Ошибка формата выполняемого файла

RN6LIQ
16.04.2020, 15:04
хорошо бы добавить в меню функцию выбора постоянно оставаться активным на переднем плане, а так же выбора свободной горячей клавиши на передачу
Как сделать что бы программа была постоянно активной, я честно говоря не знаю. Но на переднем плане, что бы всегда была, сделать можно. Но фокус у не все равно будет теряться, если вы будете работать с другой программой. Можно конечно сделать перехват клавиатуры от системы, и тогда передача будет срабатывать всегда, есть ли фокус на программе или нет. Но в этом случае гарантированно начнут ругаться антивирусники. Сложный выбор.


И второе, хотелось бы видеть в доступе серверную часть, если конечно не планируется в будущем коммерческая основа.
Благодаря Сергею, RV3DOD, сейчас программа работает через его выделенный сервер. Сервер будет работать до октября этого года, может быть чуть больше. Потом выключится. Закончится срок оплаты. За все в интернете надо платить. Но это не страшно, программа взаимодействует с двумя серверами-диспетчерами, которые перенаправят программу на другой ресурс, может быть не такой мощный, но достаточный для работы. Вот в это время я и хочу предоставить сервера для общего доступа, под Windows и Linux. Общая стратегия заключается в том, что бы таких серверов было много. Тогда легче затеряться в лабиринте серверов и их почтовых индексов. Ведь программа удобна именно для небольших проверенных групп пользователей. А пока желательно, что бы все работали через единый сервер, во первых, что бы он не простаивал, все таки деньги уже уплачены, а во вторых что бы набралась статистика как сервер держит нагрузку.


Как вариант, можно сделать и английскую версию, думаю людям не владеющим языком будет тоже интересен проект.
Это сделать можно, но на данном этапе пока не имеет смысла. Хотя людей уже не мало скачало и включило программу, где то около 1200 человек, но это все наши соотечественники понимающие русский язык.


Интересно как поведет себя дальняя связь.
Программа имеет возможность перейти на более низкое качество, как это сделать я потом расскажу, для заинтересованных сторон, а пока желательно что бы было единообразие, желательно для тестирования и для Анатолия, который делает программу под Андроид.


Ну и по теме. Хочется в дополнение отметить так же возможность визуального контроля численности операторов в канале. Очень удобно!
Первоначально в программе этого не было. Но пошел сознательно на усложнение сервера. Дело в том, что серверу все равно какую информацию транслировать, звуковую или иную. Не хотелось вешать на него специфические задачи отдельных проектов. Но потом пришел к выводу, что не только для звука, но и для других данных полезно знать сколько программ стоит в канале, особенно если канал "закрыт" почтовым индексом. Что бы не нервничать и знать точно, что тут только свои, двое или трое. Как только цифра выросла, значит кто то еще случайно или как зашел в канал.

Refraktor
16.04.2020, 15:23
там бинарный файл лежит. Должен запускаться?
В описании от автора нашел: "Единственный дополнительный файл который создает программа, это файл в котором программа хранит настройки."
По логике запускаться не должен. Успехов!

RN6LIQ
16.04.2020, 15:27
RN6LIQ, там бинарный файл лежит. Должен запускаться?
Если версия Linux совпадает, то должен запустится. Если нет, то сначала нужно откомпилировать (запустить файл ./make). Если ругнется, что нет библиотеки ALSA для разработчика, поставить ее sudo apt-get install libasound2-dev
Если со звуковой картой все нормально и ALSA ее видит, то должно заработать сразу. Может быть изменить значения
static char *deviceIn = "hw:0,0";
и
static char *deviceOut = "hw:0,0"; // звуковое устройство ALSA
по умолчанию указаны первые устройства. Если все нормально, то удалите файл init.bin, там хранятся настройки программы, а я не не помню какие именно установил. Потом в функции main() измените
MySave.MailIndex = 1;// как уже писал эксперименты мы проводим при почтовом индексе 1
MySave.PChannel = 2; // прошлый раз использовали 1 канал, сегодня будем второй юзать
на
MySave.MailIndex = 0;
MySave.PChannel = 1;
это будет соответствовать первому каналу виндусовой pmr-ки. А затем опять откомпилируйте (./make). Обращаю внимание, что это не команда компилятора, а исполняемый файл который лежит в этом же каталоге где и исходник. Там внутри командная строка gcc -o pmr pmr.c -lpthread -lm -lz -lasound
Это что бы не вводить эту команду каждый раз. Не люблю сложности и предпочитаю компилировать программы вот такими простыми командами. Проекты то у меня тоже простые. А то ведь одно только содержимое makefile может напугать кого угодно, кроме профессионалов конечно. Но я то не профессионал :)
Ну а потом, если все нормально, через эту программу будет слышно то, что передает виндусовая программа, ну а клавишей ENTER можно будет включать выключать\передачу. Для того, что бы перейти на другой канал, например второй, то нажимает 2 (двойку) а затем ENTER. Вызов нажать b, а затем ENTER. Ну а что бы выйти из программы набирает exit, а затем ENTER. Интерфейс с пользователем сделан специально попроще, что бы не отвлекаться на него. Главная задача примера показать как работать со звуком и с сервером.

И еще, у меня почему то это работало только с правами root, без этих прав запускается, но звука нет

Refraktor
16.04.2020, 15:38
Спасибо Василий за ответ! Все понятно.
Главное, при неактивном окне PMR-а есть звуковой контроль, этого тоже вполне достаточно и никто не будет пропущен при вызове.
По поводу вопроса о серверной части, это к тому что если вдруг не дай Бог :) прекратится поддержка этого маленького чуда и внешнего центрального сервера, софт будет лежать без пользы.
На 7-м канале кто то крутит музыку, хорошее качество и эфир без тормозов. :p-up: :) В общем, все до минимума просто и есть все самое неоходимое. Спасибо за интересный проект еще раз! :)

RN6LIQ
19.04.2020, 10:10
Придумал как сделать перехват клавиатуры и в то же время не вызывать подозрительность антивирусных программ. Надо перехват делать из другой программы. Если даже антивирусная программа заблокирует эту другую программу, PMR останется вне подозрения и продолжит работу, правда без удобства перехвата нажатий управляющих клавиш, независимо от того есть фокус на программе или его нет. По ссылке (http://188.168.58.111:8080/READ/keypmr.zip) скачиваем программу и "вынимаем" её в удобное для себя место. Запускать нужно key.exe, при первом запуске окно программы не отобразится, но появится иконка в trey. При повторном запуске окно программы отобразится. В нем ничего интересного нет, кроме служебной информации, но программу при этом можно закрыть уже стандартным способом. Программа ищет все запущенные программы PMR и в случае нажатия левого CTRL или правого оповещает их об этом событии. Если конкретный экземпляр программы PMR настроен на управление одной из этих клавиш, то он будет управляться. Если например запущено несколько экземпляров программы с управлением от левого CTRL, то при нажатии на эту клавишу все они станут на передачу.

UD4FD
19.04.2020, 10:30
Если со звуковой картой все нормально и ALSA ее видит, то должно заработать сразу. Может быть изменить значения
static char *deviceIn = "hw:0,0";
У меня Debian 4.19.98-1 (2020-01-26) i686 GNU/Linux - без ошибок запустилось только с такой строкой


//static char *deviceIn = "hw:0,0"; // имя входного звукового устройства, если бы мы вставили USB карту, было бы "hw:1,0"
//static char *deviceIn = "hw:CARD=Intel,DEV=0"; // имя входного звукового устройства, если бы мы вставили USB карту, было бы "hw:1,0"
static char *deviceIn = "plughw:CARD=Intel,DEV=0"; // имя входного звукового устройства, если бы мы вставили USB карту, было бы "hw:1,0"


но можно и так
static char *deviceIn = "plughw:0,0";

иначе выдает такую ошибку

MailIndex = 1 PChannel = 2 kanal_PRD = 10 kanal_Secret = 0
IN audio interface opened
OUT Playback open
IN hw_params allocated
IN hw_params initialized
IN hw_params access setted
IN hw_params format setted
IN hw_params rate setted
IN cannot set channel count (Invalid argument) 1
IN hw_params freed
IN audio interface closed
ALSA lib pcm.c:8507:(snd_pcm_set_params) Channels count (1) not available for PLAYBACK: Invalid argument
OUT Playback params error: Invalid argument
OUT Playback interface closed

RA3QDP
19.04.2020, 10:49
как и с "шарманкой" - нет истории версий.

RO4I
19.04.2020, 18:03
Про PMR
Под виндой подобных прог море в том числе и бесплатные и с видео потоком. Например zoom, в нем также вводим свой код и пожалуйста все вместе. zoom работает и под андроид и iOS.

Если речь идет о носимом устройстве под управлением микроконтроллера - может быть и есть какой то смысл и то сомнительный.

RN6LIQ
20.04.2020, 12:56
как и с "шарманкой" - нет истории версий.
А зачем эта история? Тут одна версия и единственная.

Под виндой подобных прог море
Так кто же спорит. Под винду программа делалась, что бы "подыгрывать" тем устройствам которые будут делаться на микроконтроллерах. Пример специально положил на Linux, что бы понятней было. Потом осознал что программа очень проста и в этом ее достоинство которое дает ей шанс на самостоятельную жизнь. Когда есть выбор среди многообразия жизнь ярче. Тем более делюсь, не продаю же. Сейчас мой коллега делает версию под Андроид. Бэта версию уже тестируем.

RA3QDP
20.04.2020, 18:54
одна версия и единственная
у нас с Владимиром AT - три (взяты с Web-chat Шарманки), здесь ссылка на "четвертую" ? или та же "третья" ?
В Windows - "правой кнопкой по файлу - свойства - подробно" и видны версии, а в PMR - ничего не видно.
Также надо бы про каждую новую версию писать в текстовом файле - что изменилось по сравнению с предыдущей.
Это общемировая практика.
На счет "единственная" - не стоит зарекаться. К тому же Вы завели ветку форума и логично предположить, что для ОБСУЖДЕНИЯ и РЕКОМЕНДАЦИЙ по совершенствованию.

RN6LIQ
20.04.2020, 19:42
Дорабатывать тут нечего. Единственная серьезная доработка, которую сделал - это отображение числа пользователей в канале. Это действительно удобно, но сразу ограничило некоторые перспективные направления развития. Не клиентской программы, а серверной. Для различных возможностей у меня есть другие проекты. А в этом только подыгрывать микроконтроллерам. Ну и простота главное удобство программы.

RA3QDP
21.04.2020, 11:07
если, например, прописать на первом канале индекс 000000, то как связаться на первом канале с индексом 000001 ?

RN6LIQ
21.04.2020, 13:23
если, например, прописать на первом канале индекс 000000, то как связаться на первом канале с индексом 000001 ?

Никак, в этом и фишка. На обоих программах должен стоять одинаковый канал и одинаковый индекс, тогда будет связь. Жаль все таки, что я повелся на желание определенных пользователей и сделал версию, где для каждого канала можно сделать отдельный индекс. Мне самому больше нравится первая версия (188.168.58.111:8080/READ/PMR.ZIP), где индекс выставляется для всей восьмерки каналов. Выставил для двух программ индекс, например 123456, и связь возможна по любому из 8-ми каналов, лишь бы стояли обе программы на нем вместе. Кто "копал" исходник на Си для Linux, тот уже понял, что частота дискретизации звука в программе применяется 16000 раз в секунду, а 16 битный семпл для передачи в канал преобразовывается в 8-ми битный G711. Но данная программа понимает и 16 битный звук, для частот дискретизации 16000 и 8000. Для обоих частот дискретизации программа принимает чистый 8-ми битный звук без всяких кодеков. На всякий случай присутствует также кодек GSM. На передачу программа также может работать в перечисленных режимах. Но пока что сознательно не озвучиваю все возможности, что бы не создавать хаос в каналах, для тех программистов, кто уже делает свои эксперименты по повторению программы. Например моему коллеге Анатолию это будет только мешать по созданию программы под Андроид. А в будущем конечно же распишу как что включать и правильно передавать. С некоторых микроконтроллеров нечего будет "выдавить" кроме 8-ми битного звука. Ни о каких кодеках там речи не может идти. Памяти просто не хватит. Вот для них в данной программе и включена возможность 8-ми битного звука для частот дискретизации 8000 и 16000.

RN6LIQ
21.04.2020, 13:45
Кстати, хочу поблагодарить RX3AKF за то, что нашел в примере неправильный код. В функции int opensocket(u_short port) нет инициализации переменной opt. На самом деле эта переменная лишняя, ее надо закоментировать также как и строки
// setsockopt(srv_socket,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));
// setsockopt(srv_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
поскольку эти режимы в программе не используются и даже могут нарушить ее работоспособность, если в переменной opt окажется не то значение, что надо. А именно если там будет положительное значение, то инициализируемый сокет сможет принимать широковещательные пакеты, а нам этого не нужно. Также может появится возможность открытия из другой программы еще одного сокета с таким же номером порта, что также нам не нужно.
Данный код был перенесен из другого проекта, но неправильно были удалены лишние для этого проекта строки.

RN6LIQ
21.04.2020, 14:45
Внимание начинаем тестирование версии под Андроид!!! (http://188.168.58.111:8080/READ/app-release.apk)[/COLOR] Просьба подходить к этому конструктивно. Анатолий до этого не писал программ для Андроида, это его первый опыт. Просьба это понимать и не критиковать жестко, а то "спугнете художника". Первый проект это как первая любовь, ранит в сердце. В принципе в этом проекте все есть, что и в виндусовой программе, но еще идет отладка, что то может работать не так. Просим выявить это и подсказать. У Анатолия пока нет на этом форуме регистрации, но он его читает. Для того, что бы выставить почтовый индекс надо нажать на клавишу выключения и держать пока не появится окно ввода. Остальное и так понятно. GO!!!

RA3QDP
21.04.2020, 16:00
Мне самому больше нравится первая версия , где индекс выставляется для всей восьмерки каналов
надо с этим что-то делать.
Не хочется ставить сниффер - у Вас пакеты IP или UDP используются ?

RA3QDP
21.04.2020, 16:02
мой приятель попробовал поставить на планшет андроид - не ставится.
Может нужен "чистый" или root ?

RN6LIQ
21.04.2020, 16:11
надо с этим что-то делать.
Если честно, то не понимаю, - с чем этим? Пакеты UDP, инкапсуляция в IP.

По поводу установки на Андроид, тут я пас. Не разбираюсь. Может памяти не хватает?

RA3QDP
21.04.2020, 16:20
Если честно, то не понимаю, - с чем этим?
с каналами и индексами. Может просто использовать старую версию ?

RN6LIQ
21.04.2020, 16:24
Если про программу под Windows, то это и есть старая версия. С самого начала был почтовый индекс. У всех с кем вы хотите общаться должен быть выставлен одинаковый почтовый индекс ( это позволяет спрятаться среди его множества вариантов ) и конечно же все должны стоять на одном канале.

RN6LIQ
21.04.2020, 16:26
мой приятель попробовал поставить на планшет андроид - не ставится.
Может нужен "чистый" или root ?
Анатолий сообщает, что версия Андроид должна быть 5 и выше. Его среда разработки не работает с версиями ниже.

RA3QDP
21.04.2020, 16:32
как я понял и старая сейчас будет работаь. Так ?
Может сделать так, что бы каналы в клиентской программе были логическими-условными (как в современных телевизорах), а не определяли фактический канал ? (и у всех пользователей будут "свои им настроенные каналы). Тогда пользователь сам их может программировать высатвляя индекс который ему захочтеся. Но сокраится в 8 раз общее числи с 8-ми миллионов до одного.

Refraktor
21.04.2020, 16:33
мой приятель попробовал поставить на планшет андроид - не ставится
По дефолту в системе запрещена установка приложений не из плэймаркета. Отключите на время установки защиту в настройках.
Успехов!

Refraktor
21.04.2020, 16:40
начинаем тестирование версии под Андроид
Приветствую Василий. Ну наконец то! :) Поздравляю с "допилом"! Анатолия тоже с победой! Молодцы! :)
По поводу PMR-ки, да можно обе версии оставить, на любителя. :) Ну и самое главное спасибо за ключик, все нормально с установкой. :)

RA3QDP
21.04.2020, 17:03
версия Андроид должна быть 5 и выше
Если все-таки ВОЗМОЖНО сделать программу под младшие версии, то надо делать для САМОЙ младшей. Ведь не покупать же для этой порграммки дорогое новое устройство ! А ведь у многих валяются без дела устаревшие старые модели. И было бы им применение. Можно понять больших производителей (и солидарных с ними программистов), которые заставляют покупать новое. Но в данном случае - зачем так поступать ?

RA3QDP
21.04.2020, 17:04
спасибо за ключик
что за "ключик" ?

Refraktor
21.04.2020, 17:32
что за "ключик" ?
Лицензия на программу виртуальной софтины "ТипаРадио" (http://tiparadio.ru/).

RA3QDP
21.04.2020, 18:07
приятель поставил на андроид 5. Переключение каналов - только вверх, назад не работает.
При нажатии на любую кнопку - загорается передача.

RA3QDP
21.04.2020, 18:30
у него прием есть, вижу у себя, что еще одна станция появилась, когда он включается на передачу - у себя вижу зеленый огонек, но ничего не слышу и вызов не слышу.

RN6LIQ
21.04.2020, 18:49
Но в данном случае - зачем так поступать ?
Странный вопрос :( какой есть инструмент такой получается и продукт. Что бы написать программу для такой маленькой коробочки как смартфон или планшет, надо поставить на компьютер тяжеловесные программы занимающие много места и требующие большой экран и мощный процессор. Найти старые IDE среды для создания программ для старых устройств надо еще постараться. И не факт что они заработают на современных компьютерах. Анатолий провел большую работу, разобрался со средой программирования какую сейчас предлагают для разработки, но она может создавать программы только для версий 5 и выше. Что есть, как говорится.

Лично я даже не хочу этим заниматься, меня больше тянет ближе к железу. Хотя должен заметить, что среды IDE для работы с микроконтроллерами также тяжеловесны.

R2DO
21.04.2020, 18:55
На xiaomi redmi 7A ( Android 9, MIUI 11 ) не заработала вообще. Запускается и... ни на какие нажатия не реагирует. :s9: Снёс.

RN6LIQ
21.04.2020, 19:35
не заработала вообще.
Когда при скачивании предлагает запустить, действительно не реагирует. Надо закрыть и снова запустить. При мне ставили на два смартфона, также программа себя вела.

R2DO
21.04.2020, 19:43
Василий, ну не блондинка я... :s7: Запускал "с ярлычка" на рабочем столе несколько раз, появляется картинка и не реагирует дальше на нажатия вообще... И выгрузить-то её из фона ( закрыть ) потом никак не получается. Только через полный снос...

RA3QDP
21.04.2020, 21:06
Странный вопрос какой есть инструмент такой получается и продукт
Странный ответ. Любая программа пишется один раз программистом, а потом ее используют долго многие пользователи.
Так чему при этом отдается приоритет ? Это автор Вам ответил, что именно так обстоит дело ? Что НЕВОЗМОЖНО написать для более младшей версии ?
И почему бы ему самому здесь не поучаствовать в форуме ?

RA6AS
21.04.2020, 21:24
На 9 Андроиде все ОК.На 10 не запускается.

RA6AS
21.04.2020, 22:07
.На 10 не запускается.
После перезагрузки телефона заработало.Mi MAX 3-9 Android,MIUI 11-работает.
MI 9T-10 Android,MIUI 11-тоже работает.

RN6LIQ
22.04.2020, 02:47
Странный ответ. Любая программа пишется один раз программистом, а потом ее используют долго многие пользователи.
Насчет того, что любая программа пишется один раз программистом позвольте мне не согласится. Она пишется для конкретной железки и системы. Мне пришлось начинать писать еще для спектрума, потом DOS, Windows разных версий и Linux, и даже немножко для для Андроида. Несмотря на то, что общий смысл программы не меняется, но от среды к среде, от версии к версии программы приходилось не просто пере компилировать, но и переписывать. Есть конечно общая мечта, что бы было так как вы сказали, для этого создаются специальные языки программирования и специальные виртуальные среды для которых на этих языках будут писаться программы. Но пока нет универсальной "таблетки", как видите многое зависит от версий Андроида.

Это автор Вам ответил, что именно так обстоит дело ? Что НЕВОЗМОЖНО написать для более младшей версии ?

Мне автор дословно ответил "Версия 4.1 действительно очень старая уже. Актуальная AndroidStudio поддерживает от 5.0 и выше. Подумаю что можно сделать с этим", остальное я писал от себя. Хотя у меня нет соответствующего образования, программирование постигал самоучкой, но 9 лет назад мне пришлось поработать инженером-программистом по совместительству, где моей работой было написание статьи для других программистов нашей группы с обзором того как обстоят дела на рынке программирования мобильных устройств и подробной инструкцией о том, - как где что скачать и как настроить среду для написания программ для Андроид. Даже несколько программ для примера черкнул, в том числе по работе со звуком. Через полтора месяца работы нашей экспериментальной группы работодатель посчитал что это направление ему не интересно и распустил нас, но я заработал тогда на ноутбук с которого сейчас пишу этот текст. Не дешевый по тем временам. Хотя он битый перебитый, экран держится на зажимах для бумаги, но все еще соответствует моим требованиям для работы. Имея тот старый еще опыт осмелился от себя написать, что программирование под Андроид это еще тот "геморрой".


И почему бы ему самому здесь не поучаствовать в форуме ?
Это зависит от него. Он молодой человек который только начинает свою профессиональную деятельность. На мое предложение примкнуть к радиолюбительству он пока ответил отказом. Все это ему интересно, он любознателен, но не настолько что бы окунуться в наш мир. И кстати, что бы написать даже такие простые программы как наши нужно время. Сейчас это время дает карантин и самоизоляция. По окончании всего этого интерес Анатолия может снизится к проекту. У молодых свои заботы и свои жизненные цели, так что пользуемся этим и не требуем "вызова на ковер".

UA0YAS
22.04.2020, 05:12
Как сделать, что бы в фоновом режиме на Андроид программа принимала вызов?

RN6LIQ
22.04.2020, 10:45
Анатолий пересобрал программу под версию Андроида 4.0 Если у кого стоит эта виртуальная рация, надо ее удалить. Затем скачать и установить новую версию все по той же ССЫЛКЕ (http://188.168.58.111:8080/READ/app-release.apk)


Как сделать, что бы в фоновом режиме на Андроид программа принимала вызов?
Анатолий работает над этим.

R7CL
23.04.2020, 10:12
Привет.
Не очень понял, чем Андроид-программа отличается от Zello рации?

Программу поставил на OnePlus 3 (Андроид 9). Работает, наверное. На одном канале (с индексом по умолчанию) музыку кто-то транслировал. :)
При нажатии на MENU программа падает. Теперь, если позволите, советы для Анатолия:
- Интерфейс программы надо сделать не фотографией, а обычными кнопками и текстовыми полями. Безумное количество ценного экранного места уходит в никуда.
И чисто визуально-психологически не правильно "засовывать" прибор в прибор (рацию в телефон). На компьютере - там простительно, там места на экране много.
- При изменённом интерфейсе можно будет и по-человечески писать, что мол "2 пользователя в канале" и т.п. Интерфейс программы будет гораздо более дружественным и понятным.
- К "Усиление" - отдельный вопросы. Что это? Усиление чего? Надо ли мне оно? Надо ли мне оно на главном экране? А при правильном интерфейсе и организации приложения такие вопросы или не должны возникать, или моментально решаться/поясняться.
- Что значат красные и зеленые кружки-индикаторы? И почему они на клавише РТТ находятся? (Это не вам вопрос, это вопрос к программе)
- Можно сделать так, чтобы экран телефона не гас, если приложение запущено. Это несложно.
- Можно потом и фоновый режим освоить, но это сложнее.
- Ну и до напоследок - иконка программы и название программы. Название должно быть коротким! Чтобы в списке приложений телефона было понятно, что за программа. Ваша программа знаете как у меня показывается? "Виртуа..." ;)

А Анатолий пусть не расстраивается из-за такой критики. Он, конечно, "художник и так видит" (с). Но так оно будет правильнее...

RA3QDP
23.04.2020, 13:09
У приятеля новая версия - заработала. Индекс прописывается. Есть и прием и передача. Программа устанавливается штатно, закрывается корректно.
Недостатки : кнопку передачи надо держать постоянно (не фиксируется), уровень микрофона - мал (тихо слышно), если включить усиление - хрипит. Подобрать уровень расстоянием до микорофона - не получается.

Ровесник
23.04.2020, 14:07
Добрый день всем! Не болейте и берегите ближних! моё первое сообщение
Сегодня поставил новую версию на андроид 5. Всё заработало: приём отлично, передача - нет фиксации режима передачи, необходимо касаться дисплея. Громкость на передачу слабая, поставил галочку усиление -пошли искажения. Надо искать в настройках телефона. Но ранее такой функции в девайсе не находил На приём работает отлично, кто с винды. Установил на андроид 4.1. Пока непонятки, отпишусь. Я думаю что Анатолий победит проблемы, не всё сразу. И можно будет использовать старые телефоны для таких общений. Вот будут рады рыбаки!

Ровесник
23.04.2020, 14:30
Андроид 4.1 - приём есть, вижу количество абонентов в канале. Индекс выставляется, на передачу не включается. Приём абонента вижу,зеленый индикатор, но не слышу. Динамик зачеркнут, громкость на всю. И не могу активировать динамик. Сколько этих гаджетов с одной версией, и везде разная конфигурация аппарата. Не позавидуешь Анатолию.

RN6LIQ
23.04.2020, 14:50
Анатолий сделал новую версию (http://188.168.58.111:8080/READ/app-release.apk) Он читает эту ветку поэтому отреагировал на замечания. На этот раз конкретно не предупреждал, но думаю, что старую версию лучше удалить перед установкой новой. Новая версия корректно завершается , может работать в фоне, изменен интерфейс и есть проверка на себя

RN6LIQ
23.04.2020, 15:34
Громкость на передачу слабая, поставил галочку усиление -пошли искажения.

Вот только что Анатолий исправил ошибку с усилителем микрофона. ССЫЛКА не меняется, все та же, но там уже новая версия КАЧАЕМ ЕЩЕ РАЗ (http://188.168.58.111:8080/READ/app-release.apk).

Ровесник
23.04.2020, 15:40
На андроиде 5 удалил старую, поставил новую версию. Можно говорить на 30-40 см от телефона без искажений. Провели контрольную связь. Фиксации передачи пока нет, неудобно. Сейчас буду запускать на 4.1, отпишусь.
У меня планшетник 10", для этой цели не подходит. Но проверю.

Ровесник
23.04.2020, 16:05
На 4.1 не хочет работать, сбрасывается без строки предупреждения. Во всяком случае на моём планшетнике. Интересно у кого как программа себя ведёт?

RN6LIQ
23.04.2020, 16:12
У меня смартфон прошлогодний, поэтому работает без проблем. Только что пообщался на 1 канале с почтовым индексом 000000 с Андреем 4L4KA, он с версии под Windows, а я с последней Андроидной версии с включенным усилителем микрофона. Великолепно!!!

Ровесник
23.04.2020, 18:06
Василий, фиксация передачи у вас есть?

RN6LIQ
23.04.2020, 20:55
Василий, фиксация передачи у вас есть?
Анатолий сообщил, что уже сделал, по двойному клику. Но еще не выложил. Ждем от него обновление, там еще будут некоторые изменения.

RX3AKF
23.04.2020, 21:50
Насчет индекса. В клиентской программе добавить еще один флаг на фрейме установки индекса "Все каналы", либо еще один пункт меню Индекс для всех каналов, если не хочется менять фрейм установки индекса.
Одна версия интерфейса клиента все же удобнее для пользователей, да и для автора тоже.
Выложенная линуксовая версия не дописана в части инициализации устройства воспроизведения: у многих без изменения настроек не запустится из-за нестандартной частоты дискретизации и одного канала воспроизведения, обычно по умолчанию в настройках 2 канала 44100 или 48000 Гц.
С другой стороны, если кто-то уже установил gcc, то справится со временем.
73!

RN6LIQ
24.04.2020, 05:48
Не очень понял, чем Андроид-программа отличается от Zello рации?
А что общего? Только и того что обе работают со звуком. Так и радиолюбитель алекает в эфир со звуком и диктор радио и военный связист, но суть то при этом разная. Что PMR для виндовс, что виртуальная рация под Андроид имеют право на самостоятельное существование, но они входят в эдакий звуковой конструктор из которого можно собирать нужные под себя проекты. Вот например ту же Zello я пытался приспособить под свои нужды, сделать мост между мной со смартфоном и виртуальной шарманкой, ну и результатом остался недоволен. Работает не так как мне хотелось. Ну и зачем мне капать разработчикам Zello на мозги, если можно сделать подобное, но уже под себя, без сложных протоколов которые должны учитывать тысячи нюансов разнообразного применения.


Насчет индекса. В клиентской программе добавить еще один флаг на фрейме установки индекса "Все каналы", либо еще один пункт меню Индекс для всех каналов, если не хочется менять фрейм установки индекса.
Одна версия интерфейса клиента все же удобнее для пользователей, да и для автора тоже.
73!
Лично я ничего не понял. Что за одна версия интерфейса? И зачем такие сложности с индексом? Индекс переносит все 8 каналов в другое физическое и логическое пространство. Это очень удобно. Что еще не так?


Выложенная линуксовая версия не дописана в части инициализации устройства воспроизведения: у многих без изменения настроек не запустится из-за нестандартной частоты дискретизации и одного канала воспроизведения, обычно по умолчанию в настройках 2 канала 44100 или 48000 Гц.
С другой стороны, если кто-то уже установил gcc, то справится со временем.
73!
Пример писался для Анатолия, там даже в ремарках я обращаюсь все время к нему. А тут выложил для тех кто разбирается в коде и кто конечно же может править его и компилировать. Это не для пользователей которые хотят общаться с Linux в PMR-ке. Это начальный конструктор. Упрощенный, так как виндусовая программа сложнее. Частоты дискретизации на самом деле стандартные для голосовой связи. Вообще-то в этом проекте их две - 8000 и 16000. Сейчас в примере только 16000, потому что обеспечивает бОльшее качество. Работает со звуком пакетом по 640 байт, что соответствует 20 миллисекундам звука. Это стандарт в связи. При 8000 размер пакета 320 байт при тех же 20 миллисекундах. Те же 320 байт при кодеке GSM преобразовываются в 33 байта кода для передачи по каналу связи, а потом из 33 байт обратно в 320 для передачи звуковому устройству. Но должен заметить, что некоторые USB звуковые карты в ALSA не хотят работать при такой частоте дискретизации, могут действительно только 44100 или 48000 и обязательно стерео(что интересно а микрофон только моно). У меня такая карта есть. Что бы подстроиться под этот проект пришлось делать искусственное преобразование частот дискретизации, но для этого уже приходится применять цифровой фильтр который обрезает паразитные шумы выше 8000 герц.

RN6LIQ
24.04.2020, 13:53
Ребята, КАЧАЕМ новую версию (http://188.168.58.111:8080/READ/app-release.apk) Есть вызов ( для приема вызова надо что бы в канале была тишина ), и это работает в фоновом режиме. По двойному клику фиксируется передача, не надо держать все время динамик

UA0YAS
24.04.2020, 14:44
Заикания- это где проблемы?

RN6LIQ
24.04.2020, 14:52
Заикания- это где проблемы?
Как правило какие то особенности интернета или работы роутера ( которые встречаются с какими то особенностями программы ). Иногда достаточно выйти с программы а потом зайти и заикания пропадают. При чем у меня по вай фай заикания есть ( не все время, а периодически ), а когда принимаю на мобильный интернет их нет, ну или иногда в зависимости от того по какой части здания иду. Если заикания постоянные, то может быть программа не совсем дружат именно с вашим телефоном.

RX3AKF
24.04.2020, 15:51
Лично я ничего не понял. Что за одна версия интерфейса? И зачем такие сложности с индексом? Индекс переносит все 8 каналов в другое физическое и логическое пространство. Это очень удобно. Что еще не так?


Выше шла небольшая дискуссия о том, что устанавливать индекс некоторым лучше сразу для всех каналов, чтобы можно было менять каналы как на PMR в своей группе. Тогда индекс становится аналогом CTCSS. Тут дело автора программы.

Refraktor
24.04.2020, 17:41
Всем доброго вечера коллеги!
OS: Android v8.1, интернеет на телефоне от сотового оператора, последий релиз PMR - полет нормальный. Отличное качество приема. Какие либо проблемы вроде не выявлены, все четко пока что, без сбоев. :p-up:

Ровесник
24.04.2020, 21:27
Добрый вечер всем! Переустановил программу, всё работает, андр. 5. Индекс для всех каналов одинаков. Провёл контрольную связь, микрофон работает на любом удалении. Сейчас попробую на 4.1

Ровесник
24.04.2020, 21:46
На 4.1 acer a200, интерфейс в норме, индекс набирается, симплекс включается, на приём работает, загорается зелёный индикатор, звука нет динамик зачеркнут. У каждой фирмы своя сборка андроид, пойди разберись. При попытке включить передачу, вылетает ошибка и программа закрывается. Плэймаркет отключен, разрешена установка сторонних программ.

RA3QDP
25.04.2020, 14:35
Тут дело автора программы.
я сразу поднимал этот вопрос (выше по этой ветке). И педлогал там свой вариант, который считаю более логичным и правильным - не связывать каналы и индексы для указания фактического канала, а сделать каналы чисто логическими - у всех пользователей свои индексы на всех каналах (хоть одинаковые, хоть разные) - какие они захотят для себя у себя запрограммировать (как в современных телевизорах).
Считаю Василий, как отец этого проекта, должен принять окончательное решение и сделать одинаково и в Windows и в Android.

RN6LIQ
25.04.2020, 17:24
Считаю Василий, как отец этого проекта, должен принять окончательное решение и сделать одинаково и в Windows и в Android.
Уже принял. И там и там одинаково, индекс общий для всей группы из 8-ми каналов.

RA3QDP
25.04.2020, 23:50
у человека - одна группа товарищей (по рыбалке) - на одном индексе, другая (по радио) - на другом...
Если на компьютере можно и две программки запустить, то на телефоне и планшете ? - не удобно.
У Вас какие аргументы - "индекс общий для всей группы из 8-ми каналов" ?

RN6LIQ
26.04.2020, 06:54
У Вас какие аргументы - "индекс общий для всей группы из 8-ми каналов" ?
Мы с вами по разному смотрим на цели проекта, отсюда и недопонимание. Вы хотите увидеть что то типа групп в WhatsApp, а я вижу как инструмент для подключения к своим проектам. Ввел один раз индекс и попал в свою группу, где на одном канале у меня идет трансляция какого то интернет ресурса, типа канала виртуальной шарманки, по другому каналу могу послушать радиоприемник настроенный на интересующую меня частоту, а то и несколько приемников, а значит несколько каналов, еще в одном канале не только прослушать реальный канал, но и самому выйти в реальный эфир, типа CB радиостанции или PMR, LPD. Я уже делал в версии Winows то что вы предлагаете, послушал ваших единомышленников, но на данный момент вернул все в исходное состояние и такой версии вы больше не скачаете. Очень неудобно. Во первых люди путаются, предлагают перейти на такой то канал и не слышат друг друга, потому что для данного канала у них стоят разные индексы. Во вторых вместо одного индекса теперь приходится их вбивать сразу восемь, а это лишние движения которые лично меня раздражают. В перспективе пользователи проекта смогут не только выбирать канал и индекс но и сервер. Задача проекта это не создавать ресурс через который можно общаться большими группами в конференциях, по типу виртуальной шарманки, а создание каналов для небольших групп по очень простому протоколу. Недостатком этого простого протокола конечно же является незащищенность от хакерских атак, но если затеряться среди серверов, которые не публикуются для широкой общественности, а на самих серверах закрыться индексом, то никакая защита и не нужна. Вот если бы я предложил Анатолию повторить под Андроид шарманку, думаю он вряд ли бы согласился, потому что очень сложно, даже если не повторять все ее возможности, то один только звук представляет большую проблему который тяжело повторить в Java. А вот данный проект повторить легко, потому, что все просто. Думаю, что не только ответил на ваш вопрос но и высказал дополнительно свои взгляды на проект.

RA3QDP
26.04.2020, 13:01
почему бы не прописать один и тот же индекс для всех каналов, и тогда будет как в Вашем варианте.
Аргумент, что "что придется набивать все 8 каналов" - так не все "кое-какеры с девизом - не заморачиваться" и в детстве слышали сказку по Емелю на печи, который мечтал ничего не делать.
Как быть если у человек не такой замкнутый и у него много разных увлечений и коллег по разным направлениям, которые, естественно, используют разные индексы ?
Надеюсь, что Вы создаете свои программы для людей, а не просто их используете "в темную", как бесплатных добровольных бета-тестеров для своих интересов.

RN6LIQ
26.04.2020, 14:54
Если вам нужен еще один WhatsApp, то вы знаете где его найти. Это я перефразирую высказывание создателя языка Си, когда его просили добавить в язык Си то то и то, он отвечал, что если вам нужен еще один язык программирования... ну и так далее как я уже написал вначале. Знали бы вы как я не согласен со многими решениями авторов программ, но ничего не поделаешь, они так видят мир. А у меня уже есть опыт по выполнению различных хотелок и пришел к выводу, что нужно делать так как сам видишь что лучше.

RA3QDP
26.04.2020, 18:35
как для Вас лучше - никто не мешает сделать для себя любимого специальную версию.

RN6LIQ
26.04.2020, 18:59
Ооо, под Linux этим и занимаюсь, для себя любимого. А в проекте должно быть единообразие. К тому же меньшинство должно подчиняться большинству, из за пары человек делать неудобства для остальных, - это не правильно.

RA3QDP
27.04.2020, 13:30
а кто эти остальные ? Я что-то здесь не вижу никого. Здесь сайт радиолюбителей, для них Вы и "делитесь" программой, значит для них и делаете.
НИКТО ничего другого не предложил, а молчание - знак согласия. Разве не так ?

RX3AKF
27.04.2020, 16:10
...Во первых люди путаются, предлагают перейти на такой то канал и не слышат друг друга, потому что для данного канала у них стоят разные индексы. Во вторых вместо одного индекса теперь приходится их вбивать сразу восемь...

Очень здравые аргументы. Общительные люди, бывает, даже по два телефона (или телефон с двумя сим-картами, у которого два независимых профиля пользователя) таскают, они и без помощников справятся.
На мой взгляд, здесь спорить с автором нельзя. Авторы продаваемых программ иногда вынуждены идти на компромисс, но здесь не тот случай.
Дальнейших успехов!

RN6LIQ
27.04.2020, 18:32
Здесь сайт радиолюбителей, для них Вы и "делитесь" программой, значит для них и делаете.
Если честно, то я не понимаю причину вашей настойчивости. Вот только что правильно товарищ сказал, это не тот случай. С какой кстати надо делать как вам хочется? Проект предоставляется как есть, пользуйтесь пожалуйста. Писать программы это не махать волшебной палочкой, нужно работать с утра до вечера, как на работу ходить. Я долго искал в компаньоны программиста который смог бы участвовать в моих проектах. За бесплатно никто работать не хочет. Ведь как объяснить жене чего ты сидишь с утра до вечера за компьютером, а денег при этом нет и холодильник пустой? Если нет жены, то как объяснить своему пустому желудку почему он пустой? А тут уникальный случай, Анатолий сидит дома по причине карантина, а деньги при этом ему платит наше предприятие, где мы с ним работаем. На эти субботу, воскресенье Анатолий запросил выходные, потому что все время работает по созданию программы. Уже месяц работает. И времени осталось мало, закончится карантин, закончится работа над программой, по крайней мере с таким темпом как сейчас работать уже не получится. А вы в одну и то же точку стучите и стучите, как вроде бы вам что то должны. Берите как есть и пользуйтесь. Когда Анатолий начнет писать коммерческие программы вот тогда и будете требовать, помахивая при этом кошельком.

RA3QDP
27.04.2020, 19:32
От всей души хочу Вас поблагодарить за очень нужные и полезные программы и за PMR и за Шарманку. Думаю Вы еще не раз всех порадуете своими новыми разработками. Удачи Вам во всех начинаниях.

RN6LIQ
27.04.2020, 21:54
Замечена зависимость, при работе через вай-фай при включенном блютуз рвет сигнал. Если выключить, то все нормально.

UY3IG
30.04.2020, 07:57
Два дня крутил программу на Андроиде 8,1. Ничего не понял. Если в канале есть корреспонденты, то обычно музыка. С хреновым качеством (ну какое качество на телефоне?). Если нет музыки, то нет и корреспондентов. Зову, зову - никого не дозвался. Снёс. Жду продолжения.

Refraktor
30.04.2020, 08:09
Два дня крутил программу на Андроиде 8,1. Ничего не понял. Если в канале есть корреспонденты, то обычно музыка. С хреновым качеством (ну какое качество на телефоне?). Если нет музыки, то нет и корреспондентов. Зову, зову - никого не дозвался. Снёс. Жду продолжения.
На 7-м канале 1-го индекса в основном постоянно кто то есть, частенько слышу. На 0-м индексе тоже бывают но реже.

RN6LIQ
30.04.2020, 08:59
Если нет музыки, то нет и корреспондентов. Зову, зову - никого не дозвался.
Хотелось бы напомнить, что этот проект для индивидуального использования. Надо иметь с кем общаться. Это не шарманка где организовываются круглые столы со случайно набежавшими пользователями. Тут надо пригласить кого то и сообщить ему индекс, который никто кроме вас не знает. Или организовать какую то интересную трансляцию, как например на 7 канале 1 индекса. Там кстати транслируется канал шарманки, причем только в одну сторону. Если надо в обратную сторону организовать, то тогда бы я ввел индекс посложнее и смог бы принимать участие в беседе в шарманке, но с телефона. Можно и радиостанцию подключить вместо шарманки и общаться удаленно через программу. Версия Windows позволяет это сделать через встроенный VOX и на радиостанции он тоже должен присутствовать. Или реализовать это под Linux на Raspberry PI или подобном микрокомпьютере, там уже есть GPIO через которые можно реализовать взаимодействие с радиостанцией. Еще один пример использования это радио няня, пошли в гости и создали канал прослушки всего что у вас шумит дома. Наверное можно придумать много применений организации индивидуальной связи. В прошлые выходные я использовал просто для связи с другом. Начали общение в WhatsApp, а потом перешли на свой созданный закрытый канал где и общались в течении 3 часов. И ощутили преимущество, во первых в программах где делается подавление собственного эха звук имеет неприятный металлический оттенок, который раздражает и утомляет при длительном прослушивании. А в нашей программе звук постоянного качества, болтали долго но не устали и не было неприятных ощущений на уши. Вначале для моего друга было необычным общаться в режиме приема-передачи, но потом он оценил преимущество такого способа общения. Как не крути, но при длительном разговоре переходишь в режим длительных монологов, и если тебе навстречу идут с обратной стороны посторонние звуки собеседника, то это сбивает нить повествования и отвлекает. А если корреспондент в это время слушает но выключил при этом свою передачу, то может во время прослушивания налить себе чаю, зевнуть, кашлянуть не боясь что помешает кому то.

UY3IG
30.04.2020, 15:14
Каналов 8. Это понятно. А что такое 1 индекс? 2? 3? Ну, в настройках я могу ввести пятизначный индекс (например свой почтовый) и смогу говорить только с тем, у кого такой же и у кого в телефоне постоянно включена эта программа. А если она выключена? "Грузить" постоянно память телефона не хочется. После входа в Меню и ввода своего индекса как вернуться в программу? Просто ходом "назад" - слетает введенный индекс (если это была однозначное число) Сколько цифр должен содержать индекс? Если я вижу несколько корреспондентов в канале как мне выбрать нужного? Нет понятной инструкции пользователя. Отсюда и вопросы.

UY3IG
30.04.2020, 16:12
Как должен выглядеть набранный индекс? Например: индекс (1) - это 00001 или 10000 или просто 1?

RL6M
30.04.2020, 17:23
Хотелось бы напомнить, что этот проект для индивидуального использования. Надо иметь с кем общаться. Это не шарманка где организовываются круглые столы со случайно набежавшими пользователями. Тут надо пригласить кого то и сообщить ему индекс, который никто кроме вас не знает. Или организовать какую то интересную трансляцию, как например на 7 канале 1 индекса. Там кстати транслируется канал шарманки, причем только в одну сторону. Если надо в обратную сторону организовать, то тогда бы я ввел индекс посложнее и смог бы принимать участие в беседе в шарманке, но с телефона. Можно и радиостанцию подключить вместо шарманки и общаться удаленно через программу.

Тема "болтается" в топе уже недели две.. :-) Читаю ее, поневоле и никак в толк не возьму "Какое отношение это ПО имеет к РАДИОСВЯЗИ?". Сначала думал, что это RN6LIQ автор, потом оказывается нет, Анатолий, который без позывного, тогда почему на ЭТОМ форуме?


У большинства из нас, есть оборудование и нам есть с кем общаться. Вместо индексов, мы используем частоты любительских диапазонов. Музыку, конечно, не крутим (это другой вид извращения), но вот Азбука Морзе и другие виды модуляции присутствуют.

Я не спорю, интересно было человеку, написать какую-то программу, он написал. А от зачем ее "пиарить" на форуме, где большинство пользователей считает ее бессмысленной?. Не пойму.

Тимофей

RN6LIQ
30.04.2020, 20:43
Какое отношение это ПО имеет к РАДИОСВЯЗИ?
А какое отношение имеет интернет к радиосвязи? Тем не менее вы поневоле в нем пропадаете. По правилам форума эта тема размещена в разделе "Цифровая техника. Компьютеры. Программное обеспечение." Не знаю как вы это относите к радиолюбительству. А еще есть раздел "Бытовая техника", там то же не насвистывают морзянку. Авторов программы тут двое, я Windows версии, а Анатолий без позывного Андроидной версии. Кстати на этом форуме присутствуют люди без позывного и они его активные участники. Думаете их надо отсюда гнать "поганой" метлой? А ведь нигде не написано в правилах форума, что тут должны быть только люди с красивыми позывными.


А от зачем ее "пиарить" на форуме, где большинство пользователей считает ее бессмысленной?. Не пойму.
Это мысли про себя или перед вами лежит подробный отсчет кто прочитал тему и что про нее думает? Тему прочитали 479 человек. Программу запустили и проверили с более 2000 IP адресов. Откуда у вас статистика про мысли всех этих людей юзавших программу?


Нет понятной инструкции пользователя. Отсюда и вопросы.
Тема еще не разрослась, не трудно ее прочитать с начала. Найдете ответы на интересующие вас вопросы.

RL6M
01.05.2020, 07:07
А какое отношение имеет интернет к радиосвязи? Тем не менее вы поневоле в нем пропадаете. По правилам форума эта тема размещена в разделе "Цифровая техника. Компьютеры. Программное обеспечение." Не знаю как вы это относите к радиолюбительству. А еще есть раздел "Бытовая техника", там то же не насвистывают морзянку. Авторов программы тут двое, я Windows версии, а Анатолий без позывного Андроидной версии. Кстати на этом форуме присутствуют люди без позывного и они его активные участники. Думаете их надо отсюда гнать "поганой" метлой? А ведь нигде не написано в правилах форума, что тут должны быть только люди с красивыми позывными.

В том то и дело, что никаких правил вы не нарушили. И никто вас отсюда не гонит...
Вы просто создали непонятный заголовок, вот и попалось на него 480 человек, в том числе и я. :-)

Я вашу программу не скачивал, поскольку нее вижу смысла в ней :-), но могу дать совет, что исправить, чтобы ей воспользовалось гораздо больше РАДИОЛЮБИТЕЛЕЙ С ПОЗЫВНЫМИ ....


Вместо "УКВ потаскушки", нужно бы сделать "переднюю панель обычного КВ трансивера", где ваши индексы это "условные любительские частоты", изменяемые "ручкой настройки", добавить окно ведения аппаратного журнала, чтобы проведенные "виртуальные" связи можно потом было бы сохранить в виде ADIF (CABRILLO) файла.

И в один из дней провести первый экспериментальный виртуальный контест. Хотя бы просто в телефонном режиме. Для справедливости (и приближения к реальному эфиру) необходимо добавить некоторую вероятность связи между двумя корреспондентами.
Условно говоря, чтобы я с Владивостоком не смог провести связь в 12 часов дня на виртуальной частоте 3.650, поскольку это и в реальном эфире невозможно... и т.д.

Эта идея совершенно не моя, но мне было бы реально интересно, поскольку это имело бы прямое отношение к моим интересам в радио. И, я думаю, тогда у вас 2000 IP адресов будет использовать вашу программу одновременно. Плюс, последующим этапом возможна будет и монетизация проекта, чтобы вашему программисту было интересно. Думаю, вы догадываетесь как...


Тимофей

RN6LIQ
01.05.2020, 07:56
Тимофей, благодарю вас за советы, но хотелось бы еще раз пояснить, что у этого проекта своя ниша и в первом посте я описал его предназначение. Создавать полную копию виртуального эфира никогда не стремился, но полу копии у меня есть. Вот тут (http://www.cqham.ru/forum/showthread.php?28073-%C2%E8%F0%F2%F3%E0%EB%FC%ED%E0%FF-quot-%F8%E0%F0%EC%E0%ED%EA%E0-quot) виртуальная шарманка, где общаются люди у которых проблемы с антеннами или просто нравится общение в формате радио эфира. Красивой мордашки трансивера нет, жаль тратить на это свое время которого всегда не хватает. Официальный сайт (http://tiparadio.ru/) проекта. Есть проект (http://www.cqham.ru/forum/showthread.php?35606-%C2%E8%F0%F2%F3%E0%EB%FC%ED%FB%E9-%FD%F4%E8%F0-%E4%EB%FF-%F2%E5%EB%E5%E3%F0%E0%F4%E8%F1%F2%EE%E2) приближенный более и менее к реальному звучанию эфира. Там меньше народу, но все равно есть свои поклонники которые, что бы не засорять реальный эфир проводят тренировочные связи телеграфом.
А что касается монетизации моих проектов, так слава Богу есть на что жить. Есть работа и к тому поклонники моих программ периодически помогают своими пожертвованиями в поддержке серверов, их оплаты и модернизации. Анатолий свою версию данного проекта так же предоставляет бесплатно, по крайней мере версию с теми же возможностями что и моя версия под Windows. Но какие то другие проекты конечно же ему надо монетизировать, но это уже его выбор.

RW3FB
01.05.2020, 10:44
Дорабатывать тут нечего. Единственная серьезная доработка, которую сделал - это отображение числа пользователей в канале. Это действительно удобно, но сразу ограничило некоторые перспективные направления развития. Не клиентской программы, а серверной. Для различных возможностей у меня есть другие проекты. А в этом только подыгрывать микроконтроллерам. Ну и простота главное удобство программы.

Василий, привет.
А не планируется ли управление PTT через COM порт для возможности сопряжения с RoIP шлюзами? И VOX тоже было бы неплохо.

RN6LIQ
01.05.2020, 11:24
А не планируется ли управление PTT через COM порт для возможности сопряжения с RoIP шлюзами?
Евгений, версии под Windows и Андроид это просто дань совместимости с популярными операционными системами где будет работать конечная программа. А с другой стороны, рядом с радиостанцией, будет работать версия под Linux или версия на микроконтроллере, и вот там все будет как вы хотите. Если вы еще не юзали микрокомпьютеры, типа RaspberryPI, то советую это сделать. Это более экономически оправданное решение чем использовать для этого полноценный компьютер под управлением Windows. Но и тут можно использовать Windows версию с функцией VOX, как ее включить могу подсказать. А еще круче прикрутить к радиостанции микроконтроллер. Сейчас, когда базовая система создана, я возвращаюсь к совместной работе с Владимиром, RZ6AT, и мы будем делать версию этой программы на микроконтроллерах, результаты этой работы будем выкладывать тут же, на этой ветке.

RN6LIQ
04.05.2020, 18:35
Итак, мы с Владимиром(RZ6AT) покажем применение микроконтроллера Arduino UNO + Ethernet модуль W5500 в данном проекте. Для начала пример попроще. Трансляция только в одну сторону. Выход радиостанции FT-817 будем транслировать во второй канал PMR с индексом 1. Для этого понадобится

259895

Arduino UNO + Ethernet модуль W5500 + FT817 + очень простая схема сопряжения

259896

Ну и сама программа, если есть вопросы по инициализации микроконтроллера, то адресуйте их Владимиру ( RZ6AT )


#include "SPI.h"
#include "Ethernet.h"
#include "EthernetUdp.h"

int pinIn = A0; // АЦП
//ДОБАВЛЯЕМ ПАРАФАЗНЫЕ ВЫХОДЫ ЦАП
int pinTest = 2; // ТЕСТ ПРЕРЫВАНИЯ 8 кГц
byte mac[] = {0xDE, 0xAD, 0xEE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,0,84);
IPAddress ipout(194,63,141,124);
unsigned int localPort = 8984;
unsigned int localPortout = 16000;
EthernetUDP Udp;



// Непосредственно для работы с сервером нужны
byte kanal_PRD; // номер канала 0 - 255
uint16_t kanal_Secret; // и секретный код 0 - 65536
// но в PMR проекте необходим
byte PChannel = 2; // номер канала 0 - 8
uint32_t MailIndex = 1; // и индекс 0 - 999999

void setup()
{
// put your setup code here, to run once:
pinMode(pinIn,INPUT); // АЦП
Serial.begin(115200); // последовательный порт нужен только для отладки и наглядности
// put your setup code here, to run once:
Ethernet.begin(mac,ip);
Udp.begin(localPort);

// Тут происходят настройки АЦП и ЦАП и прерывания 8000. В данном примере нужен только АЦП
//ДОБАВЛЯЕМ АЦП
ADCSRA = 0x87; // ВКЛЮЧАЕМ АЦП, ДЕЛИМ НА 128
ADCSRB = 0x00;
ADMUX = 0x60; // СДВИГАЕМ РЕЗУЛЬТАТ ВЛЕВО, REF=5V, A0 ЧИТАЕМ
// ТАЙМЕР1 ДЛЯ ШИМА
// TCCR1A = 0xB1; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB
TCCR1A = 0x81; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB
TCCR1B = 0x09; // PWM PHASE CORRECT 8 BIT, PRESCALER=1, CLOCK=16MHZ
TCCR1C = 0x80; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB

TCCR2A = 0x02; // ПРЕСКАЛЕР=8
TCCR2B = 0x02; // РЕЖИМ СТС
TIMSK2 = 0x02; // ПРЕРЫВАНИЯ ОТ КОМПАРАТОРА А ТАЙМЕРА 2
OCR2A = 249; // ДЕЛИМ НА 250 sei();
///////////////////////////////////////////////////////////////////////////////////////////////////


Serial.println("START");
// Преобразуем настройки из формата PMR в формат сервера
if(PChannel == 0) kanal_PRD = 0;
else kanal_PRD = (byte)(((MailIndex & 0xF) * 8) + PChannel);
kanal_Secret = (uint16_t)((MailIndex & 0xFFFFFFF0) >> 4); // секретное число 0

Serial.print("MailIndex = ");
Serial.print(MailIndex,DEC);
Serial.print("\tPChannel = ");
Serial.print(PChannel,DEC);
Serial.print("\tkanal_PRD = ");
Serial.print(kanal_PRD,DEC);
Serial.print("\tkanal_Secret = ");
Serial.println(kanal_Secret,DEC);
}

volatile uint16_t ticTest = 0; // счетчик прерываний, наращивается на 1 с каждым прерыванием
char packetBuffer[164]; // Передающий буфер

volatile uint16_t Save0; // указатель записи
volatile uint16_t Load0; // указатель чтения
volatile byte buf0[200]; // кольцевой буфер куда из прерывания размещаются данные АЦП

volatile byte Start = 0; // если значение положительное то начинаем передачу
byte buf[164]; // буфер для передачи в сеть
int kol = 4; // указатель заполнения буфера передачи (первых 4 байта являются служебными)

volatile uint16_t ticVox = 0; //
volatile byte oldVox = 0; //


void loop() {
if(ticTest > 8000) // если было 8000 прерываний ( одна секунда ), то пора напоснить серверу о себе
{
ticTest = 0; // счетчик сбрасываем
buf[0] = 7; // тип пакета таймера
buf[1] = 0;
memcpy(&buf[2],&kanal_Secret,2); // значение секретного кода, на основании этого кода сервер будет коммутировать нам нужные пакеты
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}


int packetSize = Udp.parsePacket(); // проверяем есть ли для нас принятые пакеты
if(packetSize) // есть
{
if(packetSize > 164) packetSize = 164; // в данном режиме нам не нужны пакеты размером более 164 байта
Udp.read(packetBuffer,packetSize); // чтения пакета
switch (packetSize)
{
case 4: // в данном примере нам на прием нужны только служебные пакеты размером 4 байта
if(packetBuffer[0] == 110) // пакет с количеством соединений в канале
{
uint16_t count;
memcpy(&count,&packetBuffer[2],sizeof(count));
Serial.print("Count \t");
Serial.println(count,DEC);
}
break;
default:
{
};
}
}


while(Load0 != Save0) // мониторим заполнения кольцевого буфера
{
buf[kol] = buf0[Load0]; // следуя за указателем чтения заполняем буфер для передачи
kol++; // наращиваем счетчик заполнения буфера передачи
if(kol >= 164) // если буфер заполнен
{
if(Start) // и если есть признак разрешения передачи в сеть
{
buf[0] = 27; // режим 8000 раз в секунду 8 бит
Udp.beginPacket(ipout,localPortout+kanal_PRD);
Udp.write((byte *)buf,164); // передача 160 байт данных с АЦП вместе с 4 байтами служебного заголовка
Udp.endPacket();
}
kol = 4; // указатель записи в буфер передачи сбрасываем в начальное состояние
}

if(Load0 < 199) Load0++; // указатель чтения кольевого буфера наращиваем
else Load0 = 0; // или если достигнут конец буфера сбрасываем в ноль
}
}

void(* resetFunc) (void) = 0; // объявляем функцию reset

// функция прерывания 8000 раз в секунду
ISR(TIMER2_COMPA_vect)
{
int del; //


PORTD |= (1<<pinTest); // СМОТРИМ НА ВЫВОДЕ D2 ПЕРИОД ПРЕРЫВАНИЙ 8 КГц
//ДОБАВЛЯЕМ
byte v = ADCH; // ЧИТАЕМ СТАРШИЙ БАЙТ ИЗ АЦП
if(oldVox > v) del = oldVox - v; // Измеряем изменения уровня на входе АЦП относитель прошлого отсчета
else del = v - oldVox; //
oldVox = v;
v = v - 128; // данные с АЦП преобразоваем в значение со знаком из диапазона 0 - +255 в -127 - +128
buf0[Save0] = v; // заносим в кольцевой буфер
if(Save0 < 199) Save0++; // наращиваем счетчик записи
else Save0 = 0; // а если он достиг конца буфера сбрасываем в ноль


ticTest++; // счетчик обслуживает передачу тестовых сообщений и ...
// к сожалению периодически все это подвисает, причина скорее всего во взаимодействии с Ethernrt модулем по SPI
// если в течении 1,5 секундыв в теле loop не произойдет сброс счетчика в ноль, значит где то на сетевых функциях что то зависло
if(ticTest > 13000) resetFunc(); // поэтому вызываем программный reset


if(del > 10) // если уровень на входе изменяеться больше определенного значения (подбиратся под себя)
{
ticVox = 1; // сбрасывем счетчик VOX в еденицу
if(Start == 0) Start = 1; // если до этого не было признака передачи, то включаем его
}
if(ticVox) // пока счетчик Vox истинен
{
ticVox++; // наращиваем его
if(ticVox > 8000) // если уже больше секунды не было на входе АЦП изменений сигнала ( а следовательно ticVox не сбрасывался в 1 )
{
ticVox = 0; // выключаем счетчик, теперь он не будет наращиваться
Start = 0; // выключаем признак передачи
}
}




ADCSRA |= (1<<ADSC); // ЗАПУСКАЕМ АЦП
PORTD &= ~(1<<pinTest); // СБРАСЫВАЕМ ТЕСТОВЫЙ СИГНАЛ
}



Да, звук не высокого качества, с частотой дискретизации 8000 и всего 8 бит динамического диапазона. Но для ардуинки это шикарно, цена вопроса то что надо. Для чего это может пригодится. Например вы далеко от дома, где осталось включенное радио настроенное на местный репитер. Вместе с ним работает представленная схема на ардуинке. Таким образом вы удаленно можете периодически прослушивать далекий эфир. Причем для этого не надо держать включенным персональный компьютер. Версия PMR под Windows автоматически понимает 8 бит 8000, если нет, то обновите (http://188.168.58.111:8080/READ/PMR.ZIP) ее. Для того что бы Андроид понимал этот режим надо скачать новую версию (http://188.168.58.111:8080/GAME/app-release.apk). Анатолий провел очень большую работу и программа теперь имеет еще больше возможностей.
До утра подержу эту схему включенной, что бы желающие могли послушать качество звука при такой схеме трансляции. Благо не надо держать компьютер включенным. Но с утра все выключу, что бы продолжить работу над примером двухсторонней связи. Добавлю купленные для ардуинки модули микрофонного усилителя и усилителя для вывода звука на динамик и попробую сделать что то типа ГГС ( громко говорящая связь ) по каналу PMR.

RN6LIQ
05.05.2020, 12:05
Итак мы с Владимиром(RZ6AT) представляем версию с дуплексной работой. Код ниже


#include "SPI.h"
#include "Ethernet.h"
#include "EthernetUdp.h"

int pinIn = A0; // АЦП
//ДОБАВЛЯЕМ ПАРАФАЗНЫЕ ВЫХОДЫ ЦАПА
int pinOutP = 9; // ШИМ +
//int pinOutM = 10; // ШИМ -
int pinTest = 2; // ТЕСТ ПРЕРЫВАНИЯ 8 кГц
int pinStart = 8; // Для начала передачи на этот пин надо подать землю
int pinCall = 7; // если прийдет вызов на этом пине какое то время будет переменный сигнал 50 ГЦ
byte mac[] = {0xDE, 0xAD, 0xEE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,0,84);
IPAddress ipout(194,63,141,124);
unsigned int localPort = 8984;
unsigned int localPortout = 16000;
EthernetUDP Udp;

// Непосредственно для работы с сервером нужны
byte kanal_PRD; // номер канала 0 - 255
uint16_t kanal_Secret; // и секретный код 0 - 65536
// но в PMR проекте необходим
byte PChannel = 2; // номер канала 0 - 8
uint32_t MailIndex = 1; // и индекс 0 - 999999



void setup()
{
// put your setup code here, to run once:
pinMode(pinIn,INPUT); // АЦП
// В этом примере уже убираю работу с последовательным портом, поскольку хронически не хватет памяти
// put your setup code here, to run once:
Ethernet.begin(mac,ip);
Udp.begin(localPort);

pinMode(pinOutP,OUTPUT); //ВЫХОД НА НАУШНИК ПЛЮСОВОЙ
//pinMode(pinOutM,OUTPUT); //ВЫХОД НА НАУШНИК МИНУСОВОЙ, тут я изменил настройки Владимира (RZ6AT) поскольку у меня немного другая схема вывода звука
pinMode(pinTest,OUTPUT);
pinMode(pinCall,OUTPUT);
pinMode(pinStart,INPUT);
digitalWrite(pinStart, 1); // поджимаем резистром ножку, что бы не бвло ложного срабатывания

//ДОБАВЛЯЕМ АЦП
ADCSRA = 0x87; // ВКЛЮЧАЕМ АЦП, ДЕЛИМ НА 128
ADCSRB = 0x00;
ADMUX = 0x60; // СДВИГАЕМ РЕЗУЛЬТАТ ВЛЕВО, REF=5V, A0 ЧИТАЕМ

// ТАЙМЕР1 ДЛЯ ШИМА
// TCCR1A = 0xB1; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB // тут изменил, потому что другая у меня схема вывода звука
TCCR1A = 0x81; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB
TCCR1B = 0x09; // PWM PHASE CORRECT 8 BIT, PRESCALER=1, CLOCK=16MHZ
TCCR1C = 0x80; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB

TCCR2A = 0x02; // ПРЕСКАЛЕР=8
TCCR2B = 0x02; // РЕЖИМ СТС
TIMSK2 = 0x02; // ПРЕРЫВАНИЯ ОТ КОМПАРАТОРА А ТАЙМЕРА 2
OCR2A = 249; // ДЕЛИМ НА 250
sei();
// Преобразуем настройки из формата PMR в формат сервера
if(PChannel == 0) kanal_PRD = 0;
else kanal_PRD = (byte)(((MailIndex & 0xF) * 8) + PChannel);
kanal_Secret = (uint16_t)((MailIndex & 0xFFFFFFF0) >> 4); // секретное число 0
}
volatile uint16_t ticTest = 0; // обслуживает посылку тестовых посылок и перезапуск при зависании
char packetBuffer[164]; // приемный буфер
// кольцевой буфер с указателями записи и чтения для работы с АЦП
volatile uint16_t Save0;
volatile uint16_t Load0;
volatile byte buf0[200];
// кольцевой буфер с указателями записи и чтения для ЦАП реализованного на ШИМ
volatile uint16_t Save1;
volatile uint16_t Load1;
volatile byte buf1[640];

volatile uint32_t kolrecv = 0; // хранит количество байт в очереди на воспроизведение

volatile uint16_t play = 0; // индикатор воспроизведения, нужен для корректного вывода звука в прерывании
volatile byte Start = 0; // если истинно (не ноль) звук перелается в сеть
// передающий буфер с указателем
int kol = 4;
byte buf[164];

volatile uint32_t tic = 0; // обслуживает сброс переменных если больше секунды не было приема звука

volatile boolean actionState = LOW; // обслуживает индикацию приема вызова, 50 ГЦ
volatile uint16_t call = 0;
volatile uint8_t call_50 = 0;

uint8_t d_reg; // в прерывании сюда заносится состояние региста PINB

volatile int16_t Kto = -1; // хранит IP принимаемого пользователя, значение от 0 и выше, если -1 то никого не принимаем


void loop() {


if(kolrecv < 480) // проверяем, что бы было место под воспроизведение звука, в сязи с катастрофической нехваткой памяти на Ардуино
{ // приходится с Ethernet модуля забирать данные только тогда, когда есть куда их разместить. Таким образом W5100 помогает избавится от рывков звука
int packetSize = Udp.parsePacket(); // проверяем есть ли данные на приеме
if(packetSize) // если есть
{
if(packetSize > 164) packetSize = 164; // в данном режиме нам не нужны пакеты размером более 164 байта

Udp.read(packetBuffer,packetSize); // читаем их
if(packetSize == 4) // обрабатываем служебные пакеты, они всегда имеют размер 4 байта
{
if(packetBuffer[0] == 110) // пакет с количеством соединений в канале, тут на ардуинке это некуда притулить, поскольку нет экрана индикации
{
//uint16_t count;
//memcpy(&count,&packetBuffer[2],sizeof(count));
//Serial.print("Count \t");
//Serial.println(count,DEC);
}
}
else // остальные, не служебные пакеты
{
switch (packetBuffer[0]) // в первом байте приемного буфера помещен тип пакета
{
case 20: // пришел сигнал вызова
call = 1;
digitalWrite(pinCall, HIGH);
break;

case 27: // пришел звуковой пакет
{
int16_t kto,i;
memcpy(&kto,&packetBuffer[2],sizeof(kto)); // узнаем ID пользователя кто его прислал
if(Kto == -1) // если до этого никто не от кого не принимали, то
{
Kto = kto; // начинаем принимать этого пользователя
}
else
{
if(Kto != kto) break; // если уже кого то принимаем, но пакет пришел не от того пользователя, то игнорируем
}
tic = 0; // сбрасывется счетчик индикации приема звука
for(i = 4; i < 164; i++) // заносим принятые данные в кольцевой буфер
{
buf1[Save1] = packetBuffer[i] + 128;
if(Save1 < 639) Save1++;
else Save1 = 0;
}
kolrecv = kolrecv + 160;
}
break;
default:
{
};
}
}
}
}

if(tic > 8000) // нет приема звука уже секунду,
{
tic = 0;
kolrecv = 0;
Kto = -1;
}

if(!(d_reg & 0x01)) // в этом проекте нет кнопки вызова, вместо этого есть алгоритм поднятия телефонной трубки, если трубка была поднята
{
if(call) // но мы синалим внешний вызов
{ // то прекращаем это делать
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}

Start = 1; // Начинаем передачу
}
else // земля на 8 ножке пропала ( положили трубку )
{ //
Start = 0; // выключаем передачу
}



if(ticTest > 8000) // если прошла секунда
{
ticTest = 0; // счетчик сбрасываем
buf[0] = 7; // тип пакета таймера
buf[1] = 0;
memcpy(&buf[2],&kanal_Secret,2); // значение секретного кода, на основании этого кода сервер будет коммутировать нам нужные пакеты
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}



while(Load0 != Save0) // Забираем данные с АЦП
{
buf[kol] = buf0[Load0];
kol++;
if(kol >= 164)
{
if(Start) // если разрешена передача, передаем звук
{
buf[0] = 27; // режим 8000 раз в секунду 8 бит
Udp.beginPacket(ipout,localPortout+kanal_PRD);
Udp.write((byte *)buf,164); // передача 160 байт данных с АЦП вместе с 4 байтами служебного заголовка
Udp.endPacket();
}
kol = 4; // указатель сбрасываем (первых 4 байта это служебный заголовок)
}

if(Load0 < 199) Load0++;
else Load0 = 0;
}


if(call) // обслуживаем прием вызова
{
if(call > 24000) // прошло 4 секунды с момента звучания, значит выключаем
{
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}
else // звучит сигнал вызова
{
// if(call_50 > 159) // 50 Hz, на моем DECT телефоне куда я подключал данную плату надо на определенную ножку микросхемы подать 50 гц, тогда в телефоне звучит звонок
if(call_50 > 7) // 1000 Hz, но можно поросто подать 1000 герц на любую пищалку, в тихой комнате ее хорошо слышно.
{
call_50 = 0;
if(actionState)
{
actionState = 0;
}
else
{
actionState = 1;
}
digitalWrite(pinCall, actionState); // сообственно на ножке меняем постоянно TTL уровень
}
}
}

}

void(* resetFunc) (void) = 0; // объявляем функцию reset
// функция прерывания
ISR(TIMER2_COMPA_vect)
{
d_reg = PINB; // Считываем порт, узнаем какие ножки в каком состоянии, за одно считывание сразу 8 ножек, правильное решение для прерывания в котором нельзя долго задерживаться




PORTD |= (1<<pinTest); // СМОТРИМ НА ВЫВОДЕ D2 ПЕРИОД ПРЕРЫВАНИЙ 8 КГц
//ДОБАВЛЯЕМ
byte v = ADCH; // ЧИТАЕМ СТАРШИЙ БАЙТ ИЗ АЦП
v = v - 128; // обязательно делаем число со знаком, звуковые карты другие значения не понимают
buf0[Save0] = v; // заносим значения АЦП в кольцевой буфер
if(Save0 < 199) Save0++;
else Save0 = 0;

if(play == 0) // нет было приема звука до этого
{
if(kolrecv > 320) play = 1; // если в теле loop приняты уже три звуковых пакета, то начинаем воспроизведение. Упреждение необходимо, что бы избавится от рывков звука
}
else // воспроизведение включено
{
if(Load1 != Save1) // есть звук для воспроизведения, отправляем его в ЦАП ( ШИМ )
{
v = buf1[Load1];
OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1
if(Load1 < 639) Load1++;
else Load1 = 0;
if(kolrecv) kolrecv--; // отмечаем уменьшение очереди байт на воспроизведение
play = 1; // можно конечно не делать этого, но на всякий случай сбрасываю счетчик еще раз
}
else // нет звука
{
if(play) // если до этого было воспроизведение
{
play++; // наращиваем счетчик
if(play > 500) // если прошло времени с момента прошлого пакета больше 500 тиков, то считаем, что связь разорвана
{
play = 0;
Kto = -1;
kolrecv = 0;
}
}
}
}
ticTest++;
tic++;

// если программа подвисла, то
if(ticTest > 13000) resetFunc(); //вызываем reset


if(call) // обслуживание звучания зуммера
{
call++;
call_50++;
}

// Тут Владимир проверял на себя АЦП на ЦАП
// OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
// OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1

ADCSRA |= (1<<ADSC); // ЗАПУСКАЕМ АЦП
PORTD &= ~(1<<pinTest); // СБРАСЫВАЕМ ТЕСТОВЫЙ СИГНАЛ
}



Честно говоря уже устал сидеть за компьютером, поэтому схему расскажу на словах. Относительно входа ничего не поменялось, просто вместо выхода FT-817 был подан сигнал на АЦП с микрофонного усилителя. Выход ЦАП снимается с 9 ножки, на Ардуинке, да и на картинке в предыдущем посте, она подписана этим номером. Обязательно нужно поставить RC фильтр как сделано по входу, номиналы те же 470 и 0.1 и затем подать этот сигнал на высокоомную нагрузку, Владимир настоятельно это рекомендует, так как за наш ЦАП работает ШИМ. Я же просто подал на усилитель. Проверили с Владимиром, он с Андроидной версии, а я с Ардуинки. Все хорошо работает, качество служебной связи. Для того что бы стать на передачу нужно подать землю на восьмую ножку. Если пришел вызов, то на 7 ножке будет слышен зуммер 1000 герц. Подачу вызова не делал, но это уже не сложно сделать самостоятельно. Для этого надо сделать анализ состояния нужного pin и послать служебный пакет из 4 байт, первым байтом где будет значение 20.

UA0YAS
05.05.2020, 15:55
Работает! только вот приложение под андроид вылетает при попытке сменить номер канал или нажатии на низ экрана

RN6LIQ
05.05.2020, 16:21
В предыдущем посте допустил оговорку, плату W5100 назвал W5500. Ну кто соображает наверное все понял правильно, на фотографии сразу видно что там изображено. На Arduino Nano нами как раз пробовалась и плата W5500. Она компактнее и современнее, да и по размеру больше соответствует Arduino Nano. Но в макетном варианте у меня лично они работали неустойчиво, длинные провода по интерфейсу SPI глючили. А у Владимира таких глюков не было. Тут надо сразу паять все короткими проводами. А так это почти то же самое, что и описанная выше конструкция. Только надо свою библиотеку использовать EthernetUdp2.h
Есть соблазн использовать вместо провода Ethernet, - связь WiFi, и для этого ESP8266 очень симпатично просится. Там правда нет того красивого протокола взаимодействия. У меня есть две ESP8266, одна по круче, другая попроще, с минимум GPIO. На мой взгляд единственный путь приспособить ее для проекта это не использовать стандартную прошивку, а залить свой скетч. Взаимодействие с другими устройствами организовать по последовательному порту. И у Arduino и у ESP8266 последовательный порт железно работает со скоростью 1 Мбит, этого вполне достаточно. Если бы стояла такая практическая задача, то уже сделал бы. Наверное и сделаю, но уже не с Arduino в паре, а с STMкой. Тут опять понадобиться помощь Владимира, придется мне осваивать новую среду программирования. Но STMки того стоят. Есть где разгуляться. памяти поболее, а процессоры уже 32 разрядные. В 8-ми разрядных процессорах напрягает то, что трудно применять прежние наработки, вечно где то прячутся ошибки связанные с неявным представлением типов данных. А в 32 разрядных с этим все нормально, готовые куски исходного кода компилируются также как и на персональных компьютерах. Выходные дни заканчиваются, завтра на работу. Хоть и короткая неделя, но рабочая. В принципе, для всех интересующихся данным проектом, основную часть заявленных готовых программ и некоторого исходного кода мы выложили. Есть "пища" для практических экспериментов. У Анатолия наверное еще будет чем удивить с Андроид версией, а мы с Владимиром берем тайм-аут и даст Бог вернемся с уже готовыми вариантами на 32 разрядных процессорах. Главная цель улучшить качество звука и расширить функционал.

RN6LIQ
05.05.2020, 16:24
Работает! только вот приложение под андроид вылетает при попытке сменить номер канал или нажатии на низ экрана

Тут видимо все зависит от версии Андроида, у меня работает нормально, у Владимира то же. Ребята с которыми общался то же не жалуются.

UA0YAS
05.05.2020, 17:06
видимо не для всех версий- не работает на старых 4.2 и на новых 7.0, нужны средние....:s7:

UD4FD
06.05.2020, 01:24
В предыдущем посте допустил оговорку, плату W5100 назвал W5500. Ну кто соображает наверное все понял правильно, на фотографии сразу видно что там изображено. На Arduino Nano нами как раз пробовалась и плата W5500. Она компактнее и современнее, да и по размеру больше соответствует Arduino Nano. Но в макетном варианте у меня лично они работали неустойчиво, длинные провода по интерфейсу SPI глючили. А у Владимира таких глюков не было. Тут надо сразу паять все короткими проводами. А так это почти то же самое, что и описанная выше конструкция. Только надо свою библиотеку использовать EthernetUdp2.h
Есть соблазн использовать вместо провода Ethernet, - связь WiFi, и для этого ESP8266 очень симпатично просится. Там правда нет того красивого протокола взаимодействия. У меня есть две ESP8266, одна по круче, другая попроще, с минимум GPIO. На мой взгляд единственный путь приспособить ее для проекта это не использовать стандартную прошивку, а залить свой скетч. Взаимодействие с другими устройствами организовать по последовательному порту. И у Arduino и у ESP8266 последовательный порт железно работает со скоростью 1 Мбит, этого вполне достаточно. Если бы стояла такая практическая задача, то уже сделал бы. Наверное и сделаю, но уже не с Arduino в паре, а с STMкой. Тут опять понадобиться помощь Владимира, придется мне осваивать новую среду программирования. Но STMки того стоят. Есть где разгуляться. памяти поболее, а процессоры уже 32 разрядные. В 8-ми разрядных процессорах напрягает то, что трудно применять прежние наработки, вечно где то прячутся ошибки связанные с неявным представлением типов данных. А в 32 разрядных с этим все нормально, готовые куски исходного кода компилируются также как и на персональных компьютерах. Выходные дни заканчиваются, завтра на работу. Хоть и короткая неделя, но рабочая. В принципе, для всех интересующихся данным проектом, основную часть заявленных готовых программ и некоторого исходного кода мы выложили. Есть "пища" для практических экспериментов. У Анатолия наверное еще будет чем удивить с Андроид версией, а мы с Владимиром берем тайм-аут и даст Бог вернемся с уже готовыми вариантами на 32 разрядных процессорах. Главная цель улучшить качество звука и расширить функционал.
Не трогайте ESP8266 - лучше сразу берите ESP32 - у него есть интерфейс I2S для подключения полноценных микросхем аудио-кодеков 16/24 бита, да и проц там мощнее и памяти больше - можно использовать сжатие данных...

RN6LIQ
06.05.2020, 09:22
"Допилил" кнопку вызова (6 pin ) и кнопку включения режима VOX ( 5 pin ). Подавать нужно "землю". Когда идет прием, - на 4 контакте присутствует напряжение, и наоборот. Это пригодится для того, что бы включать/выключать передатчик, в случае удаленного управления. Правда на "железке" не проверял.



#include "SPI.h"
#include "Ethernet.h"
#include "EthernetUdp.h"

int pinIn = A0; // АЦП
//ДОБАВЛЯЕМ ПАРАФАЗНЫЕ ВЫХОДЫ ЦАПА
int pinOutP = 9; // ШИМ +
//int pinOutM = 10; // ШИМ -
int pinTest = 2; // ТЕСТ ПРЕРЫВАНИЯ 8 кГц
int pinStart = 8; // Для начала передачи на этот пин надо подать землю
int pinCall = 7; // если поступил вызов на этом пине какое то время будет переменный сигнал 1000 ГЦ
int pinSendCall = 6; // Для вызова на этот пин надо подать землю
int pinOnVox = 5; // Для включения VOX на этот пин надо подать землю
int pinGoPlay = 4; // Для включения передатчика
byte mac[] = {0xDE, 0xAD, 0xEE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,0,84);
IPAddress ipout(194,63,141,124);
unsigned int localPort = 8984;
unsigned int localPortout = 16000;
EthernetUDP Udp;

// Непосредственно для работы с сервером нужны
byte kanal_PRD; // номер канала 0 - 255
uint16_t kanal_Secret; // и секретный код 0 - 65536
// но в PMR проекте необходим
byte PChannel = 2; // номер канала 0 - 8
uint32_t MailIndex = 1; // и индекс 0 - 999999



void setup()
{
// put your setup code here, to run once:
pinMode(pinIn,INPUT); // АЦП
// В этом примере уже убираю работу с последовательным портом, поскольку хронически не хватет памяти
// put your setup code here, to run once:
Ethernet.begin(mac,ip);
Udp.begin(localPort);

pinMode(pinOutP,OUTPUT); //ВЫХОД НА НАУШНИК ПЛЮСОВОЙ
//pinMode(pinOutM,OUTPUT); //ВЫХОД НА НАУШНИК МИНУСОВОЙ, тут я изменил настройки Владимира (RZ6AT) поскольку у меня немного другая схема вывода звука
pinMode(pinTest,OUTPUT);
pinMode(pinCall,OUTPUT);
pinMode(pinStart,INPUT);
digitalWrite(pinStart, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinSendCall,INPUT);
digitalWrite(pinSendCall, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinOnVox,INPUT);
digitalWrite(pinOnVox, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinGoPlay,OUTPUT);



//ДОБАВЛЯЕМ АЦП
ADCSRA = 0x87; // ВКЛЮЧАЕМ АЦП, ДЕЛИМ НА 128
ADCSRB = 0x00;
ADMUX = 0x60; // СДВИГАЕМ РЕЗУЛЬТАТ ВЛЕВО, REF=5V, A0 ЧИТАЕМ

// ТАЙМЕР1 ДЛЯ ШИМА
// TCCR1A = 0xB1; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB // тут изменил, потому что другая у меня схема вывода звука
TCCR1A = 0x81; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB
TCCR1B = 0x09; // PWM PHASE CORRECT 8 BIT, PRESCALER=1, CLOCK=16MHZ
TCCR1C = 0x80; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB

TCCR2A = 0x02; // ПРЕСКАЛЕР=8
TCCR2B = 0x02; // РЕЖИМ СТС
TIMSK2 = 0x02; // ПРЕРЫВАНИЯ ОТ КОМПАРАТОРА А ТАЙМЕРА 2
OCR2A = 249; // ДЕЛИМ НА 250
sei();
// Преобразуем настройки из формата PMR в формат сервера
if(PChannel == 0) kanal_PRD = 0;
else kanal_PRD = (byte)(((MailIndex & 0xF) * 8) + PChannel);
kanal_Secret = (uint16_t)((MailIndex & 0xFFFFFFF0) >> 4); // секретное число 0

digitalWrite(pinGoPlay, LOW);

}
volatile uint16_t ticTest = 0; // обслуживает посылку тестовых посылок и перезапуск при зависании
char packetBuffer[164]; // приемный буфер
// кольцевой буфер с указателями записи и чтения для работы с АЦП
volatile uint16_t Save0;
volatile uint16_t Load0;
volatile byte buf0[200];
// кольцевой буфер с указателями записи и чтения для ЦАП реализованного на ШИМ
volatile uint16_t Save1;
volatile uint16_t Load1;
volatile byte buf1[640];

volatile uint32_t kolrecv = 0; // хранит количество байт в очереди на воспроизведение

volatile uint16_t play = 0; // индикатор воспроизведения, нужен для корректного вывода звука в прерывании
volatile byte GoPlay = 0; // если истинен, то значит идет прием звука

volatile byte Start = 0; // если истинно (не ноль) звук перелается в сеть
// передающий буфер с указателем
int kol = 4;
byte buf[164];

volatile uint32_t tic = 0; // обслуживает сброс переменных если больше секунды не было приема звука

volatile boolean actionState = LOW; // обслуживает индикацию приема вызова, 1000 ГЦ
volatile uint16_t call = 0;
volatile uint8_t call_50 = 0;

uint8_t b_reg; // в прерывании сюда заносится состояние региста PINB
uint8_t d_reg; // в прерывании сюда заносится состояние региста PIND

uint8_t SendCall = 0; // При переходе с нуля в еденицу посылаем вызов
uint8_t StartVox = 0; // Если истинно, то работает режим VOX


volatile int16_t Kto = -1; // хранит IP принимаемого пользователя, значение от 0 и выше, если -1 то никого не принимаем


void loop() {


if(kolrecv < 480) // проверяем, что бы было место под воспроизведение звука, в сязи с катастрофической нехваткой памяти на Ардуино
{ // приходится с Ethernet модуля забирать данные только тогда, когда есть куда их разместить. Таким образом W5100 помогает избавится от рывков звука
int packetSize = Udp.parsePacket(); // проверяем есть ли данные на приеме
if(packetSize) // если есть
{
if(packetSize > 164) packetSize = 164; // в данном режиме нам не нужны пакеты размером более 164 байта

Udp.read(packetBuffer,packetSize); // читаем их
if(packetSize == 4) // обрабатываем служебные пакеты, они всегда имеют размер 4 байта
{
if(packetBuffer[0] == 110) // пакет с количеством соединений в канале, тут на ардуинке это некуда притулить, поскольку нет экрана индикации
{
//uint16_t count;
//memcpy(&count,&packetBuffer[2],sizeof(count));
//Serial.print("Count \t");
//Serial.println(count,DEC);
}
}
else // остальные, не служебные пакеты
{
switch (packetBuffer[0]) // в первом байте приемного буфера помещен тип пакета
{
case 20: // пришел сигнал вызова
call = 1;
digitalWrite(pinCall, HIGH);
break;

case 27: // пришел звуковой пакет
{
int16_t kto,i;
memcpy(&kto,&packetBuffer[2],sizeof(kto)); // узнаем ID пользователя кто его прислал
if(Kto == -1) // если до этого никто не от кого не принимали, то
{
Kto = kto; // начинаем принимать этого пользователя
}
else
{
if(Kto != kto) break; // если уже кого то принимаем, но пакет пришел не от того пользователя, то игнорируем
}
tic = 0; // сбрасывется счетчик индикации приема звука
for(i = 4; i < 164; i++) // заносим принятые данные в кольцевой буфер
{
buf1[Save1] = packetBuffer[i] + 128;
if(Save1 < 639) Save1++;
else Save1 = 0;
}
kolrecv = kolrecv + 160;
}
break;
default:
{
};
}
}
}
}

if(tic > 8000) // нет приема звука уже секунду,
{
tic = 0;
kolrecv = 0;
Kto = -1;
}

if(play)
{
if(GoPlay == 0)
{
GoPlay = 1;
digitalWrite(pinGoPlay, HIGH);
}
}
else
{
if(GoPlay)
{
GoPlay = 0;
digitalWrite(pinGoPlay, LOW);
}
}



if(!(d_reg & 0x40)) //
{
if(SendCall == 0)
{
SendCall = 1;
buf[0] = 20; // тип пакета вызова
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}
}
else
{
SendCall = 0;
}

if(!(d_reg & 0x20)) //
{
StartVox = 1; // Режим VOX включен
}
else
{
StartVox = 0; // Режим VOX выключен
}


if(StartVox == 0)
{
if(!(b_reg & 0x01)) // в этом проекте нет кнопки вызова, вместо этого есть алгоритм поднятия телефонной трубки, если трубка была поднята
{
if(call) // но мы синалим внешний вызов
{ // то прекращаем это делать
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}

Start = 1; // Начинаем передачу
}
else // земля на 8 ножке пропала ( положили трубку )
{ //
Start = 0; // выключаем передачу
}
}


if(ticTest > 8000) // если прошла секунда
{
ticTest = 0; // счетчик сбрасываем
buf[0] = 7; // тип пакета таймера
buf[1] = 0;
memcpy(&buf[2],&kanal_Secret,2); // значение секретного кода, на основании этого кода сервер будет коммутировать нам нужные пакеты
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}



while(Load0 != Save0) // Забираем данные с АЦП
{
buf[kol] = buf0[Load0];
kol++;
if(kol >= 164)
{
if(Start) // если разрешена передача, передаем звук
{
buf[0] = 27; // режим 8000 раз в секунду 8 бит
Udp.beginPacket(ipout,localPortout+kanal_PRD);
Udp.write((byte *)buf,164); // передача 160 байт данных с АЦП вместе с 4 байтами служебного заголовка
Udp.endPacket();
}
kol = 4; // указатель сбрасываем (первых 4 байта это служебный заголовок)
}

if(Load0 < 199) Load0++;
else Load0 = 0;
}


if(call) // обслуживаем прием вызова
{
if(call > 24000) // прошло 4 секунды с момента звучания, значит выключаем
{
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}
else // звучит сигнал вызова
{
// if(call_50 > 159) // 50 Hz, на моем DECT телефоне куда я подключал данную плату надо на определенную ножку микросхемы подать 50 гц, тогда в телефоне звучит звонок
if(call_50 > 7) // 1000 Hz, но можно поросто подать 1000 герц на любую пищалку, в тихой комнате ее хорошо слышно.
{
call_50 = 0;
if(actionState)
{
actionState = 0;
}
else
{
actionState = 1;
}
digitalWrite(pinCall, actionState); // сообственно на ножке меняем постоянно TTL уровень
}
}
}

}

volatile uint16_t ticVox = 0; //
volatile byte oldVox = 0; //


void(* resetFunc) (void) = 0; // объявляем функцию reset
// функция прерывания
ISR(TIMER2_COMPA_vect)
{
b_reg = PINB; // Считываем порт, узнаем какие ножки в каком состоянии, за одно считывание сразу 8 ножек, правильное решение для прерывания в котором нельзя долго задерживаться
d_reg = PIND; //



PORTD |= (1<<pinTest); // СМОТРИМ НА ВЫВОДЕ D2 ПЕРИОД ПРЕРЫВАНИЙ 8 КГц
//ДОБАВЛЯЕМ
byte v = ADCH; // ЧИТАЕМ СТАРШИЙ БАЙТ ИЗ АЦП
int del;
if(StartVox)
{
if(oldVox > v) del = oldVox - v; // Измеряем изменения уровня на входе АЦП относитель прошлого отсчета
else del = v - oldVox; //
}
v = v - 128; // обязательно делаем число со знаком, звуковые карты другие значения не понимают
buf0[Save0] = v; // заносим значения АЦП в кольцевой буфер
if(Save0 < 199) Save0++;
else Save0 = 0;

if(play == 0) // нет было приема звука до этого
{
if(kolrecv > 320) play = 1; // если в теле loop приняты уже три звуковых пакета, то начинаем воспроизведение. Упреждение необходимо, что бы избавится от рывков звука
}
else // воспроизведение включено
{
if(Load1 != Save1) // есть звук для воспроизведения, отправляем его в ЦАП ( ШИМ )
{
v = buf1[Load1];
OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1
if(Load1 < 639) Load1++;
else Load1 = 0;
if(kolrecv) kolrecv--; // отмечаем уменьшение очереди байт на воспроизведение
play = 1; // можно конечно не делать этого, но на всякий случай сбрасываю счетчик еще раз
}
else // нет звука
{
if(play) // если до этого было воспроизведение
{
play++; // наращиваем счетчик
if(play > 500) // если прошло времени с момента прошлого пакета больше 500 тиков, то считаем, что связь разорвана
{
play = 0;
Kto = -1;
kolrecv = 0;
}
}
}
}
ticTest++;
tic++;

// если программа подвисла, то
if(ticTest > 13000) resetFunc(); //вызываем reset


if(call) // обслуживание звучания зуммера
{
call++;
call_50++;
}

if(StartVox)
{
if(del > 10) // если уровень на входе изменяеться больше определенного значения (подбиратся под себя)
{
ticVox = 1; // сбрасывем счетчик VOX в еденицу
if(Start == 0) Start = 1; // если до этого не было признака передачи, то включаем его
}
if(ticVox) // пока счетчик Vox истинен
{
ticVox++; // наращиваем его
if(ticVox > 8000) // если уже больше секунды не было на входе АЦП изменений сигнала ( а следовательно ticVox не сбрасывался в 1 )
{
ticVox = 0; // выключаем счетчик, теперь он не будет наращиваться
Start = 0; // выключаем признак передачи
}
}
}

// Тут Владимир проверял на себя АЦП на ЦАП
// OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
// OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1

ADCSRA |= (1<<ADSC); // ЗАПУСКАЕМ АЦП
PORTD &= ~(1<<pinTest); // СБРАСЫВАЕМ ТЕСТОВЫЙ СИГНАЛ
}

UA0YAS
06.05.2020, 10:35
Василий, а сам сервер это " секрет фирмы"?? Не распространяется?

RN6LIQ
06.05.2020, 11:35
Василий, а сам сервер это " секрет фирмы"?? Не распространяется?

Писал уже ранее, что сейчас используем халявный сервер который оплачен до октября месяца этого года, одновременно тестируем нагрузку на сервер. По окончании аренды я предоставлю сервер в версиях под Windows и Linux в виде исполняемых файлов. Кто то из доверенных людей, получит и в исходных кодах. Я предпочитаю публично не делиться исходными кодами, особенно серверов. Хотя там ничего умудренного нет, но облегчать жизнь разным хулиганам не хочу. Они и в исполняемых файлах находят как напакостить. А тратить свое время на блокировки их злостных действий мне не хочется, в виртуальной шарманке это надоело. Так что пока сервер един, до октября, сервера выкладывать не буду. А после, - пожалуйста. Весь смак этого простого, а значит незащищенного, проекта в его простоте. А защита будет делаться наличием множества неопубликованных серверов( с неизвестными для широкой публики IP и портами ) и секретным кодом внутри их.

Старшина
08.05.2020, 10:07
Василий спасибо программу работает на все 100%. Анатолий спасибо за программу работает пока на 90% под андроидом 4.1.2 вылетает программа при попытке вкл. на передачу.
С праздником с Днём Победы!!! Здоровья,Удачи и Успехов во всём.

RN6LIQ
12.05.2020, 09:21
Для более правильного подключения к интернету добавлено несколько строк где указан шлюз ( ваш роутер ), маска подсети и DNS-сервер. Исходный код ниже


#include "SPI.h"
#include "Ethernet.h"
#include "EthernetUdp.h"

int pinIn = A0; // АЦП
//ДОБАВЛЯЕМ ПАРАФАЗНЫЕ ВЫХОДЫ ЦАПА
int pinOutP = 9; // ШИМ +
//int pinOutM = 10; // ШИМ -
int pinTest = 2; // ТЕСТ ПРЕРЫВАНИЯ 8 кГц
int pinStart = 8; // Для начала передачи на этот пин надо подать землю
int pinCall = 7; // если поступил вызов на этом пине какое то время будет переменный сигнал 1000 ГЦ
int pinSendCall = 6; // Для вызова на этот пин надо подать землю
int pinOnVox = 5; // Для включения VOX на этот пин надо подать землю
int pinGoPlay = 4; // Для включения передатчика
byte mac[] = {0xDE, 0xAD, 0xEE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,0,84);
IPAddress ipout(194,63,141,124);
IPAddress myDns(192, 168, 0, 1);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
unsigned int localPort = 8984;
unsigned int localPortout = 16000;
EthernetUDP Udp;

// Непосредственно для работы с сервером нужны
byte kanal_PRD; // номер канала 0 - 255
uint16_t kanal_Secret; // и секретный код 0 - 65536
// но в PMR проекте необходим
byte PChannel = 2; // номер канала 0 - 8
uint32_t MailIndex = 1; // и индекс 0 - 999999



void setup()
{
// put your setup code here, to run once:
pinMode(pinIn,INPUT); // АЦП
// В этом примере уже убираю работу с последовательным портом, поскольку хронически не хватет памяти
// put your setup code here, to run once:
//Ethernet.begin(mac,ip);
Ethernet.begin(mac, ip, myDns, gateway, subnet);
Udp.begin(localPort);

pinMode(pinOutP,OUTPUT); //ВЫХОД НА НАУШНИК ПЛЮСОВОЙ
//pinMode(pinOutM,OUTPUT); //ВЫХОД НА НАУШНИК МИНУСОВОЙ, тут я изменил настройки Владимира (RZ6AT) поскольку у меня немного другая схема вывода звука
pinMode(pinTest,OUTPUT);
pinMode(pinCall,OUTPUT);
pinMode(pinStart,INPUT);
digitalWrite(pinStart, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinSendCall,INPUT);
digitalWrite(pinSendCall, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinOnVox,INPUT);
digitalWrite(pinOnVox, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinGoPlay,OUTPUT);



//ДОБАВЛЯЕМ АЦП
ADCSRA = 0x87; // ВКЛЮЧАЕМ АЦП, ДЕЛИМ НА 128
ADCSRB = 0x00;
ADMUX = 0x60; // СДВИГАЕМ РЕЗУЛЬТАТ ВЛЕВО, REF=5V, A0 ЧИТАЕМ

// ТАЙМЕР1 ДЛЯ ШИМА
// TCCR1A = 0xB1; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB // тут изменил, потому что другая у меня схема вывода звука
TCCR1A = 0x81; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB
TCCR1B = 0x09; // PWM PHASE CORRECT 8 BIT, PRESCALER=1, CLOCK=16MHZ
TCCR1C = 0x80; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB

TCCR2A = 0x02; // ПРЕСКАЛЕР=8
TCCR2B = 0x02; // РЕЖИМ СТС
TIMSK2 = 0x02; // ПРЕРЫВАНИЯ ОТ КОМПАРАТОРА А ТАЙМЕРА 2
OCR2A = 249; // ДЕЛИМ НА 250
sei();
// Преобразуем настройки из формата PMR в формат сервера
if(PChannel == 0) kanal_PRD = 0;
else kanal_PRD = (byte)(((MailIndex & 0xF) * 8) + PChannel);
kanal_Secret = (uint16_t)((MailIndex & 0xFFFFFFF0) >> 4); // секретное число 0

digitalWrite(pinGoPlay, LOW);

}
volatile uint16_t ticTest = 0; // обслуживает посылку тестовых посылок и перезапуск при зависании
char packetBuffer[164]; // приемный буфер
// кольцевой буфер с указателями записи и чтения для работы с АЦП
volatile uint16_t Save0;
volatile uint16_t Load0;
volatile byte buf0[200];
// кольцевой буфер с указателями записи и чтения для ЦАП реализованного на ШИМ
volatile uint16_t Save1;
volatile uint16_t Load1;
volatile byte buf1[640];

volatile uint32_t kolrecv = 0; // хранит количество байт в очереди на воспроизведение

volatile uint16_t play = 0; // индикатор воспроизведения, нужен для корректного вывода звука в прерывании
volatile byte GoPlay = 0; // если истинен, то значит идет прием звука

volatile byte Start = 0; // если истинно (не ноль) звук перелается в сеть
// передающий буфер с указателем
int kol = 4;
byte buf[164];

volatile uint32_t tic = 0; // обслуживает сброс переменных если больше секунды не было приема звука

volatile boolean actionState = LOW; // обслуживает индикацию приема вызова, 1000 ГЦ
volatile uint16_t call = 0;
volatile uint8_t call_50 = 0;

uint8_t b_reg; // в прерывании сюда заносится состояние региста PINB
uint8_t d_reg; // в прерывании сюда заносится состояние региста PIND

uint8_t SendCall = 0; // При переходе с нуля в еденицу посылаем вызов
uint8_t StartVox = 0; // Если истинно, то работает режим VOX


volatile int16_t Kto = -1; // хранит IP принимаемого пользователя, значение от 0 и выше, если -1 то никого не принимаем


void loop() {


if(kolrecv < 480) // проверяем, что бы было место под воспроизведение звука, в сязи с катастрофической нехваткой памяти на Ардуино
{ // приходится с Ethernet модуля забирать данные только тогда, когда есть куда их разместить. Таким образом W5100 помогает избавится от рывков звука
int packetSize = Udp.parsePacket(); // проверяем есть ли данные на приеме
if(packetSize) // если есть
{
if(packetSize > 164) packetSize = 164; // в данном режиме нам не нужны пакеты размером более 164 байта

Udp.read(packetBuffer,packetSize); // читаем их
if(packetSize == 4) // обрабатываем служебные пакеты, они всегда имеют размер 4 байта
{
if(packetBuffer[0] == 110) // пакет с количеством соединений в канале, тут на ардуинке это некуда притулить, поскольку нет экрана индикации
{
//uint16_t count;
//memcpy(&count,&packetBuffer[2],sizeof(count));
//Serial.print("Count \t");
//Serial.println(count,DEC);
}
}
else // остальные, не служебные пакеты
{
switch (packetBuffer[0]) // в первом байте приемного буфера помещен тип пакета
{
case 20: // пришел сигнал вызова
call = 1;
digitalWrite(pinCall, HIGH);
break;

case 27: // пришел звуковой пакет
{
int16_t kto,i;
memcpy(&kto,&packetBuffer[2],sizeof(kto)); // узнаем ID пользователя кто его прислал
if(Kto == -1) // если до этого никто не от кого не принимали, то
{
Kto = kto; // начинаем принимать этого пользователя
}
else
{
if(Kto != kto) break; // если уже кого то принимаем, но пакет пришел не от того пользователя, то игнорируем
}
tic = 0; // сбрасывется счетчик индикации приема звука
for(i = 4; i < 164; i++) // заносим принятые данные в кольцевой буфер
{
buf1[Save1] = packetBuffer[i] + 128;
if(Save1 < 639) Save1++;
else Save1 = 0;
}
kolrecv = kolrecv + 160;
}
break;
default:
{
};
}
}
}
}

if(tic > 8000) // нет приема звука уже секунду,
{
tic = 0;
kolrecv = 0;
Kto = -1;
}

if(play)
{
if(GoPlay == 0)
{
GoPlay = 1;
digitalWrite(pinGoPlay, HIGH);
}
}
else
{
if(GoPlay)
{
GoPlay = 0;
digitalWrite(pinGoPlay, LOW);
}
}



if(!(d_reg & 0x40)) //
{
if(SendCall == 0)
{
SendCall = 1;
buf[0] = 20; // тип пакета вызова
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}
}
else
{
SendCall = 0;
}

if(!(d_reg & 0x20)) //
{
StartVox = 1; // Режим VOX включен
}
else
{
StartVox = 0; // Режим VOX выключен
}


if(StartVox == 0)
{
if(!(b_reg & 0x01)) // в этом проекте нет кнопки вызова, вместо этого есть алгоритм поднятия телефонной трубки, если трубка была поднята
{
if(call) // но мы синалим внешний вызов
{ // то прекращаем это делать
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}

Start = 1; // Начинаем передачу
}
else // земля на 8 ножке пропала ( положили трубку )
{ //
Start = 0; // выключаем передачу
}
}


if(ticTest > 8000) // если прошла секунда
{
ticTest = 0; // счетчик сбрасываем
buf[0] = 7; // тип пакета таймера
buf[1] = 0;
memcpy(&buf[2],&kanal_Secret,2); // значение секретного кода, на основании этого кода сервер будет коммутировать нам нужные пакеты
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}



while(Load0 != Save0) // Забираем данные с АЦП
{
buf[kol] = buf0[Load0];
kol++;
if(kol >= 164)
{
if(Start) // если разрешена передача, передаем звук
{
buf[0] = 27; // режим 8000 раз в секунду 8 бит
Udp.beginPacket(ipout,localPortout+kanal_PRD);
Udp.write((byte *)buf,164); // передача 160 байт данных с АЦП вместе с 4 байтами служебного заголовка
Udp.endPacket();
}
kol = 4; // указатель сбрасываем (первых 4 байта это служебный заголовок)
}

if(Load0 < 199) Load0++;
else Load0 = 0;
}


if(call) // обслуживаем прием вызова
{
if(call > 24000) // прошло 4 секунды с момента звучания, значит выключаем
{
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}
else // звучит сигнал вызова
{
// if(call_50 > 159) // 50 Hz, на моем DECT телефоне куда я подключал данную плату надо на определенную ножку микросхемы подать 50 гц, тогда в телефоне звучит звонок
if(call_50 > 7) // 1000 Hz, но можно поросто подать 1000 герц на любую пищалку, в тихой комнате ее хорошо слышно.
{
call_50 = 0;
if(actionState)
{
actionState = 0;
}
else
{
actionState = 1;
}
digitalWrite(pinCall, actionState); // сообственно на ножке меняем постоянно TTL уровень
}
}
}

}

volatile uint16_t ticVox = 0; //
volatile byte oldVox = 0; //


void(* resetFunc) (void) = 0; // объявляем функцию reset
// функция прерывания
ISR(TIMER2_COMPA_vect)
{
b_reg = PINB; // Считываем порт, узнаем какие ножки в каком состоянии, за одно считывание сразу 8 ножек, правильное решение для прерывания в котором нельзя долго задерживаться
d_reg = PIND; //



PORTD |= (1<<pinTest); // СМОТРИМ НА ВЫВОДЕ D2 ПЕРИОД ПРЕРЫВАНИЙ 8 КГц
//ДОБАВЛЯЕМ
byte v = ADCH; // ЧИТАЕМ СТАРШИЙ БАЙТ ИЗ АЦП
int del;
if(StartVox)
{
if(oldVox > v) del = oldVox - v; // Измеряем изменения уровня на входе АЦП относитель прошлого отсчета
else del = v - oldVox; //
}
v = v - 128; // обязательно делаем число со знаком, звуковые карты другие значения не понимают
buf0[Save0] = v; // заносим значения АЦП в кольцевой буфер
if(Save0 < 199) Save0++;
else Save0 = 0;

if(play == 0) // нет было приема звука до этого
{
if(kolrecv > 320) play = 1; // если в теле loop приняты уже три звуковых пакета, то начинаем воспроизведение. Упреждение необходимо, что бы избавится от рывков звука
}
else // воспроизведение включено
{
if(Load1 != Save1) // есть звук для воспроизведения, отправляем его в ЦАП ( ШИМ )
{
v = buf1[Load1];
OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1
if(Load1 < 639) Load1++;
else Load1 = 0;
if(kolrecv) kolrecv--; // отмечаем уменьшение очереди байт на воспроизведение
play = 1; // можно конечно не делать этого, но на всякий случай сбрасываю счетчик еще раз
}
else // нет звука
{
if(play) // если до этого было воспроизведение
{
play++; // наращиваем счетчик
if(play > 500) // если прошло времени с момента прошлого пакета больше 500 тиков, то считаем, что связь разорвана
{
play = 0;
Kto = -1;
kolrecv = 0;
}
}
}
}
ticTest++;
tic++;

// если программа подвисла, то
if(ticTest > 13000) resetFunc(); //вызываем reset


if(call) // обслуживание звучания зуммера
{
call++;
call_50++;
}

if(StartVox)
{
if(del > 10) // если уровень на входе изменяеться больше определенного значения (подбиратся под себя)
{
ticVox = 1; // сбрасывем счетчик VOX в еденицу
if(Start == 0) Start = 1; // если до этого не было признака передачи, то включаем его
}
if(ticVox) // пока счетчик Vox истинен
{
ticVox++; // наращиваем его
if(ticVox > 8000) // если уже больше секунды не было на входе АЦП изменений сигнала ( а следовательно ticVox не сбрасывался в 1 )
{
ticVox = 0; // выключаем счетчик, теперь он не будет наращиваться
Start = 0; // выключаем признак передачи
}
}
}

// Тут Владимир проверял на себя АЦП на ЦАП
// OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
// OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1

ADCSRA |= (1<<ADSC); // ЗАПУСКАЕМ АЦП
PORTD &= ~(1<<pinTest); // СБРАСЫВАЕМ ТЕСТОВЫЙ СИГНАЛ
}


Вчера попробовал этот код без изменений залить в Arduino Nano, за Ethernet Shield работал W5500. Все прекрасно работает, при этом размеры конструкции меньше.

Все по той же ССЫЛКЕ (http://188.168.58.111:8080/GAME/app-release.apk) выложена новая версия программы под Андроид. Добавлено 5 кнопок памяти, очень удобно сохраняются настройки , в том числе для разных серверов ( пригодится в дальнейшем ). Для того что бы сохранить, надо нажать кнопку и удерживать. Если кликнуть по кнопке один раз, то вызываются сохраненные настройки.

Для версии программы под Windows есть возможность менять режимы текстовыми файлами, которые необходимо расположить в рабочем каталоге программы. Файл ip.txt позволяет после старта программы подключаться по указанному адресу. В файле в первой строке адрес указывается так, например:
192.168.0.5:16000
Обязательно надо нажать Enter в конце строки. Файл vox.txt включает VOX. Пример:
5
1000
5 - уровень при котором срабатывает передача ( диапазон до 127 ), 1000 - количество миллисекунд после которых передача выключится, если на входе не будет достаточного уровня. Windows версия умеет принимать все заложенные в проект режимы качества звука, но для того что бы выставить нужный режим передачи необходимо создать в рабочем каталоге программы файл root.txt с содержимым:
1
0,1 - 16000 G711 - 128 Kbit/s
2 - 16000 16 bit - 256 Kbit/s
3 - 16000 8 bit - 128 Kbit/s
4 - GSM - 32 Kbit/s ( должно быть 13.2 Kbit/s, но реально заголовки пакетов UDP увеличивают трафик )
5 - 8000 16 bit - 128 Kbit/s
6 - 8000 G711 - 64 Kbit/s
7 - 8000 8 bit - 64 Kbit/s

Первая строка определяет режим передачи, остальные строки служат подсказкой.
Программа делалась с расчетом на неподготовленных пользователей, которых нельзя было пугать множеством настроек, поэтому для подготовленных пользователей была реализована вот такая немного за умудренная система. Есть также файлы tx.txt, rx.txt и rxfortx.txt в них можно прописать соответствующие уровни числами с плавающей запятой (на самом деле вместо запятой надо в файле прописывать точку). rxfortx.txt работает только тогда, когда в программе установлен симплекс. На всякий случай КАЧАЕМ актуальную версию все по той же ССЫЛКЕ (http://188.168.58.111:8080/READ/PMR.ZIP).

Таким образом версии программ которые мы вам выложили позволяют создавать свои каналы удаленного управления радио станциями и не только ими. Это может быть оперативная связь по принципу - один сказал, - все услышали. Это может быть индивидуальный телефон подключенный через Arduino к интернету на который всегда можно позвонить через интернет с мобильного устройства. Когда закончится тестирование нынешнего сервера и нами будут выложены сервера, то такая связь станет еще более независимой от авторов данного проекта.

UA0YAS
12.05.2020, 09:24
эх, еще бы CAT пробросить......:tmi:

RN6LIQ
12.05.2020, 10:26
На Arduino можно CAT самому сочинить, тем более там уже показано какие пины можно задействовать. Пин для начала передачи есть, пин где появляется уровень когда что то приходит на прием тоже есть. Осталось согласовать с конкретной радиостанцией и вперед. Правда качество звука еще низкое. Более сложное управление с перестройкой частоты и режимов... Но это уже совершенно другая тема и программы совершенно другого уровня. Мы тут за то, что бы все было как можно проще.
А на Windows работает VOX, если и на радиостанции он есть, то можно обойтись и этим. На Linux попробую в обозримом будущем какой либо пример на RaspberryPI сделать. Он хоть дороже микроконтроллера, но дешевле персонального компа, тем более можно найти дешевые платы с Китая типа OrangePI. Только придется применять USB звуковые карты. Как правило входа звука на этих микрокомпьютерах чаще всего нет. Или выход звука пускай свой будет, а вход сделать на микроконтроллере, том же Arduino или STM32F103.

Старшина
14.05.2020, 12:23
12.05.2020 Выложена новая версия программы под Андроид. Все ровно Анатолий при попытки перехода на передачу или нажатии на низ экрана программа вылетает...????
На дисплеи пишет (В приложении "Виртуальная рация" произошла ошибка) ??? Вот пока почему-то так. А во остальном все нормально (прием и прочее все работает)

Refraktor
14.05.2020, 13:20
Всем добрый день!
Вчера заметили еще одну проблему в андроидной версии. У двух станций с разным битрейтом были проблемы. У первой стоял дефолтный, на второй пониженый. Та станция у которой был дефолтный битрейт вторую не слышала. В обратную сторону все было нормально. При смене битрейта связь востановилась.

RN6LIQ
14.05.2020, 14:43
Та станция у которой был дефолтный битрейт вторую не слышала.

Тут есть один нюанс :s9: Андроидная версия может работать только в одном из двух режимов частот дискретизации, или 8000 или 16000. Мои программы под Windows могут по всякому работать, что Шарманка, что PMR-ка, но все это за счет математики. В той же PMR-ке из базовой частоты 16000 я делаю частоту 8000 методом децимации, то есть методом прореживания. Но если это делать без предварительной цифровой фильтрации, то звук приобретает металлический оттенок, то есть там есть не нужные помехи. Перенести Сишные библиотеки в Андроидную Javu не так то просто. Поэтому Анатолий сделал проще, на прием у него автоматически переключается или 16000 или 8000, и дальше внутри этой частоты дискретизации можно слышать 8 бит, 16 бит и G711, но только именно для этой частоты дискретизации. Поэтому между Андроидными версиями надо всем корреспондентам ставить один режим. А для того что бы связываться с микроконтроллером Ардуино есть один единственный режим, - 8 бит, 8000. Кстати выкладываю последнюю версию кода, которую мы с Владимиром причесали



#include "SPI.h"
#include "Ethernet.h"
#include "EthernetUdp.h"

int pinIn = A0; // АЦП
//ДОБАВЛЯЕМ ПАРАФАЗНЫЕ ВЫХОДЫ ЦАПА
int pinOutP = 9; // ШИМ +
//int pinOutM = 10; // ШИМ -
int pinTest = 2; // ТЕСТ ПРЕРЫВАНИЯ 8 кГц
int pinStart = 8; // Для начала передачи на этот пин надо подать землю
int pinCall = 7; // если поступил вызов на этом пине какое то время будет переменный сигнал 1000 ГЦ
int pinSendCall = 6; // Для вызова на этот пин надо подать землю
int pinOnVox = 5; // Для включения VOX на этот пин надо подать землю
int pinGoPlay = 4; // Для включения передатчика
int pinGoStart = 3; // Идет передача
byte mac[] = {0xDE, 0xAD, 0xEE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,0,84);
IPAddress ipout(194,63,141,124);
IPAddress myDns(192, 168, 0, 1);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
unsigned int localPort = 8984;
unsigned int localPortout = 16000;
EthernetUDP Udp;

// Непосредственно для работы с сервером нужны
byte kanal_PRD; // номер канала 0 - 255
uint16_t kanal_Secret; // и секретный код 0 - 65536
// но в PMR проекте необходим
byte PChannel = 2; // номер канала 0 - 8
uint32_t MailIndex = 1; // и индекс 0 - 999999



void setup()
{
// put your setup code here, to run once:
pinMode(pinIn,INPUT); // АЦП
// В этом примере уже убираю работу с последовательным портом, поскольку хронически не хватет памяти
// put your setup code here, to run once:
//Ethernet.begin(mac,ip);
Ethernet.begin(mac, ip, myDns, gateway, subnet);
Udp.begin(localPort);

pinMode(pinOutP,OUTPUT); //ВЫХОД НА НАУШНИК ПЛЮСОВОЙ
//pinMode(pinOutM,OUTPUT); //ВЫХОД НА НАУШНИК МИНУСОВОЙ, тут я изменил настройки Владимира (RZ6AT) поскольку у меня немного другая схема вывода звука
pinMode(pinTest,OUTPUT);
pinMode(pinCall,OUTPUT);
pinMode(pinStart,INPUT);
digitalWrite(pinStart, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinSendCall,INPUT);
digitalWrite(pinSendCall, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinOnVox,INPUT);
digitalWrite(pinOnVox, 1); // поджимаем внутренним резистром ножку, что бы не бвло ложного срабатывания
pinMode(pinGoPlay,OUTPUT);
pinMode(pinGoStart,OUTPUT);



//ДОБАВЛЯЕМ АЦП
ADCSRA = 0x87; // ВКЛЮЧАЕМ АЦП, ДЕЛИМ НА 128
ADCSRB = 0x00;
ADMUX = 0x60; // СДВИГАЕМ РЕЗУЛЬТАТ ВЛЕВО, REF=5V, A0 ЧИТАЕМ

// ТАЙМЕР1 ДЛЯ ШИМА
// TCCR1A = 0xB1; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB // тут изменил, потому что другая у меня схема вывода звука
TCCR1A = 0x81; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB
TCCR1B = 0x09; // PWM PHASE CORRECT 8 BIT, PRESCALER=1, CLOCK=16MHZ
TCCR1C = 0x80; // ДЁРГАЕМ ПИНЫ ПО СОМРА & COMPB

TCCR2A = 0x02; // ПРЕСКАЛЕР=8
TCCR2B = 0x02; // РЕЖИМ СТС
TIMSK2 = 0x02; // ПРЕРЫВАНИЯ ОТ КОМПАРАТОРА А ТАЙМЕРА 2
OCR2A = 249; // ДЕЛИМ НА 250
sei();
// Преобразуем настройки из формата PMR в формат сервера
if(PChannel == 0) kanal_PRD = 0;
else kanal_PRD = (byte)(((MailIndex & 0xF) * 8) + PChannel);
kanal_Secret = (uint16_t)((MailIndex & 0xFFFFFFF0) >> 4); // секретное число 0

digitalWrite(pinGoPlay, LOW);
digitalWrite(pinGoStart, LOW);

}
volatile uint16_t ticTest = 0; // обслуживает посылку тестовых посылок и перезапуск при зависании
char packetBuffer[164]; // приемный буфер
// кольцевой буфер с указателями записи и чтения для работы с АЦП
volatile uint16_t Save0;
volatile uint16_t Load0;
volatile byte buf0[200];
// кольцевой буфер с указателями записи и чтения для ЦАП реализованного на ШИМ
volatile uint16_t Save1;
volatile uint16_t Load1;
volatile byte buf1[640];

volatile uint32_t kolrecv = 0; // хранит количество байт в очереди на воспроизведение

volatile uint16_t play = 0; // индикатор воспроизведения, нужен для корректного вывода звука в прерывании
volatile byte GoPlay = 0; // если истинен, то значит идет прием звука

volatile byte Start = 0; // если истинно (не ноль) звук перелается в сеть
volatile byte GoStart = 0; // если истинно (не ноль) звук перелается в сеть
// передающий буфер с указателем
int kol = 4;
byte buf[164];

volatile uint32_t tic = 0; // обслуживает сброс переменных если больше секунды не было приема звука

volatile boolean actionState = LOW; // обслуживает индикацию приема вызова, 1000 ГЦ
volatile uint16_t PrdCall = 0;
volatile uint16_t call = 0;
volatile uint8_t call_50 = 0;

uint8_t b_reg; // в прерывании сюда заносится состояние региста PINB
uint8_t d_reg; // в прерывании сюда заносится состояние региста PIND

uint8_t SendCall = 0; // При переходе с нуля в еденицу посылаем вызов
uint8_t StartVox = 0; // Если истинно, то работает режим VOX


volatile int16_t Kto = -1; // хранит IP принимаемого пользователя, значение от 0 и выше, если -1 то никого не принимаем


void loop() {


if(kolrecv < 480) // проверяем, что бы было место под воспроизведение звука, в сязи с катастрофической нехваткой памяти на Ардуино
{ // приходится с Ethernet модуля забирать данные только тогда, когда есть куда их разместить. Таким образом W5100 помогает избавится от рывков звука
int packetSize = Udp.parsePacket(); // проверяем есть ли данные на приеме
if(packetSize) // если есть
{
if(packetSize > 164) packetSize = 164; // в данном режиме нам не нужны пакеты размером более 164 байта

Udp.read(packetBuffer,packetSize); // читаем их
if(packetSize == 4) // обрабатываем служебные пакеты, они всегда имеют размер 4 байта
{
if(packetBuffer[0] == 110) // пакет с количеством соединений в канале, тут на ардуинке это некуда притулить, поскольку нет экрана индикации
{
//uint16_t count;
//memcpy(&count,&packetBuffer[2],sizeof(count));
//Serial.print("Count \t");
//Serial.println(count,DEC);
}
}
else // остальные, не служебные пакеты
{
switch (packetBuffer[0]) // в первом байте приемного буфера помещен тип пакета
{
case 20: // пришел сигнал вызова
call = 1;
digitalWrite(pinCall, HIGH);
break;

case 27: // пришел звуковой пакет
{
int16_t kto,i;
memcpy(&kto,&packetBuffer[2],sizeof(kto)); // узнаем ID пользователя кто его прислал
if(Kto == -1) // если до этого никто не от кого не принимали, то
{
Kto = kto; // начинаем принимать этого пользователя
}
else
{
if(Kto != kto) break; // если уже кого то принимаем, но пакет пришел не от того пользователя, то игнорируем
}
tic = 0; // сбрасывется счетчик индикации приема звука
for(i = 4; i < 164; i++) // заносим принятые данные в кольцевой буфер
{
buf1[Save1] = packetBuffer[i] + 128;
if(Save1 < 639) Save1++;
else Save1 = 0;
}
kolrecv = kolrecv + 160;
}
break;
default:
{
};
}
}
}
}

if(tic > 8000) // нет приема звука уже секунду,
{
tic = 0;
kolrecv = 0;
Kto = -1;
}

if(Start)
{
if(GoStart == 0)
{
GoStart = 1;
digitalWrite(pinGoStart, HIGH);
}
}
else
{
if(GoStart)
{
GoStart = 0;
digitalWrite(pinGoStart, LOW);
}
}

if(PrdCall)
{
if(GoStart == 0)
{
GoStart = 1;
digitalWrite(pinGoStart, HIGH);
}
}
else
{
if(GoStart)
{
GoStart = 0;
digitalWrite(pinGoStart, LOW);
}
}

if(play)
{
if(GoPlay == 0)
{
GoPlay = 1;
digitalWrite(pinGoPlay, HIGH);
}
}
else
{
if(GoPlay)
{
GoPlay = 0;
digitalWrite(pinGoPlay, LOW);
}
}



if(!(d_reg & 0x40)) //
{
if(SendCall == 0)
{
SendCall = 1;
buf[0] = 20; // тип пакета вызова
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
sprintf(&buf[4],"BELL");
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,24); // непосредвственная передача
Udp.endPacket(); //
call = 6000;
PrdCall = 6000;
digitalWrite(pinCall, HIGH);
}
}
else
{
SendCall = 0;
}

if(!(d_reg & 0x20)) //
{
StartVox = 1; // Режим VOX включен
}
else
{
StartVox = 0; // Режим VOX выключен
}


if(StartVox == 0)
{
if(!(b_reg & 0x01)) // в этом проекте нет кнопки вызова, вместо этого есть алгоритм поднятия телефонной трубки, если трубка была поднята
{
if(call) // но мы синалим внешний вызов
{ // то прекращаем это делать
call = 0;
call_50 = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}

Start = 1; // Начинаем передачу
}
else // земля на 8 ножке пропала ( положили трубку )
{ //
Start = 0; // выключаем передачу
}
}


if(ticTest > 8000) // если прошла секунда
{
ticTest = 0; // счетчик сбрасываем
buf[0] = 7; // тип пакета таймера
buf[1] = 0;
memcpy(&buf[2],&kanal_Secret,2); // значение секретного кода, на основании этого кода сервер будет коммутировать нам нужные пакеты
Udp.beginPacket(ipout,localPortout+kanal_PRD); //
Udp.write(buf,4); // непосредвственная передача
Udp.endPacket(); //
}



while(Load0 != Save0) // Забираем данные с АЦП
{
buf[kol] = buf0[Load0];
kol++;
if(kol >= 164)
{
if(Start) // если разрешена передача, передаем звук
{
buf[0] = 27; // режим 8000 раз в секунду 8 бит
Udp.beginPacket(ipout,localPortout+kanal_PRD);
Udp.write((byte *)buf,164); // передача 160 байт данных с АЦП вместе с 4 байтами служебного заголовка
Udp.endPacket();
}
kol = 4; // указатель сбрасываем (первых 4 байта это служебный заголовок)
}

if(Load0 < 199) Load0++;
else Load0 = 0;
}


if(call) // обслуживаем прием вызова
{
if(call > 24000) // прошло 4 секунды с момента звучания, значит выключаем
{
call = 0;
call_50 = 0;
PrdCall = 0;
actionState = LOW;
digitalWrite(pinCall, LOW);
}
else // звучит сигнал вызова
{
// if(call_50 > 159) // 50 Hz, на моем DECT телефоне куда я подключал данную плату надо на определенную ножку микросхемы подать 50 гц, тогда в телефоне звучит звонок
if(call_50 > 7) // 1000 Hz, но можно поросто подать 1000 герц на любую пищалку, в тихой комнате ее хорошо слышно.
{
call_50 = 0;
if(actionState)
{
actionState = 0;
}
else
{
actionState = 1;
}
digitalWrite(pinCall, actionState); // сообственно на ножке меняем постоянно TTL уровень
}
}
}

}

volatile uint16_t ticVox = 0; //
volatile byte oldVox = 0; //


void(* resetFunc) (void) = 0; // объявляем функцию reset
// функция прерывания
ISR(TIMER2_COMPA_vect)
{
b_reg = PINB; // Считываем порт, узнаем какие ножки в каком состоянии, за одно считывание сразу 8 ножек, правильное решение для прерывания в котором нельзя долго задерживаться
d_reg = PIND; //



PORTD |= (1<<pinTest); // СМОТРИМ НА ВЫВОДЕ D2 ПЕРИОД ПРЕРЫВАНИЙ 8 КГц
//ДОБАВЛЯЕМ
byte v = ADCH; // ЧИТАЕМ СТАРШИЙ БАЙТ ИЗ АЦП
int del;
if(StartVox)
{
if(oldVox > v) del = oldVox - v; // Измеряем изменения уровня на входе АЦП относитель прошлого отсчета
else del = v - oldVox; //
}
v = v - 128; // обязательно делаем число со знаком, звуковые карты другие значения не понимают
buf0[Save0] = v; // заносим значения АЦП в кольцевой буфер
if(Save0 < 199) Save0++;
else Save0 = 0;

if(play == 0) // нет было приема звука до этого
{
if(kolrecv > 320) play = 1; // если в теле loop приняты уже три звуковых пакета, то начинаем воспроизведение. Упреждение необходимо, что бы избавится от рывков звука
}
else // воспроизведение включено
{
if(Load1 != Save1) // есть звук для воспроизведения, отправляем его в ЦАП ( ШИМ )
{
v = buf1[Load1];
OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1
if(Load1 < 639) Load1++;
else Load1 = 0;
if(kolrecv) kolrecv--; // отмечаем уменьшение очереди байт на воспроизведение
play = 1; // можно конечно не делать этого, но на всякий случай сбрасываю счетчик еще раз
}
else // нет звука
{
if(play) // если до этого было воспроизведение
{
play++; // наращиваем счетчик
if(play > 500) // если прошло времени с момента прошлого пакета больше 500 тиков, то считаем, что связь разорвана
{
play = 0;
Kto = -1;
kolrecv = 0;
}
}
}
}
ticTest++;
tic++;

// если программа подвисла, то
if(ticTest > 13000) resetFunc(); //вызываем reset

if(PrdCall) PrdCall++;

if(call) // обслуживание звучания зуммера
{
call++;
call_50++;
}

if(StartVox)
{
if(del > 10) // если уровень на входе изменяеться больше определенного значения (подбирается под себя)
{
ticVox = 1; // сбрасывем счетчик VOX в еденицу
if(Start == 0) Start = 1; // если до этого не было признака передачи, то включаем его
}
if(ticVox) // пока счетчик Vox истинен
{
ticVox++; // наращиваем его
if(ticVox > 8000) // если уже больше секунды не было на входе АЦП изменений сигнала ( а следовательно ticVox не сбрасывался в 1 )
{
ticVox = 0; // выключаем счетчик, теперь он не будет наращиваться
Start = 0; // выключаем признак передачи
}
}
}

// Тут Владимир проверял на себя АЦП на ЦАП
// OCR1A = v; // КИДАЕМ В КОМПАРАТОР А ТАЙМЕРА1
// OCR1B = v; // КИДАЕМ В КОМПАРАТОР В ТАЙМЕРА1

ADCSRA |= (1<<ADSC); // ЗАПУСКАЕМ АЦП
PORTD &= ~(1<<pinTest); // СБРАСЫВАЕМ ТЕСТОВЫЙ СИГНАЛ
}

Там где строка if(del > 10) // если уровень на входе изменяется больше определенного значения (подбирается под себя)
число 10 можно менять до максимум 127. Это настраивается чувствительность VOX. Если конечно VOX включен. Сейчас Владимир работает над принципиальной схемой, над АЧХ, усилением, кнопками и т.д.

ПРАПОР ОМСК СССР
16.05.2020, 18:04
Добрый день. Вот что происходит с мобильной версией PMR, смотри видео подробнее - https://ok.ru/video/1850859129433

Refraktor
16.05.2020, 19:10
Вот что происходит с мобильной версией PMR
Доброго времени суток. У меня аналогичная проблема с PMR-кой один в один. Система 8.1. Предыдущая версия, там где две дополнительные кнопки, работала на вылет аналогично. В старой версии все было нормально.

Пы.Сы. С пополнением! :) :p-up:

RN6LIQ
17.05.2020, 16:40
Ребята, качаем новую Андроидную версию (http://188.168.58.111:8080/GAME/app-release.apk), Анатолий устранил ошибку на которую было указано выше. Также прошу прощение за необъективный комментарий по поводу поста 109, у Анатолия должно все работать в данном случае. Я не совсем понял как все таки работает программа и неверно прокомментировал. Возможно то что описано в посте 109 имеет другие причины.

Refraktor
17.05.2020, 17:09
Ребята, качаем новую Андроидную версию, Анатолий устранил ошибку на которую было указано выше.
Доброго вечера Василий!
Скачал, установил, вроде теперь нормально. Кнопки заработали все нормально. Переходит по каналам на ура, так же отлично сохраняет указанные параметры. Наблюдается только вот это что на картинках. В старой версии изображение было так же.

261868 261869

Старшина
17.05.2020, 19:23
Все равно Анатолий при попытки перехода на передачу или нажатии на низ экрана программа вылетает,приходиться запускать снова.
На дисплеи пишет (В приложении "Виртуальная рация" произошла ошибка), версия андроида 4.1.2. Все другие функции работают отлично.

RN6LIQ
18.05.2020, 16:09
Анатолий подправил прокрутку экрана, ссылка ВСЁ ТА ЖЕ (http://188.168.58.111:8080/GAME/app-release.apk).

Refraktor
18.05.2020, 16:30
Анатолий подправил прокрутку экрана
Приветствую!
Во вкладке "Menu" сейчас все замечательно. Кнопки на панеле заработали все. Вроде все работает теперь нормально. Система 8.1 Остался вот этот косяк с наездом кнопок на динамик, хотя в промежутках между ними можно включить передачу.

261970

RN6LIQ
19.05.2020, 15:05
Нашли с Владимиром ошибку в моей версии под Windows, которая приводила к искажению сигнала при частоте дискретизации 8000. Новую версию качать все по той же ссылке (http://188.168.58.111:8080/READ/PMR.ZIP).

RN6LIQ
19.05.2020, 16:08
Вот так выглядит звук на Arduino Uno + W5100, Владимир еще работает над схемой, но я также экспериментирую на макетной плате

Видео (http://188.168.58.111:8080/GAME/ArduinoNano.html)

RN6LIQ
21.05.2020, 10:34
Не пойму, почему удален мой предыдущий пост про Arduino IDE... Вроде бы ничего запретного не писал. Название ветки почему то изменено без моего согласия. Несколько лет сюда не заходил, но вижу что на qrz.ru порядки за это время не поменялись.

Старшина
22.05.2020, 09:51
Анатолий подправил прокрутку экрана, ссылка ВСЁ ТА ЖЕ (http://188.168.58.111:8080/GAME/app-release.apk).

Все таки на передачу(TX) программа так и не хочет работать...вылетает на андроиде 4.1.2.

Старшина
22.05.2020, 10:05
Анатолий все таки на передачу (TX) программа так и не работает...вылетает на андроиде 4.1.2.

Refraktor
22.05.2020, 10:25
на передачу (TX) программа так и не работает...вылетает на андроиде 4.1.2
Вчера ради интереса попробовал на системе 4.4.2, аналогичная ситуация и кнопки съехали на динамик. Из-за этого нет возможности перейти на передачу. При нажатии на область ниже кнопок приложение закрывается с ошибкой. Остальное вроде бы все работает. На системе 8.1 кроме съехавшего дизайна пмрки проблем пока не наблюдалось.

RN6LIQ
23.05.2020, 12:47
Владимир(RZ6AT) подготовил схему подключения, публикуем
262639

Есть такой хороший чип ESP8266-01, но по сравнению с другими версиями у него очень мало GPIO. Купил, поигрался, а потом не знал куда его прикрутить. По сравнение с Arduino он очень мощный, но годится только для того что бы другой микроконтроллер работал с ним через AT команды. Попробовал скрестить его с Arduino Nano но питание 3,3 вольта у Nano очень слабое, для ESP не хватает, а возится с дополнительным питанием не хотелось. Поэтому применил Arduino Uno, и вот что получилось.

ВИДЕО (http://188.168.58.111:8080/GAME/ArduinoESP.html)

Пришлось перепрошить ESP8266 и возложить на него функции общения с сервером, а Arduino Uno оставить все остальное. Общение через последовательный порт. Скорости 115200 вполне хватает, к тому же это гарантирует последовательное воспроизведение звука на стороне ардуинки. Функционал тот же самый как и Ethernet версии, но конструкция стала более мобильная не привязанная проводом к роутеру. Будет применяться для подключения к моей FT-817 через интернет. По крайней мере смогу прослушивать вызывной канал на телефоне.

RA3QDP
23.05.2020, 19:16
проверено на Windows XP - работает

Refraktor
19.06.2020, 15:49
Для всех тех кто спрашивает как пользоваться.

265949

RA3QDP
23.06.2020, 20:56
что бы выставить нужный режим передачи необходимо создать в рабочем каталоге программы файл root.txt с содержимым:
1
0,1 - 16000 G711 - 128 Kbit/s
2 - 16000 16 bit - 256 Kbit/s
3 - 16000 8 bit - 128 Kbit/s
4 - GSM - 32 Kbit/s ( должно быть 13.2 Kbit/s, но реально заголовки пакетов UDP увеличивают трафик )
5 - 8000 16 bit - 128 Kbit/s
6 - 8000 G711 - 64 Kbit/s
7 - 8000 8 bit - 64 Kbit/s

Первая строка определяет режим передачи, остальные строки служат подсказкой.

что-то у меня не получается переключать таким файлом битрейт. Может делаю не правильно.
Расскажите понятней или лучше дате файл для, например, GSM.

RN6LIQ
24.06.2020, 06:04
Для начала обновите Windows версию PMR, на всякий случай. Затем создаете в блокнотt файл root.txt, напишите цифру 4, затем нажмите клавишу Enter, сохраните файл в рабочем каталоге PMR. Запустите саму PMR-ку. Теперь на передачу у вас будет режим GSM. Но принять этот режим может только версия Windows, в версии Android кодек GSM Анатолий пока не реализовал.

В связи с тем, что местными модераторами тема переименована, обсуждение тут, на данной ветке, теряет смысл. Получается, что как бы обсуждается эмулятор PMR рации. Но это не так, тема гораздо шире, поэтому она перенесена на http://www.cqham.ru/forum/showthread.php?41895-%D5%EE%F7%F3-%EF%EE%E4%E5%EB%E8%F2%FC%F1%FF-%EF%F0%EE%E3%F0%E0%EC%EC%EE%E9
Пожалуйста, по возможности, все желающие принять участие в дальнейшем обсуждении переходите общаться на cqham