RSS блога
Подписка
Генератор цифровых паттернов из отходов
На работе периодически приходится делать какие-то приборы, для которых заказываются печатные платы. Обычно минимальный заказ плат – это 5 или 10 шт. А приборы чаще всего делаются в единственном экземпляре. Поэтому со временем накапливаются лишние печатные платы. Большинство из них разведены для очень специфических схем и применить их с пользой очень сложно. Но иногда попадаются платы, которые можно куда-то приспособить. Один из таких случаев и решил описать.
От очередного прибора остался комплект из нескольких плат. Часть из них очень специальные и годятся разве что для раздувания костров. Но нашлось и несколько довольно универсальных плат. Одна из них предназначена для установки микросхемы FPGA Altera Cyclone II. Большое количество ножек FPGA разведено на разъемы, есть место для тактового генератора и стабилизатора LD1117S12TR на 1.2 В для питания ядра FPGA. Короче говоря, эта плата довольно сильно похожа на универсальную отладочную плату.
Еще одна плата предназначена для установки микроконтроллера (далее МК) типа STM32F103, многие ножки которого тоже разведены на разъемы. На ней нет почти ничего лишнего, зато есть всё необходимое: разъем SWD, разъем UART. И что самое главное, в эту плату вторым этажом может вставляться плата с FPGA.
Вместе две этих платы представляют отличную основу для разнообразных конструкций. Есть еще и третья плата с разъемами SMA и буферными логическими микросхемами. На ней разведены 4 логических входа и 4 логических выхода.
И тут как раз возникла необходимость в 4-канальном генераторе импульсов, в качестве которого до этого использовались два готовых 2-канальных генератора сигналов произвольной формы (AWG), плюс еще третий генератор для внешнего запуска. Вся эта связка была крайне неудобна в использовании.
Найденные платы вполне позволяют построить программируемый четырехканальный генератор импульсов. Кроме выходного разъема, кждый канал будет иметь еще и входной разъем для внешнего запуска. Остается добавить лишь блок питания и плату интерфейса USB. Прибор должен управляться от компьютера, а это сильно упрощает задачу по сравнению с созданием автономного прибора с собственным дисплеем и управлением.
Плата интерфейса USB тоже нашлась готовая от другого проекта, который делал еще раньше. Этих маленьких платок в тот раз было изготовлено с большим избытком, поэтому ставил их много куда. На плате размещен разъем USB-B, микросхема FT232RL и цифровой изолятор ADuM1201. Гальваническая развязка интерфейса очень желательна для измерительных приборов, всегда ее делаю. Если обмен медленный, то для этого подходят дешевые оптроны. Что касается микросхемы от FTDI, то она мне нравится беспроблемностью драйверов, о которых совершенно не нужно заботиться. Хотя, конечно, удовольствие не из дешевых. Было бы выгодней сделать плату на чем-то вроде CH340E + CA-IS3722 (или NSi8221), возможно, в будущем попробую.
Блок питания (БП) решил не делать полноценный сетевой, а обойтись внешним адаптером с выходным напряжением 9 или 12 В. Для питания плат требуется напряжение +3.3 В, еще как опция может быть использовано +5 В для выходных буферов. Подходящей печатной платы для БП не нашлось. Можно было сделать БП на куске макетки, но я заморочился и развел специальную плату. На ней установил стандартный разъем питания, самовосстанавливающийся предохранитель от пожара, диод от переполюсовки, разъем для выключателя питания, входной конденсатор, стабилизатор +5 В (LM2940CT-5.0) и стабилизатор +3.3 В (LF33CV). Оба стабилизатора имеют землю на корпусе, что позволило их прикрутить к шасси без прокладок.
С шасси оказалось сложнее всего – найти подходящий кусок достаточно толстого дюраля (порядка 3 мм) не удалось, пришлось взять какой-то страшно дырявый кусок, который когда-то был частью какого-то прибора. Потом его кто-то для чего-то использовал, и не раз, сверля и прогрызая все новые дырки. Нужные мне отверстия с резьбой М3 для стоек плат с большим трудом удалось разместить между имеющимися дырками. По-другому их не назвать. Чтобы хоть немного исправить эстетику, прошелся сверлом, разверткой и зенковкой, сделав из дырок вполне аккуратные круглые отверстия. Но в идеале их тут быть вообще не должно.
Платы спаял не полностью, а установил только то, что будет использоваться. Множество отверстий остались пустыми – лишние разъемы и другие детали устанавливать ни к чему. На плате входов-выходов в качестве входных буферов поставил 74LVC125, которые при питании 3.3 В могут работать с входными сигналами 3.3 или 5 В. На входе разведена защита на диодах BAS70. Входное сопротивление не делал 50 Ом, чтобы не просаживать уровень сигнала (источник сигнала может оказаться маломощным). Вместо этого сделал 10 кОм. Если будут подаваться быстрые сигналы, то наверняка на стороне источника будет согласование с кабелем 50 Ом. А согласования с одной стороны вполне достаточно, особенно когда кабели не очень длинные.
В качестве выходных буферов поставил 74ABT245, на каждый выходной разъем параллельно работают по 4 выхода, выходное сопротивление резисторами доведено до 50 Ом. Серия ABT является BiCMOS, микросхемы очень быстрые, но из-за биполярного выходного каскада уровень логической единицы заметно ниже питания. Зря выбрал эту серию, надо было ставить 74ACT. Может потом поменяю.
Согласно грубой прикидке, все эти платы влезут в корпус G765 тайваньского производителя Gainta. Такой корпус (версия «A», с алюминиевыми панелями) был специально куплен. К слову, алюминиевый сплав, из которого сделаны панели, очень мягкий и вязкий, обрабатывается крайне плохо.
Не влезала лишь плата входов-выходов, но на ней можно без особых последствий обрезать выступ, на котором расположен светодиод.
Компоновку плат в корпусе по-быстрому прикинул в CorelDraw. Рисованием в 3D не владею, да и не надо здесь это, только лишняя трата времени.
Самое главное – дизайн панелей. С этого начинается любой прибор. Пока нет дизайна, который устраивает, нельзя дать добро на применение корпуса. Но на сей раз всё вполне нормально вписалось в панели, хоть платы разрабатывались не для этого корпуса. На передней панели нарисовал логотип института, из отходов деятельности которого и делается этот прибор.
Осталось решить проблему с платой входов-выходов, которая в этот корпус не влезает. Ее надо не только обрезать, но еще и перенести на ней в другое место светодиод. А также разместить выключатель питания, который раньше вообще не был предусмотрен. Естественно, при проработке дизайна панели было учтено, где именно можно разместить эти компоненты. Для выключателя выпилил в плате паз (на этом месте ничего не было, только полигон земли), а для светодиода просверлил отверстия на краю площадки крепежного отверстия, которое здесь не используется. Площадку разрезал на два части, к которым теперь можно припаять выводы светодиода.
Выключатель питания пришлось несколько доработать. Дело в том, что отверстие для другого крепежного уха не помещалось на плату. Пришлось ухо удалить, оставив лишь небольшой усик, который будет входить в маленькое отверстие в плате и защищать выключатель от поворота.
В смонтированном виде это выглядит так:
Теперь плата влезает в корпус. Выключатель со светодиодом тоже на месте.
Следующий шаг – установка задней панели. Решил ее прикрепить к шасси с помощью уголка, так удобней. Винты сзади, на мой взгляд, допустимы. Хотя для кого-то с более строгим подходом к внешнему виду они могут показаться неприемлемыми. Тогда от них можно отказаться, панель и без этого нормально держится в пазах корпуса.
Еще одну неприемлемую с точки зрения эстетов вещь я сделал с нижней половинкой корпуса. Шасси внутри корпуса крепится с помощью саморезов к пластиковым стойкам, которые отлиты в корпусе. Но эти стойки тонкие и низкие, особой прочностью не отличаются. Допускают применение лишь коротких саморезов. Я же обычно добавляю к высоте этих стоек еще и толщину днища, для чего сверлю в стойках сквозные отверстия. Тогда можно применить более длинные саморезы, но снизу появляются четыре маленьких лишних дырочки…
В общем, блок собран.
Но чего-то не хватает: наклеек панелей. В простейшем случае печатаю наклейки на лазерном принтере на самоклеющейся бумаге, затем ламинирую холодным способом шагреневым ламинатом. Но гораздо лучше будут выглядеть наклейки, напечатанные рекламщиками на пленке ПВХ (например, Oracal 641). Они также могут ламинировать наклейку матовым ламинатом, а потом вырезать плоттером все необходимые отверстия. Стоит это очень дешево, для них это смешные объемы по сравнению с какой-нибудь внешней рекламой на здании или троллейбусе. Печать может быть полноцветной (вообще, печать всегда идет в цвете, даже черный цвет – составной), но для электронных приборов я цветом не злоупотребляю. Не вижу пока в себе сил сделать цветной дизайн панели, чтобы он не выглядел кустарно. Может быть, когда-нибудь научусь, но пока – нет.
Вот так панели выглядят с наклейками:
На этом аппаратная часть готова. Но прибор пока мертв. Чтобы вдохнуть в него жизнь, надо добавить программную часть. К сожалению, прошли времена, когда достаточно было спаять плату, и ее можно сразу же включать. Теперь постоянно приходится заниматься долгим и нудным программированием, без которого не сделать ничего приличного. Крайне неприятное занятие, не зря программистам так много платят.
Прежде всего нужно реализовать всю необходимую логику внутри FPGA. Поскольку строим генератор, то надо каким-то образом получить периодическую последовательность импульсов. Для этого можно использовать два подхода. Самый простейший – это программируемый делитель частоты. Коэффициент деления представляет собой целое число, он задает, сколько периодов опорной частоты будет в одном периоде выходной частоты. Т.е. фактически задается период. Чем меньше коэффициент деления, тем более грубой получается перестройка.
Есть другой подход, когда целое число задает частоту повторения выходных импульсов. При этом шаг изменения частоты всегда постоянен. Более того, он может быть сделан сколь угодно малым. Такой метод использует вместо счетчика сумматор. Называется это NCO (Numerically Controlled Oscillator) и используется обычно внутри прямых цифровых синтезаторов (DDS, Direct Digital Synthesizer). Однако чудес не бывает, такой метод обеспечивает лишь заданную среднюю частоту импульсов на некотором интервале времени. В то же время два соседних периода могут отличаться на величину периода опорного сигнала. Такой джиттер практически незаметен при генерации низких частот, но при высокой выходной частоте может стать неприемлемым.
Вообще говоря, чудо возможно, но требует дополнительных затрат. Если взять полноценный DDS с синусоидальным выходом, тщательно отфильтровать выходной сигнал от побочных компонентов, затем подать синус на компаратор, то на выходе получим меандр с низким джиттером и малым шагом перестройки по частоте. Но тут это не надо. Основной режим работы будет – обычный делитель частоты (DIV), а NCO может понадобиться лишь для каких-то отдельных задач. Допустим, можно сгенерировать меандр в некоторой полосе частот возле 10.7 МГц и с его помощью настроить ПЧ-тракт ЧМ-приемника.
Для получения широкого диапазона частот генератора выбрал разрядность счетчика (и сумматора для NCO) равной 32 битам. Для схем с такими счетчиками и прочей логикой максимальная тактовая частота достигает 100 МГц даже для чипа FPGA с самым плохим speed grade. Поэтому выбрал частоту опорного генератора 100 МГц. В результате в режиме делителя частоты оказалось возможным получить период сигнала от 20 нс до почти 43 с. В режиме NCO шаг частоты составил 100 МГц / 2^32 = 0.023 Гц. Это и есть минимальная выходная частота, ну а максимальная – половина от тактовой, т.е. 50 МГц. Пределы вполне достаточные для большинства практических нужд.
Тип задающего генератора (NCO или DIV) можно переключать с помощью бита в регистре режима (в данном случае это ModeReg.5). Две приведенных выше схемы на AHDL выглядят так:
Чтобы задавать рабочую частоту, надо как-то загружать коды в регистр AutoReg[]. В простейшем случае код можно задавать в параллельном виде, используя группу ножек FPGA. Но при такой большой разрядности это очень громоздко. Поскольку быстрой передачи данных тут не требуется, то можно использовать последовательный обмен с МК. Проще всего реализовать порт SPI. Для него потребуются 4 линии: SCK, MOSI, MISO и NSS (Slave Select с низким активным уровнем). Данные передаются от МК по линии MOSI, дальше они вдвигаются в сдвиговый регистр по тактовому сигналу SCK, а по окончанию приема будут параллельно перегружаться в нужный регистр генератора.
Поскольку регистров управления будет много, их надо как-то адресовать. Адрес можно передавать в той же последовательной посылке, что и данные. Допустим, сначала можно передать 8 бит адреса, а затем 32 бита данных.
Обмен данными по SPI может быть двунаправленным. В качестве признака чтения данных можно использовать один из битов адреса (допустим, старший). Если он равен единице, значит МК хочет прочитать данные. Тогда сразу после приема адреса в сдвиговый регистр надо загрузить значение из одного из регистров генератора. Следующими импульсами SCK данные будут сдвигаться и выводиться на линию MISO.
Полярность и фаза сигнала SPI могут быть разными, обычно встроенный порт SPI микроконтроллеров позволяет это настраивать. В данном случае порт SPI будет использоваться не только для обмена данными, но и для загрузки конфигурации в FPGA (в режиме PS – passive serial). Поэтому желательно использовать одинаковые настройки SPI во всех случаях. При конфигурировании FPGA в режиме PS данные защелкиваются по фронту SCK, а между посылками сигнал SCK находится в состоянии низкого уровня. Это соответствует настройкам SPI микроконтроллера CPOL = 0, CPHA = 0.
Принимаемые данные должны защелкиваться по фронту сигнала SCK, а передаваемые должны выдаваться на линию MISO по спаду SCK. Поэтому для приема и передачи я использую отдельные сдвиговые регистры, один из которых тактируется прямым сигналом SCK, а второй – инверсным.
Адрес и данные принимаются отдельными регистрами. Когда данные приняты, формируется сигнал записи WR, по которому данные можно перезаписывать в регистры генератора. Адрес дешифрируется, на его основе формируется столько сигналов WRn, сколько нужно. Чтобы понимать, когда заканчивается прием адреса и данных, тактовые импульсы на входе SCK подсчитываются с помощью счетчика. Для первых 8-ми импульсов разрешена работа сдвигового регистра адреса, для последующих 32-х – регистра данных. Если в принятом адресе старший бит равен 1, то вместо сигналов записи формируются сигналы чтения RDn. По этим сигналам данные из выбранного регистра генератора копируются сначала в буферный регистр, а потом по спаду сигнала SCK записываются в выходной сдвиговый регистр и начинают сдвигаться. Они выводятся на линию MISO через буфер с тремя состояниями выхода.
Логика порта SPI тактируется сигналом SCK, в то время как вся остальная схема генератора тактируется сигналом GCLK частотой 100 МГц. Это таит в себе опасность под именем «метастабильность».
При записи данных в любой регистр должны быть выдержаны некоторые соотношения для входных сигналов по времени. Во-первых, длительность нуля и единицы тактового сигнала не может быть меньше определенного значения. Это означает выбор тактовой частоты не выше некоторого предела. Во-вторых, данные должны поступать на вход заранее, до фронта тактового сигнала должно быть не менее времени установления (Tsu, setup time). Сниматься данные тоже должны с задержкой, которая называется временем удержания (Th, hold time). Но как выдержать эти требования по времени, если данные приходят синхронно с одним тактовым сигналом, а сам регистр тактируется другим? Это называется разные клок-домены (Clock Domains). Есть отдельная обширная тема под названием CDC (Clock Domain Crossing), где рассматриваются способы безопасной передачи данных из одного клок-домена в другой.
Что будет, если не принимать никаких мер? Тогда данные, приходящие в случайный момент времени относительно тактового сигнала регистра, иногда будут попадать в интервал времени Tsu + Th. В этом случае триггеры регистра могут оказаться в состоянии метастабильности. Конкретное проявление этого эффекта зависит от технологии чипа, один из вариантов проявления показан на осциллограмме (найдена в Интернете):
Как видно, выход триггера некоторое время находится в «сером» состоянии между единицей и нулем, а затем переходит в одно из устойчивых состояний. При этом часть триггеров регистра может защелкнуть правильные данные, а часть – ошибочные. Двоичный код числа может быть сильно искажен. Вероятность появления метастабильности не такая и маленькая. Если не принимать никаких мер, то при циклической загрузке кода частоты со стороны МК можно легко наблюдать сбои в работе генератора. Такой прибор, как говорится, только «ф топку», ну или в клок-доменную печь :)
Как бороться с метастабильностью? Для этого переход сигнала из одного клок-домена в другой делают с помощью синхронизатора (Synchronizer). Существует много вариантов реализации синхронизаторов, в простейшем случае это цепочка из двух D-триггеров:
Такой синхронизатор подходит для перехода с домена с более низкой тактовой частотой в домен с более высокой. Это как раз наш случай – порт SPI здесь работает на частоте 16 МГц, а вся остальная схема генератора – на частоте 100 МГц. На AHDL синхронизатор выглядит примерно так:
Подобные синхронизаторы используются внутри микроконтроллеров для входных сигналов GPIO, так как внешний мир для МК является другим клок-доменом по отношению к миру внутреннему. Для примера ниже приведен рисунок структуры порта микроконтроллера AVR, желтым выделен синхронизатор:
Забавно, что синхронизатор не устраняет метастабильность полностью, а лишь снижает ее вероятность. Существует расчет среднего времени между отказами (mean time between failures, MTBF), при наличии синхронизатора он дает солидное время, сбоя можем и не дождаться.
Окончательная схема порта SPI приведена ниже. Сигнал глобального сброса не показывал, он тут не принципиален. Для формирования сигналов WR и RD, которые идут в другой домен, использованы синхронизаторы. За одно они еще выполняют функции формирователей коротких импульсов длиной в один период GCLK.
При чтении данные тоже пересекают границу клок-доменов. Она находится между регистрами BuffReg и DoutReg. Но тут метастабильности не возникает, потому что сигнал RD берет свое начало в клок-домене SPI и его максимальная задержка относительно SCK легко считается и не превышает максимально допустимой.
Обычно я схем логики для FPGA не рисую, сейчас нарисовал специально для обзора (карандашом Pentel 120 A3 0.5, а поверх – ErichKrause METRIX liquid ink roller 0.5). Намного проще схемы сразу описывать текстом на языке описания аппаратуры. Весь порт SPI на AHDL выглядит так:
Когда связь с МК налажена, можно загружать в регистр периода (или частоты) нужное значение, получая выходную частоту в широком диапазоне. Но пока генератор умеет формировать лишь короткие импульсы, следующие с заданной частотой. Чтобы сделать генератор более практичным, надо добавить возможность получения на выходе импульсов произвольной длительности. Для этого потребуется цифровой одновибратор, который будет запускаться короткими импульсами задающего генератора. Схема выглядит примерно так:
С задающего генератора приходит импульс PlsBeg. JK-триггер при этом устанавливается, начинает формироваться выходной импульс. Одновременно начинает инкрементироваться счетчик длительности WidthCnt. Как только код в счетчике становится равным коду регистра длительности импульса WidthReg, формируется импульс конца интервала PlsEnd, который поступает на вход K триггера и сбрасывает его. При этом импульс заканчивается. В реальности сравнение надо делать «больше или равно», чтобы импульс прерывался, если будет загружена меньшая длительность. Иначе есть шанс зависнуть на время максимальной длительности импульса, а это десятки секунд. На AHDL формирователь выглядит так:
На первый взгляд, схема слишком сложная для простого формирования импульса заданной длительности. Но тут надо учитывать всякие «краевые» эффекты, когда в некоторых условиях возможны глитчи длительностью в один такт. Вернее, это даже не глитчи, а просто некоторые особенности логики работы. Настоящие глитчи – это короткие (короче периода тактового сигнала) импульсы, которые возникают в результате «гонок» сигналов из-за задержек в логических элементах. Тут с таким сталкиваться не приходится, схема генератора полностью синхронная, все триггеры тактируются единым сигналом GCLK. Никакой логики в цепи тактового сигнала нет, для управления используются входы Enable. В результате никакие «гонки» сигналов или промежуточные состояния многоразрядных регистров не беспокоят. Главное, чтобы все сигналы устаканились к следующему тактовому импульсу.
А проблемы могут быть связаны с логикой работы. Например, для получения импульса нужной длительности из стартового и стопового импульса логично использовать JK-триггер, у него как раз есть для этих целей отдельные входы. Но если период и длительность установить такими, что стартовый импульс совпадет со стоповым, триггер переключится в противоположное состояние, хотя по логике он должен установиться (ведь пришел стартовый импульс).
Еще хуже, если стартовые импульсы будут поступать чаще стоповых. Тогда на выходе триггера появятся импульсы хаотичной длительности. Исправить ситуацию можно добавлением логики на вход K триггера, что сделает вход J приоритетным. Как вариант, можно вместо JK-триггера применить D-триггер, но он тоже потребует дополнительной логики.
Это больше вопрос «дуракоустойчивости», ведь в добром здравии никто не будет устанавливать длительность больше периода. Но доброе здравие – это лишь математическая абстракция. В реальности пользователь может вводить что угодно, даже заведомо неправильные комбинации значений. Запрещать ввод таких значений не всегда представляется возможным, может потребоваться слишком много проверок (например, синхронизация каждого из каналов может приходить откуда угодно). Да и пользователю неудобно, когда запрещен ввод каких-то значений (придется сначала увеличивать период, а только затем длительность, наоборот интерфейс сделать не даст). Поэтому лучше просто принять меры, чтобы при неправильных параметрах поведение генератора было как можно более адекватным. К счастью, сделать машину адекватнее человека не так уж сложно. Когда длительность импульса установлена больше периода, логично ожидать, что импульс станет бесконечным, и на выходе все время будет активный уровень. Все подобные ситуации учтены в приведенной выше схеме.
Для еще большей универсальности генератора полезно добавить программируемую задержку между импульсом запуска и началом формирования выходного импульса. Это пригодится в том случае, если будут использоваться сразу несколько каналов. Тогда выходные импульсы можно будет сдвигать относительно друг друга. Формирование задержки аналогично формированию длительности выходного импульса. Опять возникает вопрос насчет поведения при некорректных параметрах. Что должно происходить, если задержка установлена больше периода? Ответ на этот вопрос не совсем очевиден. Я посчитал, что логичней всего в такой ситуации будет отсутствие выходных импульсов. По крайней мере, это намного лучше хаотичных импульсов.
Схема размножается на 4 канала, получается вполне пригодный для использования 4-канальный генератор. Размножение кода в AHDL делается просто, для этого существует конструкция FOR — GENERATE. В приведенном выше коде i – это и есть номер канала.
На плате входов/выходов есть 4 входных разъема. Чтобы они не пропадали даром, их можно задействовать для внешнего запуска генератора. С входами внешней синхронизации такая же ситуация, как и с портом SPI – каждый такой вход представляет собой отдельный клок-домен и требует применения синхронизатора.
Схема синхронизатора очень напоминает схему фильтра импульсных помех. Там тоже цепочка триггеров, выходы которых объединены по логике «И». Такая схема не будет пропускать короткие импульсы, длительность которых меньше такого количества периодов тактовой частоты, сколько имеется триггеров в цепочке. Подобные фильтры помех есть, например, на входах захвата таймеров в микроконтроллерах AVR. Подключая разное число триггеров в цепочке, можно регулировать минимальную длительность импульса, который может пройти через фильтр. На всякий случай сделал здесь такой же фильтр. Мало ли какой сигнал будет поступать на вход внешней синхронизации, нежелательные «иголки» можно таким способом убрать. Включить или отключить фильтр можно с помощью специального бита в регистре режима. Длину цепочки я сделал 6, но можно сделать какой угодно в зависимости от того, что надо фильтровать.
При работе с внешней синхронизацией мне показалось полезным иметь индикацию частоты, которая поступает на синхровход. Полноценный частотомер реализовывать не стал, а сделал просто измеритель периода, который может делать это с точностью 10 нс. Немного подумав, добавил еще и измеритель частоты, который производит счет входных импульсов в заданном окне. Первый способ дает хорошую точность при измерении низких частот, второй – высоких. Их можно объединить, получив постоянную относительную погрешность для любой частоты, но лень тут этим заниматься – не частотомер ведь.
Обмен по SPI сразу предусматривал как запись, так и чтение. Но чтение до этого не использовалось. Какой смысл читать регистры, которые мы сами загружаем, и которые меняться не могут? Но с появлением измерителя частоты операция чтения стала востребованной. И тут случился великий облом – чтение не заработало. Вообще, я в первый раз в STM32 использую встроенный SPI для чтения. До этого приходилось только передавать по нему данные во всякие внешние микросхемы. Хотя на AVR чтение по SPI неоднократно делал. Там все просто: загрузили данные в регистр данных SPI – они начали передаваться. Как только передались – можно читать регистр, в нем будут принятые данные. По наивности думал, что и в STM32 так же, но не тут-то было. Из SPI читался всякий бред. В который раз получаю доказательство, что STM32 – это не радиолюбительский процессор, с ним всегда куча проблем. Потратил на вылавливание глюка два дня и две ночи (с перерывами на обед, разумеется). Сначала не было уверенности, что проблема именно в STM. Предполагал, что FPGA неправильно отдает данные, ведь SPI в ней самодельный и тоже может содержать ошибки. На моем осциллографе это увидеть крайне сложно, тот редкий случай, когда цифровой осциллограф был бы полезен. Но такое случается не чаще, чем раз в год, поэтому бежать и покупать его вряд ли имеет смысл. Начал писать всякие тесты, параллельно модифицируя код и в STM, и в FPGA. Вроде, на осциллографе смутно вижу, что данные идут правильные. Чтобы окончательно в этом убедиться, временно подключил макетную плату с ATmega88. Конечно же, она приняла данные абсолютно корректно. Получается, собака зарыта именно в STM. С помощью параметрического программирования (когда изменения кода там и тут делаются без всякого понимания, а наблюдается лишь конечный результат) был найден рабочий вариант исходника. Кривой, но рабочий. Так и оставил, выдохнув и разжав кулаки.
В итоге имеем 4 канала автогенераторов, способных генерировать заданную частоту и 4 канала внешней синхронизации. Для большей гибкости, можно подключать каждый выходной канал генератора к любому источнику синхронизации. Можно все каналы к одному, можно к разным. Для еще большей гибкости сигнал внешней синхронизации может иметь активный фронт или активный спад. Или фронт и спад сразу. Для выбора источника синхронизации сделал мультиплексор, который управляется битами регистра режима.
В принципе, на этом можно и остановиться, реализован довольно богатый набор функций для генератора прямоугольных импульсов. Но задача, с которой пришлось столкнуться на работе, требовала большего. Вместо генерации отдельных импульсов с некоторой частотой повторения, должны генерироваться последовательности импульсов (говоря по-другому, серии, или паттерны). Внутри серии может быть несколько импульсов, разделенных промежутками.
Если дать полную свободу, то для описания серии нужно будет слишком много данных, что усложнит программирование параметров генератора. На практике это не надо (по крайней мере, в моем случае), поэтому свободу лучше ограничить. Вариант, который обычно используется в AWG, где форма записывается в память и потом «проигрывается» из нее, мне подходил меньше всего. Требовалась не совершенно произвольная последовательность выходных импульсов, а последовательность в некой сетке.
Строить серию решил из одинаковых интервалов, которые я назвал «шаг» (Step). Для этого потребовался еще один счетчик и регистр длительности шага. Все импульсы начинаются в начале шага и имеют одинаковую длительность внутри серии. Длительность импульсов задается в регистре длительности, как обычно. Пауза между импульсами – это разность между величиной шага и длительностью импульса.
Сам паттерн хранится в специальном регистре, в начале каждой серии его значение загружается в сдвиговый регистр. Если бит равен единице, то на данном шаге генерируется импульс, если ноль – то импульс пропускается. Если длительность импульса установлена равной длительности шага, а импульсы в серии идут подряд, то они сливаются в один длинный импульс. Количество шагов в серии я ограничил до 32. Без проблем можно сделать и больше, но мне даже столько с избытком. Серии в разных каналах генератора можно сдвигать относительно сигнала синхронизации с дискретностью в 1 период тактовой частоты, тут величина шага ограничений не накладывает. Если задать только 1 импульс в серии, то генератор вырождается в обычный генератор импульсов, тогда величина шага не используется. Схему этой части генератора приводить не вижу смысла, она очень специальная и вряд ли вызовет интерес.
Чтобы дать генератору еще больше возможностей, на выходе реализовал объединение каналов по логике «И» и «ИЛИ». Это позволяет получить совсем странные последовательности на выходе. Эти возможности, скорее всего, не нужны, но в самом начале пути я думал, что просто обойдусь логическими выходными операциями без паттернов. Но паттерны пришлось все-таки добавить, а выходную логику при этом убирать не стал, раз уже написана.
Долго думал, как реализовать интерфейс пользователя для задания паттернов. Решил задавать паттерн в виде строки из 0 и 1, но для большей наглядности еще рисовать на экране, какой выходной сигнал в итоге получится. Цифровые значения (период, длительность, задержка и т.д.) задаются с помощью полей ввода.
Внутри FPGA проект занял 3513 логических элементов (LE), что составляет 76% от полной емкости кристалла. Набравшись наглости, я решил попробовать задействовать PLL внутри FPGA и поднять тактовую частоту. Временной анализатор Quartus-а показывает максимальную частоту для проекта примерно 120 МГц (она немного меняется при каждой перекомпиляции в зависимости от структуры проекта). Можно оптимизировать проект по скорости, но я решил попробовать без этого. Подняв с помощью PLL частоту до 200 МГц, я не обнаружил никаких глюков – все работало как следует, обеспечивая очень даже неплохое разрешение по времени в 5 нс. Нагрев микросхемы FPGA тоже незначительный – она еле теплая. Конечно, в серьезных проектах так делать нельзя (но в несерьезных – можно).
Мой осциллограф имеет слишком узкую полосу пропускания для полноценного наблюдения сигналов этого генератора. Однако по падению отображаемой амплитуды импульса можно определить его длительность, даже если она 10 нс (или даже 5 нс). Ниже показан скриншот экрана осциллографа с одним из сигналов, который был получен с помощью этого генератора:
Встроенный микроконтроллер генератора выполняет лишь примитивные функции: полученные по USB коды загружает в регистры FPGA, а также по запросу читает коды из регистров и передает их по USB. Это позволило почти избежать мучительного процесса его программирования. Еще МК по включению питания загружает конфигурацию в FPGA из своей FLASH. По умолчанию записал туда вариант на 200 МГц, но в случае чего с помощью программы с компьютера можно загрузить обычную, на 100 МГц. В программе предусмотрел загрузку конфигурации FPGA из файла в формате .rbf, который генерирует Quartus. Так что можно держать на диске сколько угодно прошивок FPGA под конкретные задачи.
В настройках программы сделал возможность указания тактовой частоты FPGA, мало ли какие будут еще прошивки.
Все это я делал под конкретную задачу, но получилось довольно универсально. Например, можно «нарисовать» пакет для передачи данных в какое-нибудь устройство по SPI или другому последовательному интерфейсу. При этом можно плавно двигать сигналы относительно друг друга с шагом 5 нс. Что еще можно было бы добавить, так это однократное формирование паттерна при нажатии кнопки. Пока этого нет, но допишу при первой востребованности. Тут и так сделано много лишнего.
Программа работает через DLL, в которой реализовал все функции управления. Сделал так специально, чтобы можно было использовать генератор из среды Matlab.
Мораль всей этой истории – когда разводите печатные платы для работы, разводите их так, чтобы потом можно было использовать для чего-нибудь полезного.
От очередного прибора остался комплект из нескольких плат. Часть из них очень специальные и годятся разве что для раздувания костров. Но нашлось и несколько довольно универсальных плат. Одна из них предназначена для установки микросхемы FPGA Altera Cyclone II. Большое количество ножек FPGA разведено на разъемы, есть место для тактового генератора и стабилизатора LD1117S12TR на 1.2 В для питания ядра FPGA. Короче говоря, эта плата довольно сильно похожа на универсальную отладочную плату.
Еще одна плата предназначена для установки микроконтроллера (далее МК) типа STM32F103, многие ножки которого тоже разведены на разъемы. На ней нет почти ничего лишнего, зато есть всё необходимое: разъем SWD, разъем UART. И что самое главное, в эту плату вторым этажом может вставляться плата с FPGA.
Вместе две этих платы представляют отличную основу для разнообразных конструкций. Есть еще и третья плата с разъемами SMA и буферными логическими микросхемами. На ней разведены 4 логических входа и 4 логических выхода.
И тут как раз возникла необходимость в 4-канальном генераторе импульсов, в качестве которого до этого использовались два готовых 2-канальных генератора сигналов произвольной формы (AWG), плюс еще третий генератор для внешнего запуска. Вся эта связка была крайне неудобна в использовании.
Найденные платы вполне позволяют построить программируемый четырехканальный генератор импульсов. Кроме выходного разъема, кждый канал будет иметь еще и входной разъем для внешнего запуска. Остается добавить лишь блок питания и плату интерфейса USB. Прибор должен управляться от компьютера, а это сильно упрощает задачу по сравнению с созданием автономного прибора с собственным дисплеем и управлением.
Плата интерфейса USB тоже нашлась готовая от другого проекта, который делал еще раньше. Этих маленьких платок в тот раз было изготовлено с большим избытком, поэтому ставил их много куда. На плате размещен разъем USB-B, микросхема FT232RL и цифровой изолятор ADuM1201. Гальваническая развязка интерфейса очень желательна для измерительных приборов, всегда ее делаю. Если обмен медленный, то для этого подходят дешевые оптроны. Что касается микросхемы от FTDI, то она мне нравится беспроблемностью драйверов, о которых совершенно не нужно заботиться. Хотя, конечно, удовольствие не из дешевых. Было бы выгодней сделать плату на чем-то вроде CH340E + CA-IS3722 (или NSi8221), возможно, в будущем попробую.
Блок питания (БП) решил не делать полноценный сетевой, а обойтись внешним адаптером с выходным напряжением 9 или 12 В. Для питания плат требуется напряжение +3.3 В, еще как опция может быть использовано +5 В для выходных буферов. Подходящей печатной платы для БП не нашлось. Можно было сделать БП на куске макетки, но я заморочился и развел специальную плату. На ней установил стандартный разъем питания, самовосстанавливающийся предохранитель от пожара, диод от переполюсовки, разъем для выключателя питания, входной конденсатор, стабилизатор +5 В (LM2940CT-5.0) и стабилизатор +3.3 В (LF33CV). Оба стабилизатора имеют землю на корпусе, что позволило их прикрутить к шасси без прокладок.
С шасси оказалось сложнее всего – найти подходящий кусок достаточно толстого дюраля (порядка 3 мм) не удалось, пришлось взять какой-то страшно дырявый кусок, который когда-то был частью какого-то прибора. Потом его кто-то для чего-то использовал, и не раз, сверля и прогрызая все новые дырки. Нужные мне отверстия с резьбой М3 для стоек плат с большим трудом удалось разместить между имеющимися дырками. По-другому их не назвать. Чтобы хоть немного исправить эстетику, прошелся сверлом, разверткой и зенковкой, сделав из дырок вполне аккуратные круглые отверстия. Но в идеале их тут быть вообще не должно.
Платы спаял не полностью, а установил только то, что будет использоваться. Множество отверстий остались пустыми – лишние разъемы и другие детали устанавливать ни к чему. На плате входов-выходов в качестве входных буферов поставил 74LVC125, которые при питании 3.3 В могут работать с входными сигналами 3.3 или 5 В. На входе разведена защита на диодах BAS70. Входное сопротивление не делал 50 Ом, чтобы не просаживать уровень сигнала (источник сигнала может оказаться маломощным). Вместо этого сделал 10 кОм. Если будут подаваться быстрые сигналы, то наверняка на стороне источника будет согласование с кабелем 50 Ом. А согласования с одной стороны вполне достаточно, особенно когда кабели не очень длинные.
В качестве выходных буферов поставил 74ABT245, на каждый выходной разъем параллельно работают по 4 выхода, выходное сопротивление резисторами доведено до 50 Ом. Серия ABT является BiCMOS, микросхемы очень быстрые, но из-за биполярного выходного каскада уровень логической единицы заметно ниже питания. Зря выбрал эту серию, надо было ставить 74ACT. Может потом поменяю.
Согласно грубой прикидке, все эти платы влезут в корпус G765 тайваньского производителя Gainta. Такой корпус (версия «A», с алюминиевыми панелями) был специально куплен. К слову, алюминиевый сплав, из которого сделаны панели, очень мягкий и вязкий, обрабатывается крайне плохо.
Не влезала лишь плата входов-выходов, но на ней можно без особых последствий обрезать выступ, на котором расположен светодиод.
Компоновку плат в корпусе по-быстрому прикинул в CorelDraw. Рисованием в 3D не владею, да и не надо здесь это, только лишняя трата времени.
Самое главное – дизайн панелей. С этого начинается любой прибор. Пока нет дизайна, который устраивает, нельзя дать добро на применение корпуса. Но на сей раз всё вполне нормально вписалось в панели, хоть платы разрабатывались не для этого корпуса. На передней панели нарисовал логотип института, из отходов деятельности которого и делается этот прибор.
Осталось решить проблему с платой входов-выходов, которая в этот корпус не влезает. Ее надо не только обрезать, но еще и перенести на ней в другое место светодиод. А также разместить выключатель питания, который раньше вообще не был предусмотрен. Естественно, при проработке дизайна панели было учтено, где именно можно разместить эти компоненты. Для выключателя выпилил в плате паз (на этом месте ничего не было, только полигон земли), а для светодиода просверлил отверстия на краю площадки крепежного отверстия, которое здесь не используется. Площадку разрезал на два части, к которым теперь можно припаять выводы светодиода.
Выключатель питания пришлось несколько доработать. Дело в том, что отверстие для другого крепежного уха не помещалось на плату. Пришлось ухо удалить, оставив лишь небольшой усик, который будет входить в маленькое отверстие в плате и защищать выключатель от поворота.
В смонтированном виде это выглядит так:
Теперь плата влезает в корпус. Выключатель со светодиодом тоже на месте.
Следующий шаг – установка задней панели. Решил ее прикрепить к шасси с помощью уголка, так удобней. Винты сзади, на мой взгляд, допустимы. Хотя для кого-то с более строгим подходом к внешнему виду они могут показаться неприемлемыми. Тогда от них можно отказаться, панель и без этого нормально держится в пазах корпуса.
Еще одну неприемлемую с точки зрения эстетов вещь я сделал с нижней половинкой корпуса. Шасси внутри корпуса крепится с помощью саморезов к пластиковым стойкам, которые отлиты в корпусе. Но эти стойки тонкие и низкие, особой прочностью не отличаются. Допускают применение лишь коротких саморезов. Я же обычно добавляю к высоте этих стоек еще и толщину днища, для чего сверлю в стойках сквозные отверстия. Тогда можно применить более длинные саморезы, но снизу появляются четыре маленьких лишних дырочки…
В общем, блок собран.
Но чего-то не хватает: наклеек панелей. В простейшем случае печатаю наклейки на лазерном принтере на самоклеющейся бумаге, затем ламинирую холодным способом шагреневым ламинатом. Но гораздо лучше будут выглядеть наклейки, напечатанные рекламщиками на пленке ПВХ (например, Oracal 641). Они также могут ламинировать наклейку матовым ламинатом, а потом вырезать плоттером все необходимые отверстия. Стоит это очень дешево, для них это смешные объемы по сравнению с какой-нибудь внешней рекламой на здании или троллейбусе. Печать может быть полноцветной (вообще, печать всегда идет в цвете, даже черный цвет – составной), но для электронных приборов я цветом не злоупотребляю. Не вижу пока в себе сил сделать цветной дизайн панели, чтобы он не выглядел кустарно. Может быть, когда-нибудь научусь, но пока – нет.
Вот так панели выглядят с наклейками:
На этом аппаратная часть готова. Но прибор пока мертв. Чтобы вдохнуть в него жизнь, надо добавить программную часть. К сожалению, прошли времена, когда достаточно было спаять плату, и ее можно сразу же включать. Теперь постоянно приходится заниматься долгим и нудным программированием, без которого не сделать ничего приличного. Крайне неприятное занятие, не зря программистам так много платят.
Прежде всего нужно реализовать всю необходимую логику внутри FPGA. Поскольку строим генератор, то надо каким-то образом получить периодическую последовательность импульсов. Для этого можно использовать два подхода. Самый простейший – это программируемый делитель частоты. Коэффициент деления представляет собой целое число, он задает, сколько периодов опорной частоты будет в одном периоде выходной частоты. Т.е. фактически задается период. Чем меньше коэффициент деления, тем более грубой получается перестройка.
Есть другой подход, когда целое число задает частоту повторения выходных импульсов. При этом шаг изменения частоты всегда постоянен. Более того, он может быть сделан сколь угодно малым. Такой метод использует вместо счетчика сумматор. Называется это NCO (Numerically Controlled Oscillator) и используется обычно внутри прямых цифровых синтезаторов (DDS, Direct Digital Synthesizer). Однако чудес не бывает, такой метод обеспечивает лишь заданную среднюю частоту импульсов на некотором интервале времени. В то же время два соседних периода могут отличаться на величину периода опорного сигнала. Такой джиттер практически незаметен при генерации низких частот, но при высокой выходной частоте может стать неприемлемым.
Вообще говоря, чудо возможно, но требует дополнительных затрат. Если взять полноценный DDS с синусоидальным выходом, тщательно отфильтровать выходной сигнал от побочных компонентов, затем подать синус на компаратор, то на выходе получим меандр с низким джиттером и малым шагом перестройки по частоте. Но тут это не надо. Основной режим работы будет – обычный делитель частоты (DIV), а NCO может понадобиться лишь для каких-то отдельных задач. Допустим, можно сгенерировать меандр в некоторой полосе частот возле 10.7 МГц и с его помощью настроить ПЧ-тракт ЧМ-приемника.
Для получения широкого диапазона частот генератора выбрал разрядность счетчика (и сумматора для NCO) равной 32 битам. Для схем с такими счетчиками и прочей логикой максимальная тактовая частота достигает 100 МГц даже для чипа FPGA с самым плохим speed grade. Поэтому выбрал частоту опорного генератора 100 МГц. В результате в режиме делителя частоты оказалось возможным получить период сигнала от 20 нс до почти 43 с. В режиме NCO шаг частоты составил 100 МГц / 2^32 = 0.023 Гц. Это и есть минимальная выходная частота, ну а максимальная – половина от тактовой, т.е. 50 МГц. Пределы вполне достаточные для большинства практических нужд.
Тип задающего генератора (NCO или DIV) можно переключать с помощью бита в регистре режима (в данном случае это ModeReg.5). Две приведенных выше схемы на AHDL выглядят так:
PerCnt[i][].(clk, clrn) = (GCLK, nGCLR);
IF ModeReg[i][3]
THEN -- NCO mode:
PerOvf[i] = PerCnt[i][RES - 1];
PerCnt[i][] = PerCnt[i][] + PerReg[i][];
ELSE -- Auto mode:
PerOvf[i] = PerCnt[i][] >= PerReg[i][];
IF PerOvf[i]
THEN PerCnt[i][] = 0;
ELSE PerCnt[i][] = PerCnt[i][] + 1;
END IF;
END IF;
PerEnd[i] = DFF(PerOvf[i], GCLK, nGCLR, );
ASync[i] = DFF(PerOvf[i] & !PerEnd[i], GCLK, nGCLR, );
Чтобы задавать рабочую частоту, надо как-то загружать коды в регистр AutoReg[]. В простейшем случае код можно задавать в параллельном виде, используя группу ножек FPGA. Но при такой большой разрядности это очень громоздко. Поскольку быстрой передачи данных тут не требуется, то можно использовать последовательный обмен с МК. Проще всего реализовать порт SPI. Для него потребуются 4 линии: SCK, MOSI, MISO и NSS (Slave Select с низким активным уровнем). Данные передаются от МК по линии MOSI, дальше они вдвигаются в сдвиговый регистр по тактовому сигналу SCK, а по окончанию приема будут параллельно перегружаться в нужный регистр генератора.
Поскольку регистров управления будет много, их надо как-то адресовать. Адрес можно передавать в той же последовательной посылке, что и данные. Допустим, сначала можно передать 8 бит адреса, а затем 32 бита данных.
Обмен данными по SPI может быть двунаправленным. В качестве признака чтения данных можно использовать один из битов адреса (допустим, старший). Если он равен единице, значит МК хочет прочитать данные. Тогда сразу после приема адреса в сдвиговый регистр надо загрузить значение из одного из регистров генератора. Следующими импульсами SCK данные будут сдвигаться и выводиться на линию MISO.
Полярность и фаза сигнала SPI могут быть разными, обычно встроенный порт SPI микроконтроллеров позволяет это настраивать. В данном случае порт SPI будет использоваться не только для обмена данными, но и для загрузки конфигурации в FPGA (в режиме PS – passive serial). Поэтому желательно использовать одинаковые настройки SPI во всех случаях. При конфигурировании FPGA в режиме PS данные защелкиваются по фронту SCK, а между посылками сигнал SCK находится в состоянии низкого уровня. Это соответствует настройкам SPI микроконтроллера CPOL = 0, CPHA = 0.
Принимаемые данные должны защелкиваться по фронту сигнала SCK, а передаваемые должны выдаваться на линию MISO по спаду SCK. Поэтому для приема и передачи я использую отдельные сдвиговые регистры, один из которых тактируется прямым сигналом SCK, а второй – инверсным.
Адрес и данные принимаются отдельными регистрами. Когда данные приняты, формируется сигнал записи WR, по которому данные можно перезаписывать в регистры генератора. Адрес дешифрируется, на его основе формируется столько сигналов WRn, сколько нужно. Чтобы понимать, когда заканчивается прием адреса и данных, тактовые импульсы на входе SCK подсчитываются с помощью счетчика. Для первых 8-ми импульсов разрешена работа сдвигового регистра адреса, для последующих 32-х – регистра данных. Если в принятом адресе старший бит равен 1, то вместо сигналов записи формируются сигналы чтения RDn. По этим сигналам данные из выбранного регистра генератора копируются сначала в буферный регистр, а потом по спаду сигнала SCK записываются в выходной сдвиговый регистр и начинают сдвигаться. Они выводятся на линию MISO через буфер с тремя состояниями выхода.
Логика порта SPI тактируется сигналом SCK, в то время как вся остальная схема генератора тактируется сигналом GCLK частотой 100 МГц. Это таит в себе опасность под именем «метастабильность».
При записи данных в любой регистр должны быть выдержаны некоторые соотношения для входных сигналов по времени. Во-первых, длительность нуля и единицы тактового сигнала не может быть меньше определенного значения. Это означает выбор тактовой частоты не выше некоторого предела. Во-вторых, данные должны поступать на вход заранее, до фронта тактового сигнала должно быть не менее времени установления (Tsu, setup time). Сниматься данные тоже должны с задержкой, которая называется временем удержания (Th, hold time). Но как выдержать эти требования по времени, если данные приходят синхронно с одним тактовым сигналом, а сам регистр тактируется другим? Это называется разные клок-домены (Clock Domains). Есть отдельная обширная тема под названием CDC (Clock Domain Crossing), где рассматриваются способы безопасной передачи данных из одного клок-домена в другой.
Что будет, если не принимать никаких мер? Тогда данные, приходящие в случайный момент времени относительно тактового сигнала регистра, иногда будут попадать в интервал времени Tsu + Th. В этом случае триггеры регистра могут оказаться в состоянии метастабильности. Конкретное проявление этого эффекта зависит от технологии чипа, один из вариантов проявления показан на осциллограмме (найдена в Интернете):
Как видно, выход триггера некоторое время находится в «сером» состоянии между единицей и нулем, а затем переходит в одно из устойчивых состояний. При этом часть триггеров регистра может защелкнуть правильные данные, а часть – ошибочные. Двоичный код числа может быть сильно искажен. Вероятность появления метастабильности не такая и маленькая. Если не принимать никаких мер, то при циклической загрузке кода частоты со стороны МК можно легко наблюдать сбои в работе генератора. Такой прибор, как говорится, только «ф топку», ну или в клок-доменную печь :)
Как бороться с метастабильностью? Для этого переход сигнала из одного клок-домена в другой делают с помощью синхронизатора (Synchronizer). Существует много вариантов реализации синхронизаторов, в простейшем случае это цепочка из двух D-триггеров:
Такой синхронизатор подходит для перехода с домена с более низкой тактовой частотой в домен с более высокой. Это как раз наш случай – порт SPI здесь работает на частоте 16 МГц, а вся остальная схема генератора – на частоте 100 МГц. На AHDL синхронизатор выглядит примерно так:
WrOut = DFF(DFF(WrIn, GCLK, nGCLR, ), GCLK, nGCLR, );
Подобные синхронизаторы используются внутри микроконтроллеров для входных сигналов GPIO, так как внешний мир для МК является другим клок-доменом по отношению к миру внутреннему. Для примера ниже приведен рисунок структуры порта микроконтроллера AVR, желтым выделен синхронизатор:
Забавно, что синхронизатор не устраняет метастабильность полностью, а лишь снижает ее вероятность. Существует расчет среднего времени между отказами (mean time between failures, MTBF), при наличии синхронизатора он дает солидное время, сбоя можем и не дождаться.
Окончательная схема порта SPI приведена ниже. Сигнал глобального сброса не показывал, он тут не принципиален. Для формирования сигналов WR и RD, которые идут в другой домен, использованы синхронизаторы. За одно они еще выполняют функции формирователей коротких импульсов длиной в один период GCLK.
При чтении данные тоже пересекают границу клок-доменов. Она находится между регистрами BuffReg и DoutReg. Но тут метастабильности не возникает, потому что сигнал RD берет свое начало в клок-домене SPI и его максимальная задержка относительно SCK легко считается и не превышает максимально допустимой.
Обычно я схем логики для FPGA не рисую, сейчас нарисовал специально для обзора (карандашом Pentel 120 A3 0.5, а поверх – ErichKrause METRIX liquid ink roller 0.5). Намного проще схемы сразу описывать текстом на языке описания аппаратуры. Весь порт SPI на AHDL выглядит так:
------------------------------- SPI Interface ---------------------------------
SPICnt[].(clk, clrn) = (GSCK, !nSS & nGCLR); -- SPI clocks counter
SPICnt[] = SPICnt[] + 1;
SPIRen = DFFE(vcc, GSCK, !nSS & nGCLR, , SPICnt[] == 7); -- Read enable
SPIWen = DFFE(vcc, GSCK, !nSS & nGCLR, , SPICnt[] == 39); -- Write enable
SPIAddrReg[].(clk, ena, clrn) = (GSCK, !nSS & !SPIRen, nGCLR); -- AddrReg
SPIAddrReg[6..0] = SPIAddrReg[7..1]; -- shift data
SPIAddrReg[7] = MOSI; -- input data
SPIRdWr = SPIAddrReg[7];
SPIDinReg[].(clk, ena, clrn) = (GSCK, !nSS & SPIRen, nGCLR); -- DinReg
SPIDinReg[30..0] = SPIDinReg[31..1]; -- shift data
SPIDinReg[31] = MOSI; -- input data
SPIBuffReg[].(clk, ena, clrn) = (GCLK, SPIRd, nGCLR); -- BuffReg
SPIDoutReg[].(clk, ena, clrn) = (!GSCK, !nSS, nGCLR); -- DoutRegr
IF SPICnt[] == 8
THEN SPIDoutReg[] = SPIBuffReg[]; -- load data
ELSE SPIDoutReg[30..0] = SPIDoutReg[31..1]; -- shift data
END IF;
MISOTri.(in, oe) = (SPIDoutReg[0], !nSS & SPIRdWr); -- output enable
MISO = MISOTri; -- output data
SPIWs = DFF(SPIWen, GCLK, nGCLR, );
SPIWe = DFF(SPIWs, GCLK, , nGCLR);
SPIWr = DFF(SPIWs & !SPIWe, GCLK, nGCLR, ) & !SPIRdWr;
SPIRs = DFF(SPIRen, GCLK, nGCLR, );
SPIRe = DFF(SPIRs, GCLK, , nGCLR);
SPIRd = DFF(SPIRs & !SPIRe, GCLK, nGCLR, ) & SPIRdWr;
FOR i IN 0 TO 13
GENERATE
Wr[i] = SPIWr & SPIAddrReg[6..0] == i;
END GENERATE;
FOR i IN 0 TO 1
GENERATE
Rd[i] = SPIRd & SPIAddrReg[6..0] == i;
END GENERATE;
Когда связь с МК налажена, можно загружать в регистр периода (или частоты) нужное значение, получая выходную частоту в широком диапазоне. Но пока генератор умеет формировать лишь короткие импульсы, следующие с заданной частотой. Чтобы сделать генератор более практичным, надо добавить возможность получения на выходе импульсов произвольной длительности. Для этого потребуется цифровой одновибратор, который будет запускаться короткими импульсами задающего генератора. Схема выглядит примерно так:
С задающего генератора приходит импульс PlsBeg. JK-триггер при этом устанавливается, начинает формироваться выходной импульс. Одновременно начинает инкрементироваться счетчик длительности WidthCnt. Как только код в счетчике становится равным коду регистра длительности импульса WidthReg, формируется импульс конца интервала PlsEnd, который поступает на вход K триггера и сбрасывает его. При этом импульс заканчивается. В реальности сравнение надо делать «больше или равно», чтобы импульс прерывался, если будет загружена меньшая длительность. Иначе есть шанс зависнуть на время максимальной длительности импульса, а это десятки секунд. На AHDL формирователь выглядит так:
WidthCnt[i][].(clk, clrn) = (GCLK, nGCLR);
WidthOvf[i] = WidthCnt[i][] >= WidthReg[i][];
IF PlsBeg[i] # WidthOvf[i] # !Pulse[i]
THEN WidthCnt[i][] = 0;
ELSE WidthCnt[i][] = WidthCnt[i][] + 1;
END IF;
PlsEnd[i] = !PlsBeg[i] & WidthOvf[i] & Pulse[i];
Pulse[i].(j, k, clk, clrn) = (PlsBeg[i], PlsEnd[i], GCLK, nGCLR);
На первый взгляд, схема слишком сложная для простого формирования импульса заданной длительности. Но тут надо учитывать всякие «краевые» эффекты, когда в некоторых условиях возможны глитчи длительностью в один такт. Вернее, это даже не глитчи, а просто некоторые особенности логики работы. Настоящие глитчи – это короткие (короче периода тактового сигнала) импульсы, которые возникают в результате «гонок» сигналов из-за задержек в логических элементах. Тут с таким сталкиваться не приходится, схема генератора полностью синхронная, все триггеры тактируются единым сигналом GCLK. Никакой логики в цепи тактового сигнала нет, для управления используются входы Enable. В результате никакие «гонки» сигналов или промежуточные состояния многоразрядных регистров не беспокоят. Главное, чтобы все сигналы устаканились к следующему тактовому импульсу.
А проблемы могут быть связаны с логикой работы. Например, для получения импульса нужной длительности из стартового и стопового импульса логично использовать JK-триггер, у него как раз есть для этих целей отдельные входы. Но если период и длительность установить такими, что стартовый импульс совпадет со стоповым, триггер переключится в противоположное состояние, хотя по логике он должен установиться (ведь пришел стартовый импульс).
Еще хуже, если стартовые импульсы будут поступать чаще стоповых. Тогда на выходе триггера появятся импульсы хаотичной длительности. Исправить ситуацию можно добавлением логики на вход K триггера, что сделает вход J приоритетным. Как вариант, можно вместо JK-триггера применить D-триггер, но он тоже потребует дополнительной логики.
Это больше вопрос «дуракоустойчивости», ведь в добром здравии никто не будет устанавливать длительность больше периода. Но доброе здравие – это лишь математическая абстракция. В реальности пользователь может вводить что угодно, даже заведомо неправильные комбинации значений. Запрещать ввод таких значений не всегда представляется возможным, может потребоваться слишком много проверок (например, синхронизация каждого из каналов может приходить откуда угодно). Да и пользователю неудобно, когда запрещен ввод каких-то значений (придется сначала увеличивать период, а только затем длительность, наоборот интерфейс сделать не даст). Поэтому лучше просто принять меры, чтобы при неправильных параметрах поведение генератора было как можно более адекватным. К счастью, сделать машину адекватнее человека не так уж сложно. Когда длительность импульса установлена больше периода, логично ожидать, что импульс станет бесконечным, и на выходе все время будет активный уровень. Все подобные ситуации учтены в приведенной выше схеме.
Для еще большей универсальности генератора полезно добавить программируемую задержку между импульсом запуска и началом формирования выходного импульса. Это пригодится в том случае, если будут использоваться сразу несколько каналов. Тогда выходные импульсы можно будет сдвигать относительно друг друга. Формирование задержки аналогично формированию длительности выходного импульса. Опять возникает вопрос насчет поведения при некорректных параметрах. Что должно происходить, если задержка установлена больше периода? Ответ на этот вопрос не совсем очевиден. Я посчитал, что логичней всего в такой ситуации будет отсутствие выходных импульсов. По крайней мере, это намного лучше хаотичных импульсов.
Схема размножается на 4 канала, получается вполне пригодный для использования 4-канальный генератор. Размножение кода в AHDL делается просто, для этого существует конструкция FOR — GENERATE. В приведенном выше коде i – это и есть номер канала.
На плате входов/выходов есть 4 входных разъема. Чтобы они не пропадали даром, их можно задействовать для внешнего запуска генератора. С входами внешней синхронизации такая же ситуация, как и с портом SPI – каждый такой вход представляет собой отдельный клок-домен и требует применения синхронизатора.
Схема синхронизатора очень напоминает схему фильтра импульсных помех. Там тоже цепочка триггеров, выходы которых объединены по логике «И». Такая схема не будет пропускать короткие импульсы, длительность которых меньше такого количества периодов тактовой частоты, сколько имеется триггеров в цепочке. Подобные фильтры помех есть, например, на входах захвата таймеров в микроконтроллерах AVR. Подключая разное число триггеров в цепочке, можно регулировать минимальную длительность импульса, который может пройти через фильтр. На всякий случай сделал здесь такой же фильтр. Мало ли какой сигнал будет поступать на вход внешней синхронизации, нежелательные «иголки» можно таким способом убрать. Включить или отключить фильтр можно с помощью специального бита в регистре режима. Длину цепочки я сделал 6, но можно сделать какой угодно в зависимости от того, что надо фильтровать.
При работе с внешней синхронизацией мне показалось полезным иметь индикацию частоты, которая поступает на синхровход. Полноценный частотомер реализовывать не стал, а сделал просто измеритель периода, который может делать это с точностью 10 нс. Немного подумав, добавил еще и измеритель частоты, который производит счет входных импульсов в заданном окне. Первый способ дает хорошую точность при измерении низких частот, второй – высоких. Их можно объединить, получив постоянную относительную погрешность для любой частоты, но лень тут этим заниматься – не частотомер ведь.
Обмен по SPI сразу предусматривал как запись, так и чтение. Но чтение до этого не использовалось. Какой смысл читать регистры, которые мы сами загружаем, и которые меняться не могут? Но с появлением измерителя частоты операция чтения стала востребованной. И тут случился великий облом – чтение не заработало. Вообще, я в первый раз в STM32 использую встроенный SPI для чтения. До этого приходилось только передавать по нему данные во всякие внешние микросхемы. Хотя на AVR чтение по SPI неоднократно делал. Там все просто: загрузили данные в регистр данных SPI – они начали передаваться. Как только передались – можно читать регистр, в нем будут принятые данные. По наивности думал, что и в STM32 так же, но не тут-то было. Из SPI читался всякий бред. В который раз получаю доказательство, что STM32 – это не радиолюбительский процессор, с ним всегда куча проблем. Потратил на вылавливание глюка два дня и две ночи (с перерывами на обед, разумеется). Сначала не было уверенности, что проблема именно в STM. Предполагал, что FPGA неправильно отдает данные, ведь SPI в ней самодельный и тоже может содержать ошибки. На моем осциллографе это увидеть крайне сложно, тот редкий случай, когда цифровой осциллограф был бы полезен. Но такое случается не чаще, чем раз в год, поэтому бежать и покупать его вряд ли имеет смысл. Начал писать всякие тесты, параллельно модифицируя код и в STM, и в FPGA. Вроде, на осциллографе смутно вижу, что данные идут правильные. Чтобы окончательно в этом убедиться, временно подключил макетную плату с ATmega88. Конечно же, она приняла данные абсолютно корректно. Получается, собака зарыта именно в STM. С помощью параметрического программирования (когда изменения кода там и тут делаются без всякого понимания, а наблюдается лишь конечный результат) был найден рабочий вариант исходника. Кривой, но рабочий. Так и оставил, выдохнув и разжав кулаки.
В итоге имеем 4 канала автогенераторов, способных генерировать заданную частоту и 4 канала внешней синхронизации. Для большей гибкости, можно подключать каждый выходной канал генератора к любому источнику синхронизации. Можно все каналы к одному, можно к разным. Для еще большей гибкости сигнал внешней синхронизации может иметь активный фронт или активный спад. Или фронт и спад сразу. Для выбора источника синхронизации сделал мультиплексор, который управляется битами регистра режима.
В принципе, на этом можно и остановиться, реализован довольно богатый набор функций для генератора прямоугольных импульсов. Но задача, с которой пришлось столкнуться на работе, требовала большего. Вместо генерации отдельных импульсов с некоторой частотой повторения, должны генерироваться последовательности импульсов (говоря по-другому, серии, или паттерны). Внутри серии может быть несколько импульсов, разделенных промежутками.
Если дать полную свободу, то для описания серии нужно будет слишком много данных, что усложнит программирование параметров генератора. На практике это не надо (по крайней мере, в моем случае), поэтому свободу лучше ограничить. Вариант, который обычно используется в AWG, где форма записывается в память и потом «проигрывается» из нее, мне подходил меньше всего. Требовалась не совершенно произвольная последовательность выходных импульсов, а последовательность в некой сетке.
Строить серию решил из одинаковых интервалов, которые я назвал «шаг» (Step). Для этого потребовался еще один счетчик и регистр длительности шага. Все импульсы начинаются в начале шага и имеют одинаковую длительность внутри серии. Длительность импульсов задается в регистре длительности, как обычно. Пауза между импульсами – это разность между величиной шага и длительностью импульса.
Сам паттерн хранится в специальном регистре, в начале каждой серии его значение загружается в сдвиговый регистр. Если бит равен единице, то на данном шаге генерируется импульс, если ноль – то импульс пропускается. Если длительность импульса установлена равной длительности шага, а импульсы в серии идут подряд, то они сливаются в один длинный импульс. Количество шагов в серии я ограничил до 32. Без проблем можно сделать и больше, но мне даже столько с избытком. Серии в разных каналах генератора можно сдвигать относительно сигнала синхронизации с дискретностью в 1 период тактовой частоты, тут величина шага ограничений не накладывает. Если задать только 1 импульс в серии, то генератор вырождается в обычный генератор импульсов, тогда величина шага не используется. Схему этой части генератора приводить не вижу смысла, она очень специальная и вряд ли вызовет интерес.
Чтобы дать генератору еще больше возможностей, на выходе реализовал объединение каналов по логике «И» и «ИЛИ». Это позволяет получить совсем странные последовательности на выходе. Эти возможности, скорее всего, не нужны, но в самом начале пути я думал, что просто обойдусь логическими выходными операциями без паттернов. Но паттерны пришлось все-таки добавить, а выходную логику при этом убирать не стал, раз уже написана.
Долго думал, как реализовать интерфейс пользователя для задания паттернов. Решил задавать паттерн в виде строки из 0 и 1, но для большей наглядности еще рисовать на экране, какой выходной сигнал в итоге получится. Цифровые значения (период, длительность, задержка и т.д.) задаются с помощью полей ввода.
Внутри FPGA проект занял 3513 логических элементов (LE), что составляет 76% от полной емкости кристалла. Набравшись наглости, я решил попробовать задействовать PLL внутри FPGA и поднять тактовую частоту. Временной анализатор Quartus-а показывает максимальную частоту для проекта примерно 120 МГц (она немного меняется при каждой перекомпиляции в зависимости от структуры проекта). Можно оптимизировать проект по скорости, но я решил попробовать без этого. Подняв с помощью PLL частоту до 200 МГц, я не обнаружил никаких глюков – все работало как следует, обеспечивая очень даже неплохое разрешение по времени в 5 нс. Нагрев микросхемы FPGA тоже незначительный – она еле теплая. Конечно, в серьезных проектах так делать нельзя (но в несерьезных – можно).
Мой осциллограф имеет слишком узкую полосу пропускания для полноценного наблюдения сигналов этого генератора. Однако по падению отображаемой амплитуды импульса можно определить его длительность, даже если она 10 нс (или даже 5 нс). Ниже показан скриншот экрана осциллографа с одним из сигналов, который был получен с помощью этого генератора:
Встроенный микроконтроллер генератора выполняет лишь примитивные функции: полученные по USB коды загружает в регистры FPGA, а также по запросу читает коды из регистров и передает их по USB. Это позволило почти избежать мучительного процесса его программирования. Еще МК по включению питания загружает конфигурацию в FPGA из своей FLASH. По умолчанию записал туда вариант на 200 МГц, но в случае чего с помощью программы с компьютера можно загрузить обычную, на 100 МГц. В программе предусмотрел загрузку конфигурации FPGA из файла в формате .rbf, который генерирует Quartus. Так что можно держать на диске сколько угодно прошивок FPGA под конкретные задачи.
В настройках программы сделал возможность указания тактовой частоты FPGA, мало ли какие будут еще прошивки.
Все это я делал под конкретную задачу, но получилось довольно универсально. Например, можно «нарисовать» пакет для передачи данных в какое-нибудь устройство по SPI или другому последовательному интерфейсу. При этом можно плавно двигать сигналы относительно друг друга с шагом 5 нс. Что еще можно было бы добавить, так это однократное формирование паттерна при нажатии кнопки. Пока этого нет, но допишу при первой востребованности. Тут и так сделано много лишнего.
Программа работает через DLL, в которой реализовал все функции управления. Сделал так специально, чтобы можно было использовать генератор из среды Matlab.
Мораль всей этой истории – когда разводите печатные платы для работы, разводите их так, чтобы потом можно было использовать для чего-нибудь полезного.
Самые обсуждаемые обзоры
+69 |
5197
174
|
+38 |
5618
103
|
+45 |
2938
91
|
+30 |
3137
73
|
Гугл не помог понять суть данного метода.
И с ламинатором проблема решалась совмещением двух кусков
бумагиподложки от самоклейки на просвет, склейки краев и засовывания текстолита внутрь этого «пакета» с последующей «ламинацией», получалось приемлемо, но с приходом jlcpcb забыл как страшный сон. Но как бы вновь вспоминать не пришлось )/(С приходом JLCPCB я тоже обрадовался и шел к тому, чтобы полностью отказаться от домашних плат. Но уже JLCPCB не работает, как и многие другие, остался только Elecrow. Когда его прикроют, будет совсем плохо.
jlc — как собирательный образ китайской заводской платы за недорого
Последний раз (несколько месяцев назад, у меня это эпизодическое хобби) заказывал на pcbwave. Вроде как говорят работает до сих пор. Речь про РФ, но не думаю, что на Беларусь санкции сильнее
Как вариант у них заказывать распечатку и этой пленкой ламинировать
И в целом странные они какие-то, ведь так проще, когда макет нормальный изначально
Можете сказать, что я делаю не так, а я напишу, как делю?
Готовлю исходники в Corel Draw (сохраняю в Ver. 11). Шрифты, разумеется, в кривых. Цвет конвертирую в CMYK. Обычно использую только градации серого, получается все по нулям, кроме K. Но они мне говорили, что каждый цвет печатается 6-ю цветами, даже черный. Делать ли что-то самому с цветоделением — не знаю. Рисунок для печати размещаю в одном слое (называю Print), контур резки из линий hairline — в другом (называю Cut). Внутри каждого слоя всё группирую. Заливку продлеваю за контур резки на 1 мм в каждую сторону. А вот надо ли сразу размножать изображения — не знаю. В последний раз сказали, что можно размножить исходя их ширины поля 1200 мм, длина блока этикеток — до 1000 мм. Тепрь размножаю, раньше просто указывал количество. Зазор между соседними контурами резки делаю не менее 3 мм. Прямо в файле с изображением размещаю напоминалку: «Печать на серебристой пленке. Ламинирование (матовое). Контур резки — синяя линия, находится в слое Cut». Контур резки на закругляю, так как часто нужны прямоугольники. Однажды за это ругались и заставили всю резку скруглить. В последнее время стали печатать хуже: буквы сильнее расплываются, а вокруг контура резки ламинат приподнят (светлая полоска по контуру). Тип пленки тот же — 641. Не знаю, ругаться ли с ними, или они не виноваты. Найти другую фирму пока не удалось, все заканчивается вопросом: какой будет объем заказа? Я отвечаю — 0.5 м^2, после чего говорят, не возмемся. Не понимаю, в чем проблема печатать мало. Да, стоимость выходит чуть меньше 20$ за метр кв.
Да только за такое ТЗ уже скидку бы дал. Уточнить абсолютно нечего. :)
Рекомендую другую контору поискать
Ну и предположения, почему они вредничают.
Скруглять контур, единственная причина этого при некачественном резе прямые углы могут цепляться и лишнюю плёнку сложнее убирать, со скругленными это проще. Приподнятие ламината, видимо с резкой проблема тоже или не аккуратно делали, что он отходить начал.
Претензия к составному чёрному это уже перебор, видимо у них с принтером проблема, к тому же указываете что расплывается всё, печатные головы или не сведены или хана им уже. Свой принтер настраивал так, что пропечатывается белый текст 0,5 мм в чОрном фоне отлично (обычно его чёрным затягивает совсем)
Цветоделение это уже не ваша проблема, ладно бы сложный цвет был, но чёрный.
Раскладывать на ширину рулона, это удобнее для изготовителя конечно, но постоянно уточнять какой рулон (у меня 4 размера сейчас есть) как для клиента оно вам надо?
По поводу составного черного претензии не было, была просто информация, что мой черный они печатают 6-ю цветами, хоть у меня в файле CMYK 0 0 0 100. По поводу ширины — сказали что у них всегда 1200 мм. Поискать альтернативного печатника хотелось бы, но пока не нашел. Поэтому спрашиваю всех: если кто-то знает, кто в Минске берётся за заказы менее 1 м кв., подскажите.
«Свой принтер настраивал так, что пропечатывается белый текст 0,5 мм в чОрном фоне отлично (обычно его чёрным затягивает совсем)» — вот с этим у них проблема, и это больше всего мне мешает. Раньше меньше затягивало буквы черным, сейчас сильнее затягивает. Могу ли я что-то предпринять, о чем-то их попросить, чтобы стало лучше? Или бесполезно, раз такое оборудование?
Вот такое качество (высота шрифта 1.85 мм):
На красном фоне шрифт значительно толще, хоть в файле такой же, как и на черном.
6 цветов, возможно латексный принтер,, обычно можно включить печать чисто чёрным, но надо заморачиваться отдельно же :)
Поищите у кого стоят УФ широкоформатники, они обычно более сговорчивы ))
Вот к примеру было, где конверт высота букв строчных около 1 мм, толщина линии не помню. Кстати, если у «поделки» панели ровные и отдельными частями, как в посте лицевая, очень удобно найти у кого есть планшетные УФ принтеры сувенирный и напрямую прямо на пластик печатать, дороже, но качество уже иное совсем. А стойкости лаком добавить сразу во время печати.
К примеру, прямая уф печать по металлу, тут правда у меня отец с корпусом прикололся по полной, блок тяжеленный xD
А можно пояснить, почему у них заливаются буквы на черном фоне? И что им придется сделать, чтобы это улучшить, если я попрошу? Хотя, скорее всего, меня пошлют с мелкими заказами. Для других они печатают огромные вывески, там качество устраивает. Когда приходил в другую контору, приносил образец наклейки пульта, что выше на фото. Так сказали, что светлые буквы на черном фоне они не смогут напечатать даже с таким качеством. Наверное, это какая-то глобальная проблема.
Что касается УФ, то знакомый печатал так панель магнитофона. Получилось отлично, но денег взяли огромное количество. Я почему цепляюсь за ПВХ пленку — это дешево.
Вот эта панель УФ, качество отличное. Но две проблемы: очень дорого, и делал он это по знакомству, я не знаю, куда обратиться с улицы (и будет еще дороже, думаю).
Полквадрата да маловато, но если сроки у клиентов не горят мы такую мелочевку просто копим и массово потом в печать.
Кратко говоря, открываем карту, ищем у кого есть широкоформат и просто рассылаем запросы с вашими требованиями, а там уже и выбрать можно у кого печататься.
А вот замечание «последнее время качество ухудшилось» и «по краям поднимается» говорит об экономии на инструменте и зарплатах мастеров.
За станок встаёт студент «за три копейки» — и он даже не контролирует остроту инструмента и его износ. Очень хорошо знакомо.
Что такое«конткр обводки»? Что такое «плашка заливки»? Знаю только плашку для нарезания резьбы на стержне.
У Корела есть неприятность, про которую многие не знают, или забывают — при отрисовке любого нового элемента его „контурная линия“ сразу есть — и она ненулевой толщины, имеет цвет (обычно как раз чёрный) и расположена „поверх заливки“.
Для мелких элементов дизайна это недопустимо, приводит как раз к описанному Вами браку на мелких шрифтах.
Обычно в Corel по умолчанию Outline тонкая (Hairline). Я или отключаю ее, когда не нужна, или задаю определенную толщину.
Если для Outline поставить галочку Behind fill, то вокруг объекта останется видимой половина толщины линии. Чем это отличается от ситуации, когда линия сверху, но вдвое тоньше?
Я так понимаю, линию предлагаете сделать для того, чтобы край объекта выглядел более резким? Это не всегда красиво, картинка получается типа перешарпленной.
Наверное, это «секрет» из юмористического рассказа — как в деревне кто не умел патефон заводить. На дачу приехал «уникальный специалист » в виде студента, стал монополистом и заважничал.
А потом в деревне появился мальчишка. Который быстренько всю деревню научил обращаться с патефоном.
www.ozon.ru/product/plenka-dlya-laminirovaniya-80-mkm-s-teksturoy-iskry-razmer-a4-10sht-1322356228/
Я про что говорю: вот оно похожее — на озоне, как и спрашивали (по цене сориентироваться, поискать аналогичное и т.д. и т.п.).
Т.е. ссылка опровергает заявление «Купить невозможно», «в розницу не продают».
А по фактуре — я бы сказал что по фото неподготовленный человек вряд ли отличит слабомаркое от ещё менее маркого.
Кстати, Вы хорошую идею подкинули: можно будет попробовать матовую (и т.п.) плёнку для ламинации стекол(которую мне есть откуда взять).
По факту можно обычной матовой закатывать, в сравнении с глянцем гораздо менее маркая и не бликует
Не планируете выложить исходники? :)
Но подход к проектам — порадовал.
«Яндекс» — аналогично. Поискал тут — не нашёл.
Поискал также тут.
Ну вот что вы с автором творите?! Мне уже выходить давно надо, а я тут сижу, ищу логотипы вузов!
Ну, относительную — все таки когда мы начали альтеровские плисы использовать, мне около 40 было…
И мы очень активно все это использовать начали, даже парню под разработку ПЛИС купили крутой комп: 486DX4-100 и аж 128 мегабайт памяти… :)
Что позволило, в результате, сделать кусочку от обзора задней полусферы СУ-27 раза в 3-4 меньше и в несколько раз более функциональным :)
128 мегабайт RAM это даже на P3 было весьма достойно. В типовом домашнем ПК было 64.
У меня в это время на компе рабочем как бы не 2 было, ну, может, 4…
Объём физической адресуемой памяти: 4 Гбайт — это из вики
А винчестеров на такие объемы не припомню, чтоб прямо кратно степени двойки.
20 — помню, и 200 — помню, 128 — не помню, хотя, может, и был такой…
Где память возьмете? Там вроде еще SIM стояла…
Про диски много не помню, в 98-м брал уже себе фуджицу на 3.2 ГБ и стоил он тогда около $100.
А затем комменты:
Ого, круто.
Да, обязательно куплю себе такую.
Покопался в гаражном хламе и нашел такую же печь. Завтра буду плавить сталь
:D
Здесь все-таки вполне стандартный набор для любителей побаловаться с электроникой.
Платы нынче можно заказать за пару баксов, usb-uart стопудов имеется, stm'ка тоже найдется. Докупить плиску и рассыпуху на алике и все необходимое будет. А с учетом качественной документации в этой статье, получается отличный проект для самоделки. Причем, не очередная мигалка-метеостанция, а вполне себе полезный девайс
Раньше на LCSC и правда можно было со стартовым бонусом заказать очень дёшево. Потом выросла доставка, потом вообще перестали пересылать в РФ.
Но вообще, конечно, $8 — тоже очень дёшево.
Как я понимаю, в РФ они доже отправляют. Надо попробовать.
не моей, я лишь покупаю.
Сейчас, зачастую, это более доступный источник «компонентов», причём, это готовые изделия, которые можно применять и «как есть», и вместе с чем-то — например, для быстрого прототипирования, решения какой-то одной задачи и т. д.
Но, крепитесь! Я Вас понимаю, но это, все-таки, не самый тяжелый случай! Бывает и хуже:
Поскольку домашней мастерской у меня нет, то использую только шуруповёрт, надфили и тп.
Отверстия в алюминиевой панели сверлятся тяжело, получаются со смещением. Отверстия с защитой от прокручивания вообще не понимаю как сделать.
Когда накручиваешь лицевую гайку (на переключатель, например), то обязательно будут кольцевые царапины вокруг.
Технологию печатной лицевой панели не освоил. Использую принтер для мелких наклеек
По отверстиям (да и вообще по всему, где хочется аккуратности) — спасет только труд. В каждое аккуратное отверстие надо вложить труда в 10 раз больше, чем в обычное. Сначала размечается и слегка накернивается центр отверстия. Затем циркулем-измерителем царапается окружность — контур отверстия. Затем внутри сверлится отверстие меньшего диаметра, с таким расчетом, чтобы даже при смещении сверла не выйти за контур. Потом отверстие доводится до контура круглым/полукруглым надфилем (кривизна поверхности надфиля должна быть близка к ривизне окружности). Панель закрепляется горизонтально, движения надфиля — вертикальные. Очень важен свет, его угол надо подобрать так, чтобы царапина контура была контрстной. После надфилей получается почти идеал, но можно еще пройтись разверткой. Фигурные отверстия делаются точно так же, только там будут использоваться еще и плоские/треугольные надфили. Если говорить конкретно про алюминиевые панели Gainta, то их лучше сразу выбросить и вырезать такие же из нормального сплава, например, Д16Т. Иначе они могут отбить тягу к творчеству на всю жизнь.
Гаек на панели лучше вообще избегать. Иногда не получается (для разъемов, например), тогда надо просто закручивать аккуратно. А для переключателей или регуляторов гайки не должны быть видны. Они должны быть под ручкой. Ручки должны быть утоплены в панель (делается большое отверстие для ручки, сзади к панели добавляется второй слой).
Наклейки на панели лучше всего заказать у рекламщиков. Любой город обклеен рекламой, ее где-то печатают. Можно и на принтере, у меня часть приборов сделана так. Но тут критически важен шагреневый ламинат, где его взять — не знаю. Сам добыл чисто по случайности (знакомству).
Ну и главное — надо много думать о конструкции. С ней в голове ложиться спать, с ней вставать. О ней думать в метро и на работе. Записывать появившиеся мысли во время еды и прогулки. А то, бывает, люди жалуются, что красиво не получается, а потом оказывается, что с мыслями о конструкции человек как следует и не жил.
Електрический гравер лучший вариант, называют как правило «Дремель» ;)
Для вас там все элементарно. А многим будет интересно и полезно
Лаборатоная, кажется, по усилителям, кроме стандартных приборов — всяки стенды самодельные.
И вот один такой стенд немного смахивает на летающую тарелку на постаменте.
Препод рассказал, что, когда студент, сделавший этот стенд, руками гнул железку эту — народ сбежался посмотреть.
Студент в школьные времена в авиамодельном кружке провел, и руку набил на обтекаемых формах :_
Вообще, с цветом проблемы. Невозможно заранее сказать, как какой цвет будет выглядеть на пленке. Я даже напечатал пробники на серебристой пленке градачиями серого. Есть шальная идея напечатать на пленке всю панель для Олимп-005 (потому что это намного дешевле шелкографии или УФ), но трудно будет совместить все отверстия на таком размере. Да и разрешение печати хотелось бы получше. Что-то в последнее время с этим всё хуже, может расходники стали плохие.
Даже 300 dpi вам должно хватить, это разрешение, с которым обычно печатаются иллюстрации в журналах.
А интерьерная печать нынче и начинается, по хорошему, от 720 dpi…
А про размер вообще не понял — что значит трудно совместить отверстия?
Нет, если рисовать, что вот это отверстие от края 100мм, следующее от него — 72мм, следующее от второго…
То да, может (и получится) откровенная лажа.
Делайте замеры от реперных точек, от края, к примеру, и все будет хорошо.
В том же кореле нарисовать недолго, в общем то.
Даже можно фото подложить и сверять по нему.
Что касается совмещения — точный рисунок в Corel у меня, разумеется, есть. Но пленка при наклейке тянется, на большой панели получить совмещение не выйдет. А при хранении пленка сама усаживается, размер уменьшается (чего нет с полиэстером). Даже на маленьких панелях я часто не режу отверстия в пленке в размер, а заказываю чуть меньше. А после наклейки увеличиваю их надфилем, используя саму панель как шаблон. В общем, пленка — это такая себе замена шелкографии.
Тем паче что это не лазерная печать, струйная.
И разрешение 1440 — не редкость.
Да и по краям вроде нормально с изображением.
Насчет того, что пленка тянется…
Да, она тянется.
Собственно говоря, единственное, что в голову приходит — использовать монтажную пленку.
Это та, которая используется для переноса вырезанных элементов изображения на положенное место, вот такая, к примеру:
Она практически не тянется, и пленка не растянется.
Типа перенести жесткую основу с клеевой стороны на другую :)
Вроде должно помочь…
Совсем разные разрешения используются для наружки и интерьерки, да и материалы для наружки зачастую используются такие, что там никакое разрешение не может — эти материалы на него и не рассчитаны, для наружки разрешения 75-150 дпи — за глаза, их же издалека смотрят…
Кстати, если перед наклейкой ее заламинировать — мне кажется, хрен она тянутся будет…
Основная проблема в другом — качество печати не очень. Чуть выше Giga выкладывал пример, как печатает на пленке он — так это идеал. Жаль, что найти такое место непросто.
Честно говоря, я так панели никогда не делал, да я и так себе очень редко что-то делаю.
Мы как то, в тех же 90-х, для приборчика одного заказали передние панели на самоклейке, под конрадовский корпус, были варианты прям с углублением для наклейки.
Во что это обошлось я хз, но сделали хорошо: сам материал хрен порежешь, если приклеил — хрен отдерешь, изображение — внедрено в глубину наклейки.
Что-то типа этого, только в той версии еще лейбла не было:
Всё упирается в экономику. В моем случае на панели можно сделать шелкографию или УФ-печать, будет идеал. Но за такие деньги не надо. Хобби — штука в общем дорогая, а в жизни бывают периоды, когда на лишнее нет денег. И от хобби остается лишь небольшой кусок, где можно что-то делать из мусора.
Мы первую, пробную партию заказали то ли сотню, то ли две, еще не зная, пойдет она нам или нет.
Пленка вот такая — Avery Zweckform 210x297 мм (L4775-20) Бывает и листами, бывает и готовыми этикетками уже прорезанным.
З.Ы. Про жирность от рук, мне это не итересно, мне итереснее сохранность надписей в долгосрок, при неблагоприятных условиях. У человека кто присоветовал, на аутдоре эти наклейки за 5 сезонов читаються нормально… Ну они конечно не мелкие…
З.З.Ы. Идеально конечео твухцветный пластик, с надписями выбраными фрезером. Вот это вечно для моих условий… Но там поблема с цветом и проблема с бюджетом, очень очень редко это использую.
Для панелей жирные пятна — это приговор.
Двухслойный пластик пробовал, его гравируют лазером. Нормально, но вид своеобразный.
З.Ы. я а3 цвет брал под печать проектов, так как «мартышка зрением слаба с годами стала» ))) ну и брал я естествено не новый и практически по цене металалома. Вот привести его в божеский вид, и купить к ниму родные расходники вот это да… Но зато я по лазерной печати закрылся до пенсии)))) С моей потребностью я помру быстрее, чем в нем картриджи закончатся)))
Принтер у меня HP LJ1200, надеюсь, хватит не до пенсии (которая скоро), а до самого что ни есть конца.
fotobumaga.by/shop/fotobumaga/lomond/samokleyashhayasya-prozrachnaya-plenka-lomond-a4-10l/
типа такой, прозрачная и белая в основном. конкретно эта подойдет для наклеек. если самому — печатать только пигментом, т.к. водянка выгорит
а по цвету нужен спектрофотометр -печатать плашки и делать профайл для пленки, но никто же парится не будет бесплатно.
хотя можете попробовать у Михаила отпечатать, у него отстроенное по цвету оборудование.
контакты тут koler.by он может и распечатать, но основной профиль именно профилирование
Да и если напечатать этот цвет — разница будет, в основном, из за материала.
Но все равно хрен его знает, по цвету попадете, к примеру, а изменилось освещение — и нет попадания.
Материал разный…
А 100-0-0-0 будет скорее серым на бумаге или пленке.
Если, конечно, вы не печатаете на черной бумаге.
П.С. Тележки, наверное нет.
Как бы не был хорош прибор но к сожалению с такими характеристиками в 2024 он морально устарел и не один раз. Всякие дешманские погремушки типа «мультиметр- осциллограф» от тех же fnirsi (2C23T) будут как минимум не хуже по параметрам. Я уже молчу про комбайны от RIGOL например MSO5000 серии можно купить самый дешёвый вариант на 70Мгц и 2 канала а после разблокировок получить 350Мгц 4 канала + 2 канала генератор сигналов + логический анализатор + фишки с измерениями типа автоматического построения АЧХ ФЧХ.
На эту фразу я мягко намекнул что прибор родом из 87го в 2024 будет немного «неактуален».
Нет, конечно. Но вы будете на какие-то моменты тратить меньше времени, значит, его останется больше для чего-то более важного.
Удивительно, что вам еще никто из знакомых не предложил подарить какой-нибудь старый (но новее вашего) осциллограф…
Еще вариант — сделайте сами. Умея обращаться с ПЛИС это как два байта переслать — лишь АЦП прикрутить и быструю память.
Хотя, смотрю я на ваше фото и, похоже, к саге вашей вы руку-то уже приложили. По описанию у неё 10 МГц полоса и 50 нс фронт. У вас же четко видно, что фронт 15-25 нс, а полоса, похоже, простирается даже выше 20 МГц. Как будто входной усилитель там уже совсем другой, и всё упирается в высоковольтный каскад.
Некое подобие цифрового осциллографа я делал лет 15 назад — быстрый АЦП, ПЛИС, память. А позже для другой задачи делал front-end с полосой 100 МГц. Это всё не проблема. Но вот софт для компьютера (или для вывода на местный дисплей) я не напишу. Это далеко не два байта переслать, работа на годы.
Мне вот проще будет изучить новый язык программирования, пусть даже функциональный, чем придумать нормальную качественную входную схему.
Программирование МК сильно проще. Зачастую тут не просто не нужны ООП, классы, шаблоны, паттерны и т.д., а даже вредны, т.к. всё это занимает дополнительную память и быстродействие, которые в МК ограничены. Также нет аппаратной многопоточности (за исключением некоторых МК), что сильно упрощает программирование, т.к. убирает необходимость синхронизации. Остается чистый алгоритм, разбитый лишь на вызовы функций. Бери, да пиши. Наверное, поэтому в индустрии зарплаты разработчиков МК ниже, чем обычных программистов.
Не так уж и надо. Сейчас такие IDE, что обеспечивают легкую и комфортную навигацию по коду. А если в коде еще и разбираться не надо, т.к. он написан вами же — это просто сказка, а не программирование.
Про вредны — это миф. Никто не заставляет использовать те приемы, которые слишком тяжелые для МК (исключения, например). Но те же шаблоны позволяют получить очень эффективный код. ООП позволяет лучше структурировать исходник, что более важно, чем экономия ресурсов МК. В программировании многое приходится делать в ущерб эффективности, но для повышения читаемости. И то человеку трудно разбираться в коде, что более негативно сказывается на результате, чем большая загрузка МК.
У меня настолько плохая память, что не могу запомнить функций IDE. Не пользуюсь практически ничем, кроме простого поиска. В общем, для программирования профнепригоден.
Вовсе нет. У каждого программного решения есть своя «цена», поэтому применение или неприменение того или иного решения всегда определяется аппаратной частью и конкретной задачей.
Смотря для чего их использовать. Если, например, для костыля с целью изобрести рефлексию, то такой подход априори провальный. А универсальное выполнение одних и тех же операций с разными типами данных на МК, как правило, не нужно. Особенно, если речь идет про слабые контроллеры типа AVR.
Во-первых, что именно более важно — зависит от конкретной задачи. Не зная её рассуждать о важности попросту нельзя. Во-вторых, вы можете и без ООП все хорошо структурировать — в конце концов, был же чистый С, писали на нем код.
Я бы сказал, что обратное утверждение более верно, чем ваше, иначе бы не писали ассемблерные вставки.
Лукавите. Причем, откровенно. Вы же выкладываете ваш код — нельзя сказать, что он всегда оптимален, но и индусским его тоже не назовешь. Особенно, если сравнивать с тем, что есть, например, в ардуино — там просто свалка. Так что искренне не понимаю, зачем вы так говорите.
Да, компиляторы сейчас оптимизируют лучше, чем раньше. Особенно хорош в этом плане IAR, там такой код получается, что лишь позавидовать можно. А вот GCC для AVR в этом плане слабоват. Но, вот ответьте — для чего вам в коде работы с портами шаблоны?
Это заблуждение. Особенно, если речь идет про слабые МК типа AVR. Возьмите хотя бы ардуино и поковыряйте, там достаточно ассемблера.
Ну, прямо как в анекдоте — или крестик снимите, или трусы наденьте :) Если это не ваше, то откуда убежденность про то, какой язык подходит лучше? И про ассемблер?
Странный вопрос, особенно от специалиста по C++. Удобство, наглядность, эффективность.
Слабые МК сейчас вымирают. Даже я, уж как не люблю избыточность, но даже в простейший декодер ИК на 9 команд поставил 32-разрядный процессор. Просто потому, что сейчас он доступней и дешевле, чем AVR.
Ну так общаюсь иногда с настоящими программистами. Утверждение, что C++ не подходит для МК, у них вызвало бы только смех. Сейчас тенденция — плевать на производительность, плевать на расход ресурсов, лишь бы программисту было проще. И это правильно. Потому что всё упирается не в железо, а в человека.
А можно конкретный пример? Или ссылку на код хотя бы.
Вымирают. Но, например, у меня еще есть несколько 328-х атмег, 13-х и 85-х тинь, не выкидывать же их? Поэтому ставлю по возможности туда, где хватает. Да, программировать их сложнее, приходится какие-то куски писать на ассемблере, но мне это интересно и приносит удовольствие. Как вам нравится, когда отверстие в передней панели сделано идеально, и хоть это и занимает в 10 раз больше времени, вы всё равно делаете его надфилем, так и мне нравится, когда ресурсы МК используются полноценно.
А я разве сказал, что не подходит? Мои слова были «зачастую вредны» и обоснование — ресурсы. Решение надо подбирать под задачу. А радиолюбительские задачи обычно не сверхсложные.
Это не программисты. Это туристы, вчера продававшие телефоны в «Евросети», а сегодня закончившие скиллбокс и пытающиеся выиграть в конторской фаллометрии. И нет, они не обязательно молодые — помню, собеседовал кандидата 45+, он ранее что-то там на АЭС программировал. Так он даже не знал сложности алгоритмов сортировки — говорит: «Да зачем мне это? Я вот функцию qsort использую, а как она внутри работает, мне не важно». В такие моменты становится действительно страшно за то, что он мог на АЭС на(ш)кодить.
Мы разве уже перенеслись к обсуждению производства? В хобби нет KPI и не нужно экономить человеческие ресурсы. Потому что хобби делается для удовольствия, и чем дольше это удовольствие будет — тем лучше.
Вы же часто жалуетесь, что программировать сложно и удовольствия это вам не доставляет. И тут напрашивается логичный вывод — может тогда перестать слушать «настоящих программистов» и попробовать иной подход?
Да любой мой исходник из свежих. Начал использовать C++, когда начал применять STM32. Но увидел, что это очень удобно, поэтому и для AVR стал писать на плюсах. Например, вот исходник процессора лабораторного БП.
Тоже любопытно, где это надо, какой-нибудь конкретный пример. Я много лет программировал на asm, сначала MCS-51, потом AVR. Но когда перешел на C, ни разу не понадобилась ассемблерная вставка. А для STM32 я вообще не знаю ассемблера.
Ресурсы никак не зависят от языка, а зависят от того, какие именно конструкции применяет программист.
Как раз это программисты, причем работающие в солидных компаниях. А таких, кто будет ковыряться с ассемблерными вставками, оттуда быстро выгонят.
Да, выше было про индустрию. В хобби, конечно, каждый может сходить с ума как ему хочется. Тут лишь бы нравилось. Раньше мне нравилось экономить ресурсы, долгое время писал на asm. Но чем дальше, тем труднее стало разбираться в собственных программах. Понял, что иду в тупиковом направлении. И теперь я делаю всё для читаемости, наплевав на всякую экономию.
Так подходы современных программистов как раз и направлены на получение удовольствия от программирования без оглядки на производительность. Как раз подходит и для хобби. Вполне в стиле Arduino.
Что касается области видимости — согласен, дополнительных ресурсов она не требует. Но только для домашних проектов, которые пишет один человек это не так актуально, ведь единственный автор в любом случае полностью контролирует весь код, а, значит, понимает, что для внутреннего использования, а что для внешнего. Кроме того, иногда нарушение границ видимости приводит к уменьшению/ускорению кода, это, опять, же к вопросу производительность-читабельность.
Иногда это и есть наиболее оптимальный вариант, ведь вы полностью контролируете процесс и порядок инициализации. Если, например, использовать классы, но не использовать менеджер памяти и объявить их глобальными переменными в разных юнитах трансляции, порядок вызова конструкторов определит компилятор, и он может оказаться неверным. Определение же классов в одном месте может оказаться неудобным с точки зрения программы. С другой стороны, последовательный вызов функций инициализации дает читателю полное представление о том, какой именно код и когда вызывается, то есть, что тут лучше — вопрос тоже неоднозначный.
А это и без классов можно, кстати)
Абсолютно верно! То есть, если предполагается иметь несколько сущностей одного типа в программе, то следует использовать классы. А вот если сущность 100% одна (а в случае МК это бывает часто), можно обойтись и без них.
Все правильно, ведь ардуино — универсальный фреймворк. Это как большая библиотека, там без классов никуда. Но только ардуино ни разу не про производительность, чего только стоит DigitalWrite.
И используете виртуальные функции? Вот это я, прежде всего, и имел в виду, когда говорил про «фишки» С++ и их стоимость. Например, в AVR есть ОЗУ и ПЗУ, и ПЗУ имеет совершенно другую адресацию. Часто хочется сделать базовый класс чего-то, например, экрана приложения, а от него уже унаследовать конкретные классы-потомки, и всё это разместить в ПЗУ. Но в С++ нет понятия типов памяти, поэтому компилятор не может использовать таблицу виртуальных функций напрямую из ПЗУ, а делает «ход конем» — размещает её в ПЗУ, но в стартовом коде копирует её в ОЗУ. То есть, использование виртуальных функций занимает как лишние ресурсы, так и память, которой в AVR и так «кот наплакал». А вот на STM это всё не нужно, и можно использовать как есть (понимая, конечно, что вызов виртуальной функции — это лишнее обращение к памяти).
Здесь на помощь, кстати, могут прийти шаблоны — можно сделать базовый класс шаблонным от класса-потомка, тогда он сможет вызывать функции потомка без «виртуализации», так сейчас часто поступают и в программировании на ПК. Но для МК тут есть свой минус — разрастается код, т.к. для каждого типа потомка приходится генерить свой отдельный кусок кода базового класса. Но если потомок в проекте только один (скорее всего, в случае с вашим протоколом это именно так), то такой вариант может оказаться рабочим.
А вот это — чисто ПК-шный подход. Да, код читается легче, можно каждый пункт в своем файле разместить, но с точки зрения получаемого кода будет хуже.
Планирую выложить сюда статью, как закончу проект, там подробно всё опишу, исходники размещу на гитхабе. А если кратко — есть экран 240х240х16 бит = 112.5 КБ с интерфейсом SPI. Максимальная частота работы SPI на AVR — это 1 байт за 18 тактов. На экран надо выводить линии, прямоугольники и текст, соответственно, для достижения максимального быстродействие в SPI надо подавать байты ровно через 18 тактов. Быстрее нельзя — передача собьется, медленнее можно, но не желательно, т.к. это потеря производительности, а данный экран и так тяжеловат для AVR. Написать код, который удовлетворяет этим условиям можно только на ассемблере. Особенно, если речь идет про вывод символов — там не код, а, практически, произведение искусства :)
Ну, и еще пример — понадобился мне сдвиг 32-разрядного числа на 12 бит. Казалось бы, задача простейшая. Но нет, GCC сделал её 12-ю операциями сдвига! 12-ю, Карл! Ладно, я понимаю, не умеет он нормально сдвигать на 4 разряда, но уж на 8-то можно сделать пересылкой данных, правда? В итоге, его код занимает 84 такта, а мой ассемблерный — 9. Как вам разница?
Ну, а что — в солидных компаниях сейчас тоже далеко не все программисты пишут нормальный код. Вот недавно только ревьювил пиар, там был словарь, который пополнялся по мере прохода алгоритма, а потом для каждого элемента другого массива осуществлялась проверка, есть ли данные в словаре. И что вы думаете, изначально словарь сделали std::vector'ом, и, соответственно, трудоемкость была O(N²). Хотя исправление на std::set заняло даже меньше кода, т.к. существует set::count().
Да, опять же, от задачи зависит. Сейчас на асме на работе сам не пишу, но у нас есть команды, где пишут. А на одном из предыдущих мест была задача выводить растровую графику с некоторой обработкой в процессе вывода. Мой коллега написал код на плюсах, и он работал, но весьма медленно. Вывод растра превратился в покадровое слайд-шоу. Я переписал основной цикл вывода на асм с использованием SSE и производительность возросла примерно в 10 раз! Когда мы демонстрировали результат одному из клиентов, он долго смотрел, после чего задал нам вопрос: «а почему она (программа) у вас так быстро работает?» Но есть и downside — тогда программу писали исключительно 32-разрядной, а теперь из-за ассемблера её никто там не может на 64 бита перевести :)
Через пару месяцев я уже совсем другой человек :)
Для порта — нет. Но виртуальные функции используются в том же проекте БП в меню в роли обработчиков событий от энкодера и клавиатуры. Да, с ними есть накладные расходы, но речь про проект на STM32. Для AVR тоже использовал виртуальные функции, но буквально пару раз. В обработчике клавиатуры (чтобы поддерживать как местную клавиатуру, так и ДУ). Можно обойтись и без виртуальных функций, но в количественном выражении зло от них минимально, особенно в интерфейсе пользователя, где скорость не нужна. Память — это отдельный вопрос, на младших AVR ее действительно мало, приходится ужиматься, все время волнуясь насчет достаточности размера heap.
Тут явная ошибка в выборе МК.
У меня был случай, надо было перевернуть биты в байте, когда использовал UART в режиме SPI. Сначала сделал на Си по классике.
А потом посмотрел, что в системе команд ARM есть специальная команда RBIT, которая одним махом реверсирует порядок битов в 32-разрядном слове. А компилятор предоставляет к ней доступ через intrinsics-функцию __RBIT. Переделал. В работе программы ровным счетом не изменилось ничего. Только на душе стало чуть светлее :)
Нельзя рассматривать код оторванно. Главное — это решена ли задача в срок. Ловить такты и экономить байты надо в редких случаях. Например, в очень большой серии, где на процессоре надо экономить каждый цент. А если радиолюбитель хочет дома сделать, например, гирлянду с бегущими огнями, то он вполне может отжалеть 4$ и купить в качестве процессора, к примеру, платку BlackPill. Где процессор на 100 МГц с DSP-инструкциями и FPU на борту. Возможно, желание делать ассемблерные вставки тогда отпустит :)
Минимальное зло тут, минимальное там… и вот уже 32 КБ занято, приехали. Бинарники на МК растут весьма быстро по отношению к их ПЗУ (на ПК тоже, но здесь всем всё равно).
Нет. Это был осознанный выбор. Во-первых, всё же, AVR пока еще более распространен у радиолюбителей (а я немного надеюсь, что хоть кто-то повторит проект или его часть), чем СТМ и, особенно, IAR. Во-вторых, у меня еще есть атмеги, поэтому если проект реализуем на AVR, я стараюсь использовать их. Ну, и, в-третьих, на СТМ это не так интересно — код на modern С++ и без жесткой оптимизации по перфу я пишу на работе, для себя интересно именно писать высокопроизводительные программы.
По классике — это lookup table. Быстро на любой архитектуре и для байта относительно «недорого» по ПЗУ/ОЗУ. Но разве в СТМ нельзя указать, в каком порядке биты передавать в порт?
Да, они молодцы, битовые команды бывают очень полезны. Использовал её в своем коде ФФТ для изначального перестроения массива. Также там есть еще очень полезная команда CLZ.
Не только. Задача должна быть еще решена качественно, чтобы потом не потонуть в фиксе багов.
Специально ловить и экономить — да. Но стараться писать сразу оптимальный код надо всегда.
Да можно и Orange Pi сразу купить, а весь код написать на питоне :) Вопрос целей и интересов. Если цель — быстрее что-то слепить, лучше взять ESP, там и WiFi сразу будет.
Качественно писать на асме под RISC значительно сложнее, а если конкурировать с компилятором IAR, то еще х2 более сложно. Да и в обычной жизни это не нужно — четкой растактовки команд нет, а 32-битная архитектура, «бесплатные сдвиги» и аппаратное умножение/деление позволяют компилятору не «тупить» с перестановкой регистров и, таким образом, генерировать более адекватный код. То есть, эффект от ассемблера становится не так заметен. Это не АВР, где без асма никуда.
Тем не менее, сами ST выкладывали ассемблерную реализацию Radix-4 FFT, емнип, она была в полтора раза быстрее.
Это так, но использовать его надо адекватно, а не для таких дисплеев.
Вполне логичное и достаточное объяснение. Когда что-то нравится, вопрос адекватности решения или полезности его для других не имеет значения.
Нельзя для USART в режиме SPI.
Глянул — считает лидирующие нули. Пока не представляю, где это нужно.
Я бы так не сказал. Зачем нужна оптимальность кода сама по себе? Процессор чаще всего крутит пустые циклы от нечего делать, и память не всегда занята под завязку. Надо писать сбалансированно — в меру оптимально, в меру — читаемо. Очень часто в программе делаю что-то явно не оптимально, но более понятно.
Тоже спорное заявление. После перехода на Си на AVR я реализовал более сотни разных проектов, и ни строчки asm. Если мне не интересно писать высокопроизводительные программы, то вполне можно этого и не делать.
А тут я написал код, который за один проход и символ рисует, и задний фон заполняет. То есть, он может одну строку текста заменить на другую без какого-либо мерцания. Смотрится отлично, для моих целей быстродействия достаточно. А то, что при переходе на другой экран я перерисовку вижу — ничего страшного, не так часто ведь по экранам бегаешь.
Кстати, код вывода всё равно бы пришлось свой писать, т.к. в ардуино сделать закраску фона во время вывода символа они просто не смогли, там даже комментарий на эту тему есть. А каким бы быстрым не был МК, если сначала закрашивать фон, а потом рисовать новый символ, будет мигать. Вот это считают неприемлемым.
Так какие-то трудности тут возникают только у автора. Желающим повторить будет даже проще, они возьму МК, соберут схему и зальют готовую программу. А автор таких трудностей не боится :)
Я использовал в коде вычисления целочисленного квадратного корня по алгоритму Ньютона. Отлично подходит для выбора первоначального значения. В итоге, у меня код занимал ~55 тактов (на СТМ) и давал погрешность максимум 1 LSB.
Это как выбрасывать мусор в урны. Зачем выбрасывать в урны, если есть мусор, который может перегнить и под деревом? Это называется чистота кода, и поддерживать её следует, прежде всего, по тем же самым принципам, что следует поддерживать и остальную чистоту.
Я считаю, что оптимальный код, в основном, также хорошо и читается — если, например, вы выкинули из кода несколько условий и сделали его выполнение более прямолинейным, читаться он тоже станет проще. Я не люблю частные случаи — они усложняют как выполнение, так и чтение программы. Если же оптимизация действительно делает код неочевидным, я добавляю комментарий.
У нас совершенно разные подходы к программированию. Вы пишете программы из необходимости, я — потому, что мне это нравится. Соответственно, и совершенно разный результат.
Ну хотя бы тем, что надо сильно напрягаться, программируя эту связку. И наверняка будет видна перерисовка экрана. Пусть это происходит редко, но впечатление уже не то. И самое главное — зачем на это тратить свое время? Почему не взять другой процессор (по цене будет то же самое)? Объяснение возможно одно — нравится. Тогда возражать нельзя.
Я думал, всегда так делают. Из таблицы фонта обычно читаю символ, просматриваю его попиксельно, если пиксель = 1 — рисую его цветом Color, если = 0 — цветом BgColor. Т.е. при выводе текста не требуется предварительное стирание. Только надо следить, чтобы длина строки была такой же, иначе останется хвост старой. Приходится короткие строки добивать пробелами.
Или речь идет о тексте не на однородном фоне цвета BgColor, а на фоне какой-то графики? Тогда без чтения видеопамяти или без копии экрана в ОЗУ никак.
При работе с монохромными дисплеями похожая ситуация. Там в одном байте несколько пикселей. И если надо поменять только часть из них, как оставить остальные без изменений? Чтения видеопамяти по SPI или I2C часто у дисплеев нет (на SSD1306, например). Да и медленно было бы это. Поэтому приходится сначала рисовать в памяти, а потом копировать побайтно измененную часть экрана в дисплей. Контроллер нужен с довольно большим ОЗУ, с младшими контроллерами — полный тупик. Ну или дизайнировать экран так, чтобы строчки были в отдельных байтах, но это существенное ограничение свободы.
Что-то я не могу понять, о каких трудностях речь. Если в символе фонта есть точка, рисуем ее цветом текста. Если нет точки, рисуем ее цветом фона. Можно, конечно, не рисовать, но зачем? Если только нужна поддержка для текста режима «Transparency».
Автора жалко :) Агитирую не тратить жизнь на ерунду, она короткая. Меня тоже часто агитируют, но редко слушаюсь :)
Вот тут может быть разночтение. Чистота кода — это прекрасно, но под этим я понимаю прежде всего его логичность и красоту для человека, а для машины он может стать менее эффективным.
Не всегда. Хорошо читается код, где навернута куча уровней абстракции, как листьев на капусте. А эффективный для выполнения код выглядит в общем случае нечитаемо. Конечно, можно придумать ситуации в поддержку как «за», так и «против».
Вот тут в точку. Терпеть не могу программировать. Но без этого — сейчас никуда. Поэтому пусть машина больше думает, но мне должно быть как можно проще.
У меня был в жизни интересный случай. Когда-то очень давно, почти 25 лет назад, делал я генератор прямоугольных импульсов полностью на AVR (только выходной каскад снаружи). Тогда еще писал на ассемблере, а доступен был лишь камень 2313. В общем, всё написал, там код был очень критичный к времени выполнения, от этого зависели максимальные параметры генератора. Но какие-то сервисные функции не влезли — память была битком. Один человек из Интернета, который подписывался как Andre Birua, взялся помочь. Исходник — один файл, там всё перемешано, всё оптимизировано. И вот он в этом чужом (моем) исходнике нашел большое количество возможностей дополнительной оптимизации. Причем с помощью таких приемов, которые я бы не придумал никогда. В итоге генератор получил совместно сделанный исходник и все нужные функции. Его можно найти поиском по названию PG-760. Но я увидел, что совершенно не могу программировать, не получается у меня придумывать хитрости, которые с легкостью придумывал другой человек. А раз не получается, как это дело можно любить?
Можно на время перерисовки отключать дисплей. Будет гаснуть, рисовать, появляться. Но меня не напрягает особо, т.к. в обычной эксплуатации устройства смена экранов будет нечастой.
И да, и нет. Посмотрите библиотеку ардуино Adafruit_GFX_Library/Adafruit_GFX.cpp — там прямо вот такой коммент:
Я у них взял шрифты, чтобы самому не изобретать велосипед. Дело в том, что у них хранение символа чуть другое — хранится только та часть, где есть закрашенные пиксели. То есть, для точки это будет маленький квадратик внизу, а для "%" — большой квадрат посередине. На больших символах это дает хорошую экономию. Но, получается, для правильной отрисовки надо нарисовать вокруг символа рамочку цвета заднего фона, причем для каждого символа — своих размеров.
Я написал код, который устанавливает на дисплее «окно» с внешним размером символа, закрашивает верхнюю полоску, рисует сам символ начиная и заканчивая каждую строку с вертикальных линий заднего фона, затем рисует полоску снизу. В принципе, ничего сложного за исключением того момента, что данные в регистр надо подавать ровно через 18 тактов (17 если не считать саму команду вывода в порт).
Поэтому могу смело выводить один текст поверх другого и ничего не моргает. А если надо перерисовать более длинную строку, то пробелов не добавляю (так себе идея имхо), а после завершения рисования вызываю FillRect (так назвал функцию, по аналогии с виндой) с оставшейся длиной строки. Во многих случаях это даже можно рассчитать и в программу уже константы занести, т.к. текст не меняется и никогда не изменится.
Ерунда короткая? ) А если серьезно — а на что лучше тратить? Если писать такой код доставляет удовольствие, почему нет.
Не соглашусь, всего должно быть в меру. Ваши же слова из параллельного обзора:
Так и в программировании — излишнее количество абстракций тоже затрудняет понимание, т.к. потом просто замучаешься по исходникам бегать и смотреть, кто и что делает.
Посмотрел. Вот такое мне нравится! Тут именно и раскрывается вся мощь ассемблера :)
У АВР ассемблер простой, если прямо такты не считать, на нем писать не сильно сложнее си. Медленнее, да, но код получается лучше компиляторского и меньше по объему раза в два точно. А если писать всю программу на ассемблере, можно и всякие допущения использовать, что, например, регистры R2-R8 используются только этим обработчиком прерываний, основной код их не трогает. Тогда сохранять и восстанавливать их не надо, что дает экономию времени.
А еще можно, например, регистру Y присвоить адрес начала данных и обращаться к данным не командами LDS/STS, а LD R, Y + n. Занимают такие команды те же два такта, но лишь 2 байта вместо 4-х, что на мелких МК дает очень существенную экономию места. А на tiny13, где ОЗУ всего 64 байта так можно вообще всю память адресовать!
У вас в коде тоже подобные оптимизации используются, и это здорово. А что касается читаемости — я стараюсь ассемблерный код комментариями разбавлять.
Кстати, а если бы генератор такой на СТМ делать, можно было бы без ассемблера обойтись?
В идеале — на актуальные на данный момент проекты. Чтобы внести какой-то вклад в развитие. Но я сам этого правила не придерживаюсь, поэтому не имею права давать рекомендации.
Против меры никто не спорит. Но эта мера для понимания лежит очень далеко от оптимальности по выполнению. IMHO.
Проект того генератора показал всю мою умственную отсталость в таких оптимизациях. Не мое это, не получается, напрягает дико. Мне бы писать спокойные программы, где думать не надо. А думать интересней над другим — схемотехникой, механикой.
Да, знаю такие приемы. У меня есть другой генератор — SG-642 (тоже исходник можно найти поиском), там два процессора AVR (чтобы меньше возиться с ассемблером). Один реализует интерфейс пользователя и запрограммирован на Си, а другой по сути сопроцессор и запрограммирован на асм. Для прерывания забрал 24 регистра. При тактовой 20 МГц прерывание вызывается с частотой 206 кГц, в нем реализованы 2 канала 34-разрядных DDS, интерполяция синуса на лету по 8-разрядной таблице до 16 бит (с ошибкой чуть больше младшего бита) и вывод результата в 16-разрядный двухканальный ЦАП по программно реализованному I2S. При входе в прерывание выполняется код, который выравнивает задержку входа в прерывание, чтобы избежать джиттера. Ветки самого прерывания тоже выровнены до такта. Писал это всё сам, но очень хотелось бы, чтобы больше в жизни такого писать не довелось, напрягает просто нереально.
Да, конечно. Там это все получилось бы без участия процессора — только на таймерах. Еще там есть DMA, можно было бы сделать что-то более хитрое.
Имхо UX важнее, чем дизайн, так что лучше проработать его, а дизайн может быть и несколько «кустарный». В конце концов, большинство из наших самоделок будут использоваться только нами. А вот если продукт пойдет в массы, тогда можно и переработать дизайн в соответствии с пожеланиями.
У меня именно такой, причем, для своего размера у него высокий PPI, так что сам дисплей смотрится хорошо.
А мне наоборот — не люблю «подбирать» аналоговые схемы, потому что проектированием это назвать нельзя. А вот писать интересный код, который работает в условии ограниченных ресурсов — самое то.
Посмотрел даташит at90s2313, да, вам бы даже на любой более современной АВР было бы намного проще сделать генератор, используя Fast PWM. Почему вы тогда выбрали именно этот МК? Других не было или тоже было интересно написать что-то на пределе ресурсов?
Я такое обычно вообще без прерываний пишу, но, по мне, задача интересная. Я больше скажу, мне часто интересно решить именно такую задачу, а как только решу, интерес к поделке теряется. Помню, хотел на АВР и адресных светодиодах 2812 сделать пиксельный экранчик. Проблема этих светодиодов в том, что они управляются временной последовательностью, где надо длительностью 0 и 1 передавать биты. То есть, пока МК занят передачей, он не может делать ничего другого, например, сигналы ПДУ обрабатывать и т.д. А если диодов достаточно много и хочется много FPS, то передача занимает практически всё время. Поэтому написал код, который передает данные на прерываниях, позволяя основной программе работать в обычном режиме. Передача занимала примерно 50% времени, так что для других действий оставалось достаточно. И как только сделал, проверил, убедился, что работает, интерес продолжать пропал, т.к. дальше обычная рутина — схема, плата, пайка, сборка, пользовательское ПО.
Так в этом и проблема. Я не хочу пользоваться, если не нравится внешний вид. А другие ничего не заметят.
А какая конкретно модель? Может есть ссылка?
Зачем подбирать? Для каждой задачи делается что-то свое. Сейчас весьма достоверные симуляторы, можно попробовать кучу вариантов без паяльника. Тоже весьма увлекательное занятие.
Тогда вообще тяжело с ними было, только такой был в наличии.
Да, есть такое. Это порой мешает доводить задуманное до конца — интерес теряется раньше.
https://aliexpress.ru/item/32969298268.html
Но что-то по ссылке дорого сейчас, есть дешевле. По качеству экран хороший, 16 бит цвета, пиксели мелкие, глаз не видит.
Процесс проектирования у меня и есть подбор — тут конденсатор поставлю, там поставлю. Поэтому и не очень люблю аналоговую электронику.
Тогда это здорово — между прерываниями 15 тактов, один обработчик занимает 14, другой — 13.
Помочь попросил: нужно было поменять меклкосхему, что то из серии SOP, с кучей ног и шагом 0,3 вроде.
Слава те, что без компаунда была.
Залил Розе и снял К жалом — это делается быстро, даже фен не потребовался.
Оплеткой площадки почистил, потом угловые иглой припаял, а когда микроволну поставил — он слегка охренел: куда с таким толстым жалом такую мелкую работу делать?
Ну, от результата он вообще… как бы это сказать, чтоб без мата… А, фаломорфировал :)
Ну, а я получил удовольствие от созерцания его лица :)
Вообще, первый раз я на первом комтеке — как гугл подсказывает, это был 1991 год.
Сидел мужичок и паял.
Вот там я увидел, как СМД, криво брошенные на пасту, выравниваются под феном, как хорошо отпаивать двухвыводные СМД — резисторы, конденсаторы, диоды — термопинцетом, вот не уверен — но вроде тогда же и микроволну первый раз увидел.
И стало несного обидно, что ничего этого не было у нас…
Просто в массовом производстве оно не надо было на тот момент.
Правильно протестовали — как после такого проектировщика ремонтировать?
По поводу «как ремонтировать» не понял. Если по поводу надписей, то их, к примеру, на SMD керамических конденсаторах чаще всего нет, и как-то ремонтируют. Есть же сборочный чертеж, схема, специфиукация. А протестовали они не из-за надписей, а просто привыкли к МЛТ.
Гроб, конечно. Зато надёжный до ужаса. У нас любили шутить, разглядывая страницу с ТТХ. Мол сс таким гробиком на спине упасть на асфальт с высоты 3 м — посмотрим, что будет со здоровьем радиста. А уж 15 минут на глубине 2 метра — даже представлять не надо про радиста.
а платы на керамике выглядят примерно так (хотя и называются микросборками, что как раз больше подходит для вышеприведенных фото):
А вот SMD там — не помню, хотя да, монтаж там был в некотором роде поверхностный.
Может, что и забыл за давностью лет…
Блин, заметил пару кондеров SMD… :)
Представьте себе ячейку с двумя платами, бутербродом, 220х170мм, между платами, с коротких сторон — по ряду перемычек на 45 контактов каждая, с одной стороны — разъем СНП-34-135, на платах, при разработке слепыши использовались — немножко микросхем, 133, 533,1533, 561, 541, 1802, 556…
Забито до упора, и один хрен приходилось идти на компромиссы: или будет такое работать, или такое, а вместе — не влезет.
И таких ячеек в блоке больше десятка, и тактовая только 4 МГц — многие серии просто не успевали работать с большей частотой.
А как разрешили импорт — и ячеек стало поменьше, и, как правило, одноплатные, и тактовая до 16 спокойно поднялась, и делали практически, что хотели.
Меня как то даже заставили на MCS'96, у которого и так задач хватало, БПФ сделать.
Долго пытался объяснить, что он там нахрен не нужен, потом плюнул и сделал.
Это с учетом того, что я писал только и исключительно на ассемблере.
Через неделю наигрались, и убрал оттуда БПФ…
А до этого БПФ отдельная ячейка делала, на 1802ВР2/ВР5, пзу в 556РТ7, память на 541 серии…
В общем, тогда весь НИИ вздохнул полегче :)
У меня стоит BAKU 761D, после того, как купил первый, самый дешевый конструктор на жалах Т12, использую от нее только фен…
А насчет осциллографа…
Есть, конечно, случаи, когда без цифрового, с памятью, анализом сигнала — никуда.
Тем не менее как то обычным аналоговым осциллографом двухлучевам, что-то С1- и дальше просто не помню, отловил разницу во фронтах сигналов в 4 наны.
Почему то у счетчика 1533ИЕ6 на одном из младших выходов сигнал менялся на эти наны раньше, чем на старшем, и это делало узел полностью неработоспособным.
А вот у 533ИЕ6, которая и должна была стоять, этой проблемы не было :)
Так что все решается в первую очероедь головой…
жало 5 мм от советского ЭПСН, термопара изолированная вроде ХА (тип К). Схемку регулятора сами нарисуете. 60 Вт, 100 рублей.
Ставится почти в любой современный китайский паяльник 220в 30 Вт.
Правда за три года я так и не собрался регулятор температуры спаять.
Но на обычном диммере включал — все работает.
не подскажу
UPD: хотя, смотрю, есть ручки и на Т12 с резьбой, но только зачем, там это не нужно. У меня самого алюминиевая ручка от 100 MHz, там никакой резьбы нет.
Во-вторых, конечно, полоса. Например, был у меня ригол на 100 МГц. Но, при этом, по уровню -3 дБ он показывал 170 МГц. Старый советский так точно не мог, там был очень крутой спад после максимальной частоты.
Вот у меня OWON XDS2102A, я ему батарею самостоятельно изготовил. Считаю большим плюсом перед стационарными возможность работать без сети и без заземления. Вот только полосу бы расширить. Никто не подскажет, как?
www.cqham.ru/forum/showthread.php?38166-%CE%F1%F6%E8%EB%EB%EE%E3%F0%E0%F4-OWON-XDS2102A
батарея, это хорошо. Я себе купил преобразователь 12-220 с синусом и подключаю 12в акб
Это, впрочем, сугубо субъективная оценка.
Громоздко же. Так то у меня и развязывающий блок, собранный из двух UPSов (трансформаторами навстречу) есть.
Кто-нибудь покупал Fnirsi HRM-10 в полном комплекте с держалкой-холдером для аккумуляторов.
Можете разрисовать разводку кабеля и распайку разъема GX12 — 4?
По штатным Кельвинам можно, конечно, но там на всех 4 концах синус идет, я посмотрел.
Поэтому не так уж и очевидно. Можно, конечно, просто подобрать. Всего-то пара сочетаний.
Но вдруг?
Просто купил держалку от YR1035 и разъем. Теперь думаю, как перепаять.
А то застыдили тут меня чуть раньше, что я миллиомы в младшем разряде тестера меряю. Под давлением общественного мнения, пришлось купить :-)))))
на ютубе летом было видео не помню кого, может радиогубителя, он снизу добавил разъем под имеющиеся щупы — там поидее была распайка. кстати в плане миллиомов фнирси не так чтобы хорош, середнячок. а вот вольтметр у него очень точный среди аналогов
Я тут по кельвинам прикинул — вроде бы как на картинке. Но хотелось все же уточнить.
На кроватке — то точно известно, что центральный штырек — потенциальный.
ссылка
Спасибо, нашел.
Там, кстати две разводки есть и для HRM-10 и для YR1035+
Тест: 21700 5000 мАч Liitokala
1. На щупах Кельвина: U= 4.0675 В, R= 20,41 мОм.
2. На холдере от YR1035+ c перепаянным разъемом GX12-4
U=4.0675 В, R=20.16 мОм.
3. Сами штатные щупы Кельвина могут показывать и 0.00 mR и 0.02 mR.
зависит от взаимного расположения губок крокодилов.
печатаем шаблон на планке при помощи лазерного принтера, брызгаем уплотнителем тонера (например смывка для наклеек из фикспрайса)
включаем ламинатор и нагреватель раствора для травления (можно и без ламинатора)
отрезаем и наклеиваем фоторезист, к этому времени ламинатор уже нагрелся — прогоняем через него
засвечиваем при помощи лампы для ногтей
проявляем в растворе соды
травим
далее по желанию нанесение маски примерно тем же способом, я наношу маску, накрываю пленкой от рукава для запекания, засвечиваю 45с, потом снимаю пленку и стираю остатки маски растворителем, дальше дозасветка пара минут
ну и сверление.
двухсторонние платы делать сложнее — нужно совмещать стороны.
металлизация тоже сложно.
а простые платы — на раз-два
Короче, суть в том, что засвет происходит обычной КЛЛ, но не 20 секунд как в случае с УФ-лампой, а 5-10 минут. Да, шаблон получается на просвет так себе, но на выходе все хорошо, без дырок, проверял под микроскопом. Первичную накатку ФР очень просто производить в ванночке с водой, получается ровно и без пыли. Потом в ламинатор для окончательного закрепления ФР. Проявка в стиральном порошке, закрепление в Аисте, смывка в «Кроте». Мне вот пришлось сдауншифтить на ЛУТ, в связи с известными событиями, но я это так не оставил. Сделал контроллер-термостат для ламинатора, чтобы он выдавал 200°С и покупаю желтую бумагу на Али, потому что искать какие-то журналы с правильной бумагой сейчас трудновато. Таким образом я сильно приблизил качество к ФР, недавно делал плату с QFN-24, все отлично получилось. Затраты конечно меньше, чем на ФР, но тут выиграла доступность. А утюгом наоборот, только этикетки ламинирую, почему-то больше контроля, чем с ламинатором получается.
По поводу желтой термотрансферной бумаги — не пошла она у меня. Тонер на ней совершенно не держится, невозможно сложить конвертик для двухсторонней платы и засунуть туда заготовку, чтобы не поцарапать рисунок. Да и в принтере она жуется, надо что-то мудрить с подкладыванием обычного листа. В идеале надо найти что-то среднее по адгезии тонера между термотрансферной и мелованной из журналов. Пока не нашел.
Я терпеть не могу изготовление ПП, но насобачился знатно! Максимально всю химию перевел на аптечно-бытовую и упростил процессы, т.к. я ленивый и нетерпеливый. НО! Самое гадское это пилить/сверлить, потому что пыль, а отдельного помещения у меня под это занятие нет. И вот эта самая пыль иногда останавливает от изготовления.
По платам у меня та же история. Настолько не могу терпеть их изготовление, что даже и думать не хочу об изменении процесса. Утюг и хлорное железо — к этому привык, этого и хватит. Пилить-сверлить стеклотекстолит — это кромешный ад. Обычно обрабатываю контур платы фрезой на станке, пыль очень неприятная. При сверлении то же самое. Долго собираюсь с духом, чтобы сделать очередную плату. Определенно это ложка дегтя в радиолюбительстве.
Для себя решил, что простые платы делаю ЛУТом на термотрансферной бумаге, а что посложнее — на фоторезисте. Делал бы на фоторезисте всё, т.к. качество значительно выше, но доставать фотополимерник из-за мелочи банально лень. А вот ламинатор использую при любом процессе, т.к. с утюгом у меня вообще ничего не получалось. Вообще, крайне полезная вещь в хозяйстве радиолюбителя, надо сказать. Если у вас не хватает под него места — продайте утюг, он всё равно сейчас не нужен)
Я вот точно так же думал про двухсторонние платы :) А вы их просто делаете. Поэтому и я надеюсь в будущем как-нибудь эту технологию освоить.
Ни разу сблизи не видел ламинатора, не представляю его ценность. Утюгом получается, как правило, с первого раза, с чего бы я пошел его на что-то менять?
Ну я двухсторонние делаю с детства, когда они еще рисовались рейсфедером нитрокраской. Например, так делал плату своего первого компьютера. Разводил на миллиметровке, рисовал рейсфедером. Тогда не было никаких проблем с совмещением сторон. Но для SMD так не сделать, нет ориентиров в виде отверстий.
Смотрите :) У меня такой. В него легко лезет 3 мм толщины, так что даже можно передние панели целиком запихивать. Если нужен формат А3, есть соседняя модель.
Да не надо, по сути. Мы здесь делимся собственным мнением, каждый — своим. У меня с утюгом не пошло от слова вообще, ламинатор оказался выходом из положения. И ЛУТ позволяет делать, и фоторезист наносить. Ну, и бумажки ламинировать. А утюг стоит в дальнем шкафу, даже по изначальному назначению его сейчас никто не использует.
А вот когда платы рисовались лаком руками, двухсторонние и я делал. Это ж просто было — видишь дорожки, соединяешь. Да и ошибка в 0.2 мм тогда не значила вообще ничего, максимум, что я мог руками нарисовать — это дорожку между соседними выводами микросхемы.
Да, «костыли» или «выходы из положения» (как вам будет угодно) есть. Но они не попадают под категорию «качественный результат», поэтому люди и заморачиваются по полной. По крайней мере, я считаю именно так :)
Такое невозможно, если само занятие не увлекает.
Что касается ФР — да, с ним посложнее, чем с ЛУТом, но и результат лучше. Но если у вас с ЛУТом уже всё прекрасно получается, то, наверное, и нет смысла пробовать что-то другое.
уплотнитель тонера — жидкость для снятия наклеек, она по хорошему в хозяйстве и так должна быть. ламинатор особо не нужен, можно обойтись без него, или утюгом.
для меня главное это стабильность и повторяемость результата. в отличие от ЛУТа где каждая новая плата это квест.
с фоторезистом один раз подобрал время засветки и погнал
а для фоторезиста нужно руку набить. но через месяцок-другой навык забывается и с новой платой приходится вспоминать всё по-новой.
В целом, абсолютно согласен — фоторезист дает результат лучше и более повторяемый. А если использовать фотополимерный принтер, то обычный принтер, пленка и средство для уплотнения тонера становится не нужно.
Хотелось бы задать вопрос по поводу USB, вернее корпуса самого разъема, он же экран, он же шилд.
Я в своих проектах всегда отделяю шилд от GND параллельно соединенными резистором 1Мом и конденсатором 1нФ.
Если корпус металлический, то шилд у меня имеет контакт с корпусом, а металлические корпуса обычно заземляются, по крайней мере у меня и там, где это будет работать. Про дураков сейчас не буду…
А вы смотрю просто его изолировали от корпуса, вернее металлической части корпуса. Интересно было бы услышать ваш опыт на эту тему? Спасибо!
Аналогичный опыт, работаю в сфере АСУ ТП, в офисе все работает, а на объектах не всегда, потом долгие разборы полетов и испытания. А вот 485-й кстати хорошо себя зарекомендовал, тоже используем разные MOXA'ы. Сейчас USB на наших изделиях только для конфигурации применяется.
И главное, что это вышло чистым вредительством, ИМХО: цели существенно сэкономить медь так и не было достигнуто…
как всегда — монументально, продумано и красиво.
И род деятельности, и увлечённость, и «рукоблудие», и тяга к перфекционизму… Даже возраст.
Но как специалист, Вы, конечно, на порядок круче меня. Очередной раз снимаю шляпу!
но только — вы же русские, и делаете для себя или для таких же русских. зачем везде все на английском ?!