Эта страница актуальна в 2020-м году (дата последнего изменения написана внизу), она заменяет все страницы прошлых лет.

Я (Зорин Артем Викторович) являюсь преподавателем курса лабораторных работ ТСАНИ (технические средства автоматизации научных исследований) в НГУ с 2013-го года. Это моя личная (неофициальная) страница практикума.

Страница состоит из двух частей: сначала идут общие сведения о курсе, а потом рассмотрение отдельных методичек и работ курса.

Я стараюсь не дублировать информацию. То, что уже было написано, как правило, не будет повторяться, даже если это было бы уместно.

Оглавление

Общие замечания

Комментарии к методичкам/работам

Главное

ТСАНИ в интернете:

Куратор курса — Фатькин Георгий Александрович.

Класс ТСАНИ — комната 346 (Главный корпус — 3 этаж). Ключ есть в комнатах 335 (кафедра радиофизики) и 344 (лаборатория радиофизики). Студенты без преподавателя в класс не допускаются.

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

Оценки

Зачёт дифференцированный. Оценку ставит преподаватель по своему усмотрению, строгих формальных критериев нет, но примерно так: «обязательная часть» курса состоит из работ 0—4: их необходимо сдать, чтобы получить хотя бы «удовлетворительно». После этого начинается «экспериментальная часть» курса: 1 работа = 1 балл, причём работа должна выполняться не менее 2 недель; на зачётной неделе писать код нельзя, можно только сдавать работу (а в идеале надо просто принести зачётку и получить ту оценку, которую заработали). Если вы не получили зачёт до конца зачётной недели, даётся ещё две попытки: первая пересдача (по сути, ещё одна зачётная неделя: сдаёте своему преподавателю) и вторая пересдача (сдаёте комиссии).

В случае пропуска занятия необходимо перед следующим взять допуск в деканате. Насколько мне известно, его выдают без проблем.

Как лично я отношусь к процессу обучения

У преподавателя 2 функции: 1) помочь студенту учиться; 2) поставить оценку. Это в некотором смысле конфликтующие цели, но такова жизнь.

В идеале помощь студенту не требуется вообще: он сам читает методички и выполняет задания. Но в реальности методички написаны таким образом, что без преподавателя не разобраться. Да ещё и сами студенты неправильно работают с методичками: вместо того, чтобы сначала всё прочитать и осознать, многие сразу же ищут задание и пытаются в меру своего понимания выполнить его. Особенно плохо получается, если само задание состоит из нескольких абзацев, и студенты приступают к выполнению первого же абзаца, даже не взглянув на следующие.

Совершенно неправильно забывать о работе, едва сдав её. Курс построен таким образом, что для выполнения следующих работ ТРЕБУЮТСЯ знания из предыдущих. Например, вы можете сдать 1-ю работу, не заучивая наизусть функции для работы с таймером; но у вас должно остаться знание, что среди доступных вам инструментов есть и таймер. Если же эта информация совершенно не задержится в вашей голове, вы просто не сможете корректно выполнить работу №4.

Не плохо не знать чего-то; плохо не понимать того, что вы делаете. Например, для работы с файлами многие студенты просто копируют код со страницы 19 справочника. Весь код. Вместе со строчкой if( pF == NULL ) printf("Can't open file"); и определениями переменных Var1 и Var2. А на вопрос, что это всё означает, ответа нет. Я такие программы не принимаю.

Я придерживаюсь модели, что студент учится для себя (а не для оценки и уж точно не для преподавателя). У меня нет мотивации завышать или занижать оценку. Я просто ставлю на зачётной неделе то, что вы заработали.

Если вы хотите позвать преподавателя, чтобы сдать работу, сначала проверьте её сами. Если минуту назад всё работало, и вы внесли совсем маленькую правку, всё равно проверьте заново ВСЁ.

Если вы считаете, что всё сделали правильно, а ничего не работает, не следует звать преподавателя. Сначала разберитесь, что именно не работает, сформулируйте конкретный вопрос.

Мой опыт говорит о том, что научить ТСАНИ хотя бы на тройку можно любого студента, дожившего до третьего курса ФФ НГУ. Почему же не все студенты получают зачёт? Вот типичный список причин:

Как видно, всё в конце концов сводится ко времени. Рекомендации, как получить оценку повыше:

Компьютеры

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

Папка курса ТСАНИ — D:\TSANI\. Изучите её, там много полезного.

Рабочая папка — D:\TSANI\WORK\. Она доступна всем, поэтому:

  1. Создайте в ней свою личную папку (D:\TSANI\WORK\<номер группы>\<фамилия>\).
  2. После каждого занятия копируйте свою папку на флешку.

Однако не надо работать непосредственно с флешки. Во-первых, это вредно для неё. Во-вторых, в таком случае компиляция программы занимает значительное время; я просто не буду вас ждать и пойду к следующему студенту. В-третьих, если флешка будет единственным местом хранения ваших наработок, вы рискуете потерять их.

«Корзина» не работает (несмотря на ярлык на рабочем столе), файлы удаляются сразу!

Не забывайте про существование цифрового блока клавиатуры, клавиш Home, End и всяких сочетаний клавиш (Alt+Tab, Alt+F4, Ctrl+w...). Часто так быстрее, чем мышью.

Редактор кода «LabWindows/CVI», на мой взгляд, не очень удобен. Рекомендую «Notepad++». Так как прав на установку нет, скачивать архив zip.

Рекомендую овладеть слепым десятипальцевым методом набора текста.

Язык Си

Лучшая, на мой взгляд, книга о языке Си на русском языке есть на компьютерах в папке D:\TSANI\COMMON\ДополнительнаяЛитература\.

При копировании кода из PDF-файлов методичек возможны ошибки. В частности, проверяйте кавычки и переносы строк.

Чтобы случайно не выполнить присваивание (if (a = 1)) вместо сравнения (if (a == 1)), приобретите привычку ставить константу перед переменной (if (1 == a)). Но в случае двух переменных это не поможет.

У меня на сайте (http://www.caesarion.ru/programming/#ccpp) есть раздел о языке Си, его тоже читайте, здесь я не буду дублировать то, что есть там.

Учтите, что в компьютерах, в отличие от математики, целые числа и числа с плавающей запятой (точкой) — это две большие разницы: «...Очень любопытные и странные явления: некоммутативность и неассоциативность арифметических операций, ноль со знаком, разность неравных чисел дает ноль...». Вот лишь пара ссылок: «Википедия» (обратите внимание на раздел «машинная эпсилон»), «Хабрахабр» (для нас важнее всего раздел «4. Подводные камни в арифметике с плавающей запятой»). Впрочем, «Сейчас арифметика с плавающей запятой почти совершенна. Практически всегда наивный подход сработает, и программа, не учитывающая все ее особенности, выдаст правильный результат, а описанные подводные камни касаются только экзотических случаев. Но нужно всегда оставаться бдительным: в таком вопросе как компьютерная математика легко наступить на грабли».

Если не знаете, какого типа создать переменную или параметр функции, подумайте прежде всего об int или double; как правило, использование других типов является всего лишь оптимизацией и в рамках курса ТСАНИ не требуется. А вообще для символов следует использовать char (не unsigned char).

Не забывайте, что функции чтения, читающие в аргументы (scanf, GetCtrlVal, portIn), принимают не просто переменные, а указатели.

Пользуйтесь скобками, если не уверены в приоритете операций.

Изучите условное выражение (?:). Зачастую им можно заменить оператор if, значительно экономя количество кода.

Говорят, что в коде может быть только две константы: 0 и 1. Это не всегда так. И всё же каждый раз, когда вы хотите написать в коде константу, подумайте о том, чтобы сделать это через директиву препроцессора #define.

Указатели

Указатель (pointer) — это такой тип данных, который содержит адрес переменной или функции. Дальнейшее верно для переменных. По сути, это просто беззнаковый целый тип (есть даже такое понятие, как арифметика указателей). Для взятия адреса переменной используют амперсанда (&i). Для разыменования (опосредования) указателя пишут звёздочку (*p). Ещё звёздочку используют для объявления/определения указателей (в том числе аргументов функций). Любой указательный тип можно привести к типу void* и наоборот. Адрес можно взять у любой переменной, в том числе у указателя. Можно сделать указатель на указатель, указатель на указатель на указатель и так далее. При работе с функциями указатели удобны тем, что сами они занимают мало места (в LabWindows/CVI 9.0 32 бита), но через них функция может прочитать и записать сколь угодно большой объём данных. Ссылок (reference) в языке Си нет, однако можно говорить, что указатель «ссылается».

Объявление int *p, i; эквивалентно объявлению int* p, i; и объявлениям int *p; int i;, но не объявлениям int *p; int *i;.

Конструкция int *p; *p = 1; допускается языком Си, но, если вы так написали, скорее всего, вы не понимаете, что делаете, и программа будет работать не так, как вы хотите. Правильно так: int *p; int i = 1; p = &i;. Или так: int *p; p = malloc(sizeof(int)); *p = 1; free(p);.

Пусть есть такая функция: void example(int *pi);, и вы хотите передать ей переменную i типа int. Можно сделать так: int *p; p = &i; example(p);. А можно так: example(&i);.

Подумайте, почему функция int* f(int i) {return &i;} или int* f(int i) {int j = i; return &j;} может вернуть адрес области памяти, в которой не содержится значения i или даже привести к ошибке (времени компиляции или времени исполнения), но может и заработать (в зависимости от компилятора, операционной системы, аппаратного обеспечения и ещё кучи параметров, которые не всегда можно учесть). Можете провести эксперимент: следующий код компилируется в «LabWindows/CVI 9.0» и выполняется без ошибок в «Windows 7», но первый printf выводит 123, а последний что-то другое.#include <ansi_c.h> int* f(int i); int main (int argc, char *argv[]) { int *i = f(123); printf("%d\n", *i); printf("%d\n", *i); getchar(); return 0; } int* f(int i) { int j = i; int addrj = (int)&j; return (void *)addrj; }

Самостоятельно вспомните, что общего и чем отличаются указатели, массивы и строки.

LabWindows/CVI

При создании нового проекта или файла обращайте внимание, в какой папке он создаётся.

Ознакомьтесь со страницей «C Data Types» справки «LabWindows/CVI» (в языке Си конкретные диапазоны типов зависят от используемого программно-аппаратного обеспечения).

F1 — помощь. Если курсор стоит на названии библиотечной функции, откроется страница с описанием этой функции.

Ctrl+Shift+пробел (когда курсор стоит на функции) — помощь в выборе аргументов функции.

Каждому файлу графического интерфейса (.uir) соответствует одноимённый заголовочный файл (.h), причём по умолчанию он не включается в проект. Но его стоит открыть, чтобы видеть имена элементов графического интерфейса. Обновляется .h-файл каждый раз при сохранении .uir-файла. Численные идентификаторы являются служебной информацией, они могут измениться, поэтому использовать можно только имена. Пример: #define PANEL 1: на 1 вообще не смотрим. Для нас существует лишь PANEL.

По невыясненной причине (похоже, проблема в «LabWindows/CVI». Обсуждение на форуме разработчика) иногда возникает ошибка времени исполнения обращения за пределы нестатического массива, объявленного в функции, при конфигурации debug. Можно предложить следующие способы решения проблемы:

Задержку можно сделать функцией Delay(double numberOfSeconds), но менее ресурсоёмка функция Sleep(DWORD dwMilliseconds), при этом надо вставить #include <windows.h>, причём до других #include.

Чтобы сгенерировать функцию обратного вызова (callback) через контекстное меню элемента, необходимо сначала задать её имя в свойствах элемента, а программа не должна выполняться (если она была запущена и прервана, нажмите Ctrl+F12 или кнопку Stop (Terminate Execution)).

Далеко не всем элементам графического интерфейса следует назначать callback-функции. Для некоторых элементов можно назначить одну и ту же callback-функцию.

EVENT_COMMIT — это именно общее, основное событие. В рамках курса ТСАНИ всегда (за исключением EVENT_TIMER_TICK для таймера и EVENT_CLOSE для панели) следует использовать именно EVENT_COMMIT. Необоснованное использование других событий, например, EVENT_LEFT_CLICK, является ошибкой, так как не позволяет использовать программу с клавиатуры; я не принимаю такие работы.

Graph: чтобы можно было изменять масштаб: в редакторе интерфейса в свойствах элемента Control Settings → Zoom Style: Zoom to Rectangle либо Zoom Around Point. При работе программы Ctrl + LMB + move = увеличить; Ctrl + RMB = уменьшить; Ctrl + Shift + LMB + move = передвинуть (LMB — левая кнопка мыши; RMB — правая; move — двигать мышь).

Не путайте Graph и StripChart.

Научитесь пользоваться отладчиком.

LabWindows/CVI лишь частично поддерживает стандарт C99. В частности, функция double round(double x) в библиотеке <math.h> отсутствует (это верно даже для LabWindows/CVI 19!). Вместо неё следует использовать нестандартную функцию long RoundRealToNearestInteger(double realNumber).

Библиотека tsanilib

Если вы хотите научиться работать с оригинальной библиотекой DAQmx, читайте книжку от работы №2 2010-го года издания, а также страницу ТСАНИ-2013.

Для использования библиотеки tsanilib проекты надо создавать так: File→New→Project from Template→User-Interface Application(TSANI). Для желающих увидеть внутренности библиотеки: User-Interface Application(TSANI.SRC) (вместо *.lib будут добавлены *.c).

Можно ли писать программы дома?

Краткий ответ: нет, так как дома у вас нет используемого оборудования, как и лицензии на LabWindows/CVI.

Длинный ответ: первая часть работы №1 использует только функции стандартной библиотеки языка Си (версии 99), поэтому её можно делать с помощью любого компилятора.

Вторая часть работы №1 требует среды разработки LabWindows/CVI (в классе установлена версия 9.0.0 (348), более свежие версии должны быть совместимы). Сам по себе дистрибутив можно легально скачать с сайта разработчика (ссылка на оффлайн-установщик — «Individual Offline Installers» в нижнем правом углу), но лицензия стоит очень больших денег. Кажется, там есть пробный период, что-то вроде недели или двух, но это не точно.

О «Рутрекере» говорить не будем.

Если вы достали LabWindows/CVI, то для выполнения дальнейших работ установите драйверы NI-DAQmx. Это бесплатно. В классе установлена версия 4.5.0f0, более свежие версии должны быть совместимы, в том числе со старым LabWindows/CVI. В программе NI MAX создайте необходимые виртуальные устройства: для работ №2, 3 и 4 это только модуль PXI-6251 с настройками по умолчанию (PXI Chassis = 1, PXI Slot = 2).

Далее следовало бы рассказать о подключении или эмуляции библиотеки tsanilib, но сомневаюсь, что хоть кто-то дойдёт до этого места. Обращайтесь, если что.

Список аппаратных неисправностей

Место 8, индикатор магистрали: всегда горят AD15, всегда выключены AD13 (проблема именно с индикатором; порты, модуль ввода, ЦАП-АЦП работают).

Место 9: модуль ввода вообще не работает.

Места 13, 14 неполноценные (там даже Lab4 нельзя делать).

Справочные материалы по практикуму ТСАНИ

Не рекомендуется внимательно читать раздел о языке Си в справочных материалах: там есть ошибки, очень многое вообще отсутствует (препроцессор, тернарный оператор, перечисления) или объяснено недостаточно (структуры, указатели, операторы). Лучше читайте книгу из D:\TSANI\COMMON\ДополнительнаяЛитература\.

В книге рассматривается не язык Си вообще, а лишь используемый в практикуме Си99 на архитектуре Win32 (это важно, например, в главе 3.1 «Основные типы переменных»: на других архитектурах возможны другие длины переменных).

Стр. 3 (и далее): в коде программы заменить английские кавычки (#include “file1.h”) на машинописные (#include "file1.h").

Стр. 3: ещё бывают переменные со словом static...

Стр. 4: прототип не обязательно в самом начале, лишь бы раньше вызова. И можно через include.

Стр. 4: это не объявление, а определение.

Стр. 5: однострочный комментарий можно продлить склейкой строк \.

Стр. 6: строкового типа на уровне языка не существует (это соглашение об использовании массивов char: строка заканчивается числом 0), как и булева (он подключается через библиотеку). Ещё есть указатели, составные (массивы и структуры), объединения, функции и void. В таблице не хватает short (полезен для работы с Avalon), long long. Ознакомьтесь со страницей «C Data Types» справки «LabWindows/CVI». Если не знаете, какого типа создать переменную или аргумент функции, подумайте прежде всего об int или double. Для символов следует использовать char (не unsigned char).

Стр. 8: не операторы, а выражения или операции.

Стр. 15: указатель не обязан содержать (корректный) адрес другой переменной. А ещё есть указатели на функции. Присваивание значения делать необязательно.

Стр. 15: через return можно вернуть структуру или ещё как-нибудь закодировать несколько переменных в одной.

Стр. 15: функция может изменять значения глобальных переменных. Но это плохой стиль.

Стр. 15: слово «динамически» неприменимо к объявлению массива. Тут напутаны массивы и указатели.

Стр. 16, 6.3: ещё полезны символы \n (новая строка), \t (табуляция).

Стр. 20, if/else: else может не быть.

Стр. 20, switch: нет слова «блок», есть «оператор, помеченный меткой».

break хотя и часто используется со switch, однако является другим оператором, его нужно описать отдельно.

Забыт do while и continue.

Стр. 21: for ЧАСТО ИСПОЛЬЗУЮТ, ЧТОБЫ выполнить заданный блок кода указанное число раз. Но есть и другие варианты.

Стр. 51: стоит добавить Харбисон, «Стил Язык Си с примерами» Бином 2011.

Lab 0. Системы автоматизации экспериментальных установок

TEST_HEX.ZIP (версия 1998 года, написана для DOS, на современных компьютерах требует DOSBox).

TEST_HEX_2020.zip (версия 2020 года, требует LabWindows/CVI Run-Time Engine версии 9.0 или новее или просто LabWindows/CVI (архив содержит как exe-файл, так и исходные коды)).

TEST_HEX_2020_with_RTE.zip (версия 2020 года, Run-Time Engine включён, размер 131 МБ, устанавливается в папку c:\Program Files (x86)\TEST_HEX).

Линии связи не обязательно состоят из проводов. Бывают беспроводные (радиотелеграф, WiFi, Bluetooth), оптоволоконные...

Точное значение терминов «линия связи», «магистраль», «шина» мне неизвестно, но одно из определений шины говорит, что это когда все устройства подключены к ней одновременно. Причём необязательно они подключены к одному физическому проводу, например, USB и Ethernet на витой паре (в отличие от коаксиального) требуют, чтобы каждый провод соединял только два устройства; однако благодаря таким устройствам, как концентраторы (hub), шина может содержать гораздо больше двух устройств.

В наше время байт, как и написано в методичке, состоит из 8 бит, однако это не определение, а исторически сложившееся свойство. По определению байт — это наименьшая адресуемая единица оперативного запоминающего устройства (ОЗУ, память). Определение не устанавливает размер байта, существовали даже такие компьютеры, в которых часть памяти адресовалась по 8 бит, а часть по 1 биту. Если в байте 8 бит, его можно называть октетом; особенно часто это слово используется в описаниях сетевых протоколов (так как по сети передаются биты, а ОЗУ отсутствует). Половину октета называют «ниббл» (nibble, nybble) или «тетрада», хотя в разговорной речи встречается «полубайт».

Стоит выучить натуральные степени двойки хотя бы до 10: 1, 2, 4, 16, 32, 64, 128, 256, 512, 1024. Также полезны 15-я и 16-я степени: 32 768 и 65 536.

Об оценках за практикум (стр. 17, контрольный вопрос 1) написано выше.

Приложение (стр. 19) для сдачи работы обязательно!

Для сдачи работы необходимо не только ответить на контрольные вопросы, но и пройти тест на перевод между системами счисления (ярлык на рабочем столе).

Битовые операции

Если a — однобитное число, то:

Если про числа a и b известно, что у них нет одновременно установленных битов, то a + b = a ^ b = a | b.

Язык Си не поддерживает двоичного представления чисел в коде программы. Тем не менее, существует и широко используется способ формирования чисел без обращения к таблице перевода между системами счисления; более того, можно формировать числа, зависящие от переменных.

Бит, имеющий особый смысл, отличающийся от смысла остальных битов числа, называют битовым флагом. Например, в работе №8 один из битов используется для включения нагревателя, а другой — для отображения состояния перегрева. Наряду с «записать единицу в бит» говорят также «установить (set) бит/флаг», «включить флаг», «поднять флаг». Синонимами для «записать нуль в бит» являются выражения «снять бит», «обнулить бит», «очистить (clear) бит», «сбросить (reset) бит», «опустить флаг». Наконец, бит или флаг можно переключить (toggle), то есть изменить его значение на противоположное.

1<<n — это двоичное число, n-й бит которого равен 1, а все остальные нули. С помощью операции «побитовое ИЛИ» можно сформировать число с несколькими единицами: (1<<n)|(1<<m)|(0<<k). В данном случае установленными оказались биты номер n и m, а бит k, как, впрочем, и все остальные — сброшенным. Можно было бы не писать |(0<<k), но иногда такая запись бывает удобной.

Присваивание с побитовым ИЛИ позволяет установить определённые биты произвольного числа, оставив остальные неизменными: выражение a |= (1<<0)|(1<<n) приведёт к тому, что у переменной a установятся биты номер 0 и n.

Присваивание с исключающим ИЛИ позволяет инвертировать определённые биты: после исполнения кода a ^= 1<<5 поменяется на противоположный бит номер 5.

Для того, чтобы сформировать число с несколькими нулями, а все остальные биты сделать единицами, применяют операцию побитовой инверсии: ~((1<<2)|(1<<n)) — число, у которого нулевыми являются только биты номер 2 и n.

Присваивание с побитовым И используется для того, чтобы занулить некоторые биты: запись a &= ~(1<<0) приводит к занулению бита 0. Эту операцию часто используют, чтобы узнать значение определённого бита числа. Например if (data & (1<<6)) (проверка, что бит 6 переменной data установлен) или if (!(data & (1<<6))) (проверка, что бит 6 переменной data сброшен; либо можно было использовать ветвь else предыдущего примера).

Переменная может использоваться не только справа от знака сдвига, но и слева. К примеру, выражение a<<3 даст число 8, если a == 1, и 0, если a == 0. Однако в используемой версии языка Си отсутствует тип данных, принимающий ровно 2 значения: 0 и 1. Представьте, что a == 3. В таком случае a<<3 == 24. Чтобы избежать такой ситуации, применяют условное выражение: (a?1:0)<<3.

Циклический сдвиг можно реализовать как два сдвига: a = (a<<i)|(a>>(8-i)) — циклический сдвиг вправо на i бит 8-битной переменной a.

Lab 1. Изучение среды программирования LabWindows/CVI

В следующем издании: убрать номер страницы с титульного листа. Стр. 3: «локальную сеть или Интернет» — лучше просто «сеть» (или «интернет» с маленькой буквы).

Стр. 7: не «на рабочем столе», а «на экране».

Стр. 8, 10: «функция-обработчик событий» — по сути верно, но устоявшийся перевод для «callback function» — «функция обратного вызова».

Стр. 11. Повторю и здесь: EVENT_COMMIT — это именно общее, основное событие. В рамках курса ТСАНИ всегда (за исключением EVENT_TIMER_TICK для таймера и EVENT_CLOSE для панели) следует использовать именно EVENT_COMMIT. Необоснованное использование других событий, например, EVENT_LEFT_CLICK, является ошибкой, так как не позволяет использовать программу с клавиатуры; я не принимаю такие работы.

Практическое задание 1 (парабола)

Суть задания — вспомнить язык Си, в частности, объявления и определения переменных и функций, передачу аргументов функций (по значению), области видимости, инициализацию переменных, указатели.

Многие студенты и преподаватели забывают, что помимо корней надо ещё и вершину найти.

Функции GetKey() и KeyHit() принадлежат библиотеке LabWinodws/CVI. Возможно, правильнее использовать функции стандартной библиотеки (getchar, например).

Строгое следование заданию возможно (и то при условии замены float на double), но весьма затруднительно, учитывая, что это вводная работа, а большинство студентов и так не очень хорошие программисты. В итоге каждый преподаватель принимает по-своему, в большей или меньшей степени упрощая задание (например, ещё до вызова функции CalculateRoots проверяем a == 0. Если это так, то функцию вообще не вызываем, а просто сообщаем, что уравнение не является квадратным). Хотелось бы, чтобы в переиздании задание было переформулировано. Для тех, кто всё-таки хочет строго придерживаться задания: закодируйте различные количества корней с помощью спецзначений переменных типа double. Вам поможет функция NotANumber() (также понадобится #include "toolbox.h").

Разный смысл параметров X1, X2 в зависимости от значения дискриминанта — плохой стиль (это могла бы быть вынужденная мера на устройстве с очень малыми ресурсами, но персональный компьютер таковым не является).

Префикс p в названиях параметров функции — от слова pointer. Если вы объявляете просто переменные типа double, называйте их D, Value1, Value, а не pD, pValue1, pValue2.

Вывод на экран должен быть человекопонятным. То есть в случае двух действительных корней должно быть что-то вроде X1 = 1.2 X2 = 3.4

А в случае мнимых X1 = 1.2 + i*3.4 X2 = 1.2 - i*3.4

Практическое задание 2 (синусоида)

Стр. 16, часть 1: SetAxisScalingMode — хорошая штука, но не забывайте, что многие вещи можно делать и через редактор графического интерфейса.

Стр. 16, часть 2: непрерывно перерисовываться — имеется в виду по таймеру, то есть 2 раза в секунду независимо от действий пользователя.

Стр. 16, часть 1: опечатка: веденными → введёнными.

Стр. 16, часть 3: шум имеется в виду белый; в частности, он не должен изменять среднее значение сигнала. Обоснуйте выбор пределов регулировки шума (в чём смысл отрицательного шума?).

Стр. 16, часть 5: вместо задания с мощностью можно (нужно?) сделать задание с Фурье-спектром. Под спектром понимается квадратный корень из суммы квадратов действительной и мнимой частей. О преобразовании Фурье можно почитать раздел «Frequency Analysis» в справке «LabWindows/CVI».

Lab 2. Магистрально-модульные системы автоматизации

TST-lab02.zip (версия 2019-12-24).

В следующем издании: библиотека TSANI в верхнем регистре? Переделать осциллограммы Avalon: посильнее разнести операции во времени, добавить вертикальные штриховые линии, чтобы было точно видно, что за чем следует; подписать L и H или 0 и 1.

Смысл сигнала ALE: «Внимание всем модулям! Я, контроллер шины, уже выставил на шине адрес. Запомните его!». У модулей есть 4 мкс после опускания сигнала.

Смысл низкого уровня сигнала WRITE: «Внимание всем модулям! Я, контроллер шины, уже выставил данные. Пусть тот, к кому была адресация, запомнит их!». У модуля есть 4 мкс после опускания сигнала.

Смысл низкого уровня сигнала READ: «Внимание всем модулям! Я, контроллер шины, готов читать шину и хочу, чтобы модуль, к которому была адресация, выставил данные!». У модуля есть 6 мкс после опускания сигнала на выставление данных, после чего он обязан держать шину неизменной до поднятия сигнала, после чего модуль должен отпустить шину AD.

Lab 3. Цифро-аналоговые и аналого-цифровые преобразователи

В разных источниках связь LSB и FS и Uref для ЦАП описывается по-разному: где-то коэффициент 2N (в методичке на странице 4 и в глоссарии «Maxim integrated»), где-то 2N−1 (в фильме).

Практические задания (оба)

Выключите автомасштабирование и включите возможность ручного масштабирования.

Нужно как построить все возможные графики, так и вывести численные значения ошибок (отдельно отрицательных и положительных; как в вольтах, так и в LSB; указать код или напряжение). Числа можно выводить в консоль. У графиков, в соответствии с определением характеристики преобразования, одна ось должна быть в вольтах, а другая в кодах (причём для ЦАП и АЦП это разные оси).

Для каждого задания лучше написать не одну программу, а две: одна производит измерения и записывает их в файл, а вторая читает этот файл и делает анализ. Это особенно важно для второго задания, так как измерения занимают до десяти минут.

После нахождения смещения (ошибки нуля) необходимо вычесть его из всех точек; далее находится ошибка масштаба, и всё опять корректируется в соответствии с ней. Лишь после этого находятся дифференциальная и интегральная нелинейности, причём они не должны быть целочисленными.

Для наглядности лучше строить все передаточные функции (идеальную, идеальную для АЦП с бесконечной разрядностью, измеренную, измеренную с учётом ошибки нуля, измеренную с учётом ошибки нуля и масштаба) на одном элементе Graph, но добавить возможность включать и выключать их. Остальные графики (интегральная и дифференциальная нелинейности, для АЦП — абсолютная погрешность) также можно построить на одном Graph (но другом).

Рекомендую сырые данные нарисовать красным цветом; с учётом ошибок нуля и смещения — жёлтым; идеальную передаточную характеристику — зелёным.

Практическое задание 1 (ЦАП)

В целом это задание можно считать подготовительным, так как оно почти такое же, как и следующее, только проще (не считая того, что во второй части не просят найти дифференциальную нелинейность), так что я не буду комментировать тут всё; читайте вторую часть, прежде чем делать эту.

Я точно не знаю, как устроен используемый ЦАП. Есть версия, что 3,3 В соответствует коду 255, а есть — что 256. Кроме того, могут быть проблемы в начале: первые несколько кодов выдают большее напряжение, чем должны бы.

Практическое задание 2 (АЦП)

Ощущение, что это задание почти такое же, как и предыдущее, только константы другие, обманчиво.

Контрольные вопросы для допуска к выполнению задания: в каких пределах вы собираетесь подавать напряжения и с каким шагом (сколько вы сделаете измерений)? Чему равен LSB АЦП Avalon? Чему равен LSB ЦАП NI PXI-6251?

Avalon-АЦП построен на основе микроконтроллера ATmega64, поэтому рекомендуется прочитать раздел Analog to Digital Converter: ADC Noise Canceler: ADC Accuracy Definitions, а также первые два абзаца раздела Analog to Digital Converter: ADC Conversion Result его документации (страницы 239—242 файла D:\TSANI\COMMON\ДополнительнаяЛитература\Atmel-2490-8-bit-AVR-Microcontroller-ATmega64-L_datasheet.pdf). В частности, обратите внимание, что последний переход происходит при -1,5 LSB от максимума, а не -0,5. Поэтому LSB = FS/2N = 2,5 мВ (а не FS/(2N-1) = 2,50244... мВ), а напряжению 2,56 В соответствует код 1024, а не 1023.

При расчёте нелинейностей и абсолютной погрешности необходимо брать передаточную характеристику идеального АЦП с бесконечной разрядностью.

Задание предлагаю переформулировать следующим образом: необходимо написать 2 программы. 1-я должна только сохранять передаточную характеристику в файл. Файл должен содержать 2 столбца (через пробел): в первом напряжение, поданное ЦАПом NI; во втором код, прочитанный АЦП Avalon. Программа должна содержать 3 настройки (можно в виде #define или определения глобальной переменной): 1) минимальное генерируемое напряжение; 2) шаг генерации напряжения; 3) максимальное генерируемое напряжение. 2-я программа должна анализировать этот файл. Она не знает настроек предыдущей программы, даже не знает количества строк в файле (разрешается ввести ограничение сверху, например, 10 000). Она знает только следующие числа (их тоже нужно сделать через #define или определения глобальной переменной): минимальное номинальное напряжение АЦП (0), максимальное номинальное напряжение АЦП (2,56 В), разрядность АЦП (10).

Дополнительные задания: найдите дифференциальную нелинейность. Найдите абсолютную погрешность (absolute accuracy). Абсолютная погрешность находится точно так же, как интегральная, но берутся сырые данные (без учёта ошибок нуля и смещения).

Дополнительное задание к обеим частям

Для каждой точки проведите N измерений и усредните их. Убедитесь, что шум уменьшается как корень из N.

Lab 4. Распределённые системы управления и последовательные шины передачи данных

(Стр. 4, таблица) Эта таблица хуже «Википедии». Тут намешано всё без разбора. Например, для USB количество проводов в шине 4 верно для USB 2.0, а вот скорость 5 Гбит/с — для USB 3.0, где проводов больше. Для Ethernet, опять же, намешаны всякие разные версии, а адресация вообще указана для другого протокола (IP); Ethernet Version 2 использует для адресации 48-битный MAC-адрес, причём 1 бит используется как признак широковещательной посылки, остальные биты тоже имеют различные значения.

(Стр. 5) Аббревиатура I2C означает Inter-Integrated Circuit, по-русски обычно читается как «и-два-це». Ещё этот (или слегка модифицированный) протокол обзывают по-другому, например, TWI (Two-wire Serial Interface, двухпроводной последовательный интерфейс).

(Стр. 7) «После того, как ведомый отпускает SCL, он посылает сигнал ACK». Правильнее сказать, что ведущий принимает (N)ACK после того, как обнаружил поднятый SCL. Ведь менять SDA при поднятом SCL нельзя.

(Стр. 9). «Визуально оценить состояние линий позволяют светодиоды D1 – D4», а конкретно так: для чёрных разъёмов горящий индикатор означает землю на линии, погашенный — питание. Для зелёных — наоборот.

D1D2D3D4
SDA-1SCL-1SDA-2SCL-2

Записанное значение (которое может не совпадать с состоянием линии) можно отслеживать по индикатору магистрали Avalon (возможно, предварительно придётся записать 1 в port2/line0), причём там (для чёрных разъёмов) горящий индикатор означает питание, а погашенный землю (для зелёных наоборот?).

(Стр. 15, работа с термодатчиком). Прежде всего убедитесь, что у вас есть термодатчик (их на всех не хватает). Проще всего это сделать с помощью тестера: переведите его в режим ведущего и выполните опрос термодатчика (кнопка в нижнем правом углу).

Приложение 1 (пример реализации контроллера шины) я рекомендую лишь пробежать глазами, чтобы более-менее сформировать представление о том, как можно разбить программу на функции. Но не стоит пытаться разобраться в нём: написать свой код проще, чем отлавливать ошибки в чужом. Самое глупое, что только можно сделать, — скопировать весь код в свою программу, вообще не думая, а потом исправлять и дописывать её.

Контрольный вопрос: как, соблюдая протокол, получить от термодатчика лишь один октет температуры?

Контрольный вопрос: объясните, что изображено на временной диаграмме:

Я рекомендую выполнять задания следующим образом:

  1. Разобраться с линиями SDA и SCL: научиться их писать и читать.
  2. Создать элементарные функции для работы с I2C: старт, стоп, запись бита, чтение бита. Удобнее всего, чтобы каждая из этих функций (за исключением «стоп») оставляла после себя SCL в низком состоянии.
  3. Создать функции записи и чтения одного октета по протоколу I2C (для работы с термодатчиком понадобится также функция чтения двух октетов).
  4. Применить полученные функции к конкретным используемым устройствам.

Созданное в результате выполнения данной работы устройство I2C является лишь грубой моделью из-за того, что чтение линий происходит по запросу с очень низкой частотой. Если с ролью единственного ведущего устройства оно справляется, то при наличии достаточно быстрого второго ведущего (дополнительное задание) возможно неотслеживание потери арбитража, что нарушает стандарт. Реальные устройства (в том числе реализованные программно, например, в микроконтроллерах) либо опрашивают линии гораздо чаще (если скорость шины 100 кГц, то полпериода длятся 5 мкс, за это время необходимо сделать несколько опросов), либо отслеживают фронты аппаратно (в случае микроконтроллеров получаем работу по прерываниям, а не по опросу. О прерываниях было сказано в работе №2).

Lab 5. Изучение быстропротекающих процессов с помощью цифровых осциллографов

Lab 6. Цифровые методы генерирования, регистрации и обработки сигналов

Для сдачи работы необходимо предоставить амплитудно-частотные характеристики всех чёрных ящиков и объяснить, какая АЧХ какой схеме соответствует.

Lab 7. Автоматизация контрольно-измерительной аппаратуры с помощью языка команд SCPI. Цифровая фильтрация

Lab 8. Термостат на базе цифровой системы автоматического регулирования

Прежде, чем переходить к ПИД-регулированию, я задаю следующие вопросы:

  1. Выведите на экран текущую температуру. Обоснуйте количество знаков после запятой.
  2. Нагреватель был выключен, комнатная температура неизменна. В момент времени t=0 нагреватель включают на полную мощность. Опишите поведение системы: по какому закону будет меняться температура от времени сразу после включения нагревателя? Через бесконечное время?
  3. В методичке просят поддерживать температуру в пределах ±0,1 °С, а минимальный период таймера в LabWindows составляет 1 мс. Докажите, что это вообще возможно. Для этого опишите систему аналитически, решите полученное дифференциальное уравнение, придумайте и проведите эксперимент, дающий численное значение постоянной времени системы.

Пишите на site@caesarion.ru чем больше, тем лучше: любые отзывы, пожелания, комментарии, исправления грамматических ошибок, предложения — всё, что связано с этим сайтом, как с содержанием, так и с технической стороной.

Сайт в «Архиве интернета»

Valid HTML 4.01 Strict Valid CSS!

Последнее изменение этой страницы: April 21 2020 04:23:57 UTC