Отчёт по практике Arduino. Отчет. Программирование микроконтроллеров в среде Arduino
Скачать 2.74 Mb.
|
1. Как нужно подключить термистор, чтобы получать на Arduino данные о температуре? Ответ: к пину А0. 2. Каким образом можно воспользоваться ранее разработанными функциями, не переписывая их в программный код? Ответ: подключить библиотеку. 3. Чем неудобно использование чисел с плавающей точкой на Arduino? Ответ: Эти числа имеют небольшую точность, а их использование в логических выражениях может привести к ошибкам в работе программы. 4. Можно ли записать инструкции объявления переменной temperature и формулу для ее расчета на одной строке, как это сделано для voltage? Ответ: да, можно. 5. Что за выражение стоит справа от = при объявлении булевой переменной enableSegment? Ответ: логическое выражение, возвращающее булево значение. Вывод: Я научился создавать простые измерительные устройства, выводящие показания на шкалу. Упражнение №16. Метеостанция Цель: организовать передачу данных об измеренной температуре накомпьютер. Рисунок 16.1 – Схема электрическая принципиальная Рисунок 16.2 – Схема, собранная в программной среде SimulIDE 1. Перед таблицей данных о температуре добавьте заголовок (например, "Meteostation"). #include int minute = 1; #define TERMIST_B 4300 #define VIN 5.0 Void setup(){ Serial.begin(9600); Serial.println("Meteostation"); Serial.println("Minute\tTemperature"); } Void loop(){ float voltage = analogRead(A0) * VIN / 1024.0; float r1 = voltage / (VIN - voltage); float temperature = 1. / (1. / (TERMIST_B)*log(r1) + 1. / (25. + 273.)) - 273; Serial.print(minute); Serial.print("\t"); Serial.println(temperature); delay(60000); ++minute; } Листинг 16.1 – Листингпрограммы 2. Добавьте столбец, содержащий количество секунд, прошедших с момента запуска микроконтроллера. #include int minute = 1; #defineTERMIST_B 4300 #defineVIN 5.0 voidsetup(){ Serial.begin(9600); Serial.println("Minute\tSec\tTemperature"); } voidloop(){ float voltage = analogRead(A0) * VIN / 1024.0; float r1 = voltage / (VIN - voltage); float temperature = 1. / (1. / (TERMIST_B)*log(r1) + 1. / (25. + 273.)) - 273; Serial.print(millis() / 1000 / 60); Serial.print("\t"); Serial.print(millis() / 1000); Serial.print("\t"); Serial.println(temperature); delay(1000); ++minute; } Листинг 16.2 – Листингпрограммы Ответы на вопросы: 1. Какие действия нужно предпринять, чтобы читать на компьютереданные с Arduino? Ответ: нужно открыть SerialMonitorв SimulIDE. 2. О каких ограничениях не следует забывать при работе с последовательным портом? Ответ:невозможно использовать цифровые порты 0 и 1 одновременно с передачей данных по последовательному порту. 3. Как избежать ошибки в передаче данных, содержащих обратныйслеш (\)? Ответ: обратный слэш нужно экранировать, продублировав его(\\). Вывод: Я научился организовывать передачу данных с платы Arduino накомпьютер. Упражнение №17. Пантограф Цель: поворот сервопривода на угол, задаваемый потенциометром. Рисунок 17.1 – Схема электрическая принципиальная Рисунок 17.2 – Схема, собранная в программной среде SimulIDE 1. Изменена программатак, чтобы по мере поворота ручки потенциометра, сервопривод последовательно занимал 8 положений: 45, 135, 87, 0,65, 90, 180, 150°. #include Servo myServo; void setup() {myServo.attach(9);} void loop() { int val = analogRead(A0); if ((val <= 127)&&(val >= 0)) myServo.write(45); if ((val <= 255)&&(val >= 128)) myServo.write(135); if ((val <= 383)&&(val >= 256)) myServo.write(87); if ((val <= 511)&&(val >= 384)) myServo.write(0); if ((val <= 639)&&(val >= 512)) myServo.write(65); if ((val <= 767)&&(val >= 640)) myServo.write(90); if ((val <= 895)&&(val >= 768)) myServo.write(180); if ((val <= 1022)&&(val >= 896)) myServo.write(150); } Листинг 17.1 – Листингпрограммы 2. Cервопривод управляет ‘шторкой’, и поддерживает постоянное количество ‘света’ в помещении. Рисунок 17.3– Схема, собранная в программной среде SimulIDE #include #define POT_MAX_ANGLE 270.0 Servo myServo; Void setup() {myServo.attach(9);} Void loop() {int val = analogRead(A0); int angle = int(val / 1024.0 * POT_MAX_ANGLE); angle = constrain(angle, 0, 180); myServo.write(angle); } Листинг 17.2 – Листингпрограммы Ответы на вопросы: 1. Зачем нужен конденсатор при включении в схему сервопривода? Ответ: Конденсатор нужен чтобы при включениисервопривода избежать просадки питания платы. 2. Каким образом библиотека Servo.h позволяет работать с сервоприводом? Ответ: в программе использованы методы .attach(pin) и write(angle) из этой библиотеки. 3. Зачем ограничивается область допустимых значений для angle? Ответ: угол поворот сервопривода ограничен 180 градусами, отсюда следует и программное ограничение. 4. Как быть уверенным в том, что в переменную типа int после вычислений попадет корректное значение? Ответ: в программе используется функция int() для явного приведения типов. Вывод: Я научился управлять поворотом сервопривода на угол, задаваемый потенциометром. Упражнение №18. Тестер батареек Цель: вывод на жидкокристаллический дисплей данных о напряжении,измеренном на батарейке. Рисунок 18.1 – Схема электрическая принципиальная Рисунок 18.2 – Схема, собранная в программной среде Tinkercad 1. Создан секундомер, отсчитывающий время, прошедшее с начала работы Arduino. Секунды и сотые доли секунд выводятся на экран. #include #define DIODE_DROP 0.7 LiquidCrystal lcd(13, 12, 11, 10, 9, 8); Void setup() { lcd.begin(16, 2); lcd.print("Timer:"); } Void loop() { float sec = (float)millis() / (float)1000; lcd.setCursor(0, 1); lcd.print(sec, 2); lcd.print(" Sec."); } Листинг 18.1 – Листингпрограммы 2. Совмещены отсчет времени и измерение напряжения. Все данные отображаются на дисплее и отправляются на компьютер раз в 10 секунд. #include #defineDIODE_DROP 0.7 LiquidCrystal lcd(13, 12, 11, 10, 9, 8); int count = 0; voidsetup() { lcd.begin(16, 2); Serial.begin(9600); Serial.println("Sec\tVoltage"); } voidloop() { float voltage = analogRead(A0) / 1024.0 * 10.0; if (voltage > 0.1) voltage += DIODE_DROP; lcd.setCursor(0, 0); lcd.print(voltage, 2); lcd.print(" Volts"); float sec = (float)millis() / (float)1000; lcd.setCursor(0, 1); lcd.print(sec, 2); lcd.print(" Sec."); if (count == millis() / 10000) { Serial.print(millis() / 1000); Serial.print("\t"); Serial.println(voltage); count++; } } Листинг 18.2 – Листингпрограммы Ответы на вопросы: 1. Из-за чего измерения напряжения в этом эксперименте могут бытьнеточными (на что можно повлиять)? Ответ: на диоде, защищающем от неверной полярности, падает доля напряжения. 2. Какая библиотека облегчает работу с текстовым экраном? Какие шаги нужно предпринять до начала вывода текста на него? Ответ: библиотека LiquidCrystal.h, объявляем объект, для управления дисплеем, необходимо указать номера пинов, к которым он подключен в порядке: RS E DB5 DB6 DB7 DB8 (LiquidCrystal lcd(13, 12, 11, 10, 9, 8)). Сообщаем объекту количество строк и столбцов, вызвав begin() lcd.begin(16, 2); 3. Каким образом задается позиция, с которой на экран выводитсятекст? Ответ: положение курсора задается методом lcd.setCursor(0, 1), с указанием строки и столбца. Вывод: мы научились выводить на жидкокристаллический дисплей данные о напряжении, измеренные на батарейке. Упражнение №19. Светильник, управляемый по USB Цель: управление светодиодом, подключенного к плате Arduino, передавая команды через интерфейс USB. Рисунок 19.1 – Схема электрическая принципиальная Рисунок 19.2 – Схема, собранная в программной среде SimulIDE 1. Проверьте, попадает ли переданное число в диапазон значений, которые нужно передавать в analogWrite(). Передайте на компьютер сообщение об ошибке, если нет. #define LED_PIN 9 String message; void setup() { pinMode(LED_PIN, OUTPUT); Serial.begin(9600);} void loop() {if (Serial.available()>0) { char letter = Serial.read(); if (letter >= 48 && letter <= 57) {int msg = map(letter, 48, 57,0, 255); analogWrite(9, msg);} else Serial.println("error!");}} Листинг 19.1 – Листингпрограммы 2. Переделайте программу так, чтобы устройство распознавало текстовые команды, например, «on» и «off», и соответственно включало и выключало светодиод. #define LED_PIN 9 char letter; String msg = ""; void setup() { pinMode(LED_PIN, OUTPUT); Serial.begin(9600);} void loop() { while (Serial.available()) { letter = Serial.read(); msg += letter; delay(100); if (msg == "on"); digitalWrite(LED_PIN, HIGH); if (msg == "off") digitalWrite(LED_PIN, LOW);} Serial.println(msg); msg = "";} Листинг 19.2 – Листингпрограммы Ответы на вопросы: 1. Какие объекты позволяют легко манипулировать текстовыми данными? Ответ: объекты String. 2. Что возвращают методы Serial.available() и Serial.read()? Ответ: Метод available() объекта Serial возвращает количество байт, полученных через последовательный порт. В данной работе получаем символ методом Serial.read(), который возвращает первый байт, пришедший на последовательный порт, или -1, если ничего не пришло. 3. Чем отличаются конструкции for и while? Ответ:в цикле forесть встроенный счетчик. 4. Каким образом можно организовать более сложное ветвление, чемif … else? Ответ: с помощью switch(). 5. Как можно объединить текстовые строки? Ответ: с помощью конкатенации msg += sym 6. Как можно привести текстовую строку, содержащую цифры, к числовому типу? Ответ: использовать метод toInt(). Вывод: мы научились управлять светодиодом, подключенного к плате Arduino, передавая команды через интерфейс USB. Упражнение №20. Перетягивание каната Цель: создать игру, в которой нужно быстрее соперника нажать кнопку 20 раз. Рисунок 20.1 – Схема электрическая принципиальная Рисунок 20.2 – Схема, собранная в программной среде Tinkercad 1. Вместо светодиодной шкалы подключил сервопривод и изменил код таким образом, чтобы перетягивание демонстрировалось путем отклонения сервопривода от среднего положения. Рисунок 20.3 – Схема, собранная в программной среде Tinkercad #include #defineBUZZER_PIN 0 #defineBAR_COUNT 10 #defineMAX_SCORE 20 volatileint score = 0; Servo myServo; voidsetup() { pinMode(BUZZER_PIN, OUTPUT); attachInterrupt(INT1, pushP1, FALLING); attachInterrupt(INT0, pushP2, FALLING); myServo.attach(9);} void pushP1() { score++; } void pushP2() { score--; } voidloop() { myServo.write(90); tone(BUZZER_PIN, 200, 100); while (abs(score) int delta = score * 4; int angle = 90 + delta; myServo.write(angle); } tone(BUZZER_PIN, 4000, 1000); while (true) {}} Листинг 20.1 – Листингпрограммы 2. Изменил исходный код программы так, чтобы после определения победителя нажатие любой кнопки перезапускало бы игру. #define BUZZER_PIN 0 #define FIRST_BAR_PIN 4 #define BAR_COUNT 10 #define MAX_SCORE 20 volatile int score = 0; void setup() {for (int i = 0; i < BAR_COUNT; ++i) pinMode(i + FIRST_BAR_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); attachInterrupt(INT1, pushP1, FALLING); attachInterrupt(INT0, pushP2, FALLING);} void pushP1() { score++; } void pushP2() { score--; } void loop() {tone(BUZZER_PIN, 2000, 1000); while (abs(score) < MAX_SCORE) { int bound = map(score, -MAX_SCORE, MAX_SCORE,0, BAR_COUNT); int left = min(bound, BAR_COUNT / 2 - 1); int right = max(bound, BAR_COUNT / 2); for (int i = 0; i < BAR_COUNT; ++i) digitalWrite(i + FIRST_BAR_PIN,i >= left && i <= right);} tone(BUZZER_PIN, 4000, 1000); while (digitalRead(2) || digitalRead(3)) {score = 0;,noTone(BUZZER_PIN);}} Листинг 20.2 – Листингпрограммы Ответынавопросы: 1. Каким образом подавляется дребезг контактов в этом упражнении? Ответ: схема подключения кнопок с использованием конденсаторов, резисторов и микросхемы 74HC14, называемая инвертирующим триггером Шмитта, необходима для аппаратного подавления дребезга контактов. 2. Для чего используются прерывания? Ответ: прерывание приостанавливает основную программу, выполняет заданную функцию, а затем возобновляет основную программу. По-заданию необходимо прерывание на нажатие кнопки, т.е. при смене сигнала с высокого на низкий. 3. Каким образом можно включить обработку внешних прерываний? Ответ:Arduino Uno позволяет производить прерывания на портах 2 и 3. В setup() прописывается инструкция attachInterrupt(interrupt, action, event), где – interrupt может принимать значения INT0 или INT1 для портов 2 и 3 соответственно. 4. О каких нюансах работы следует помнить при работе с прерываниями? Ответ: глобальные переменные, к которым осуществляется обращение из функции, обрабатывающей прерывания, должны объявляться с использованием ключевого слова volatile.Внутри функции, вызываемой по прерыванию, нельзя использовать delay(). 5. Как выбрать максимальное из двух значений? Минимальное? Ответ: функция min(val1, val2) возвращает меньшее из val1 и val2. Функция max(val1, val2) возвращает большее из val1 и val2. 6. Как получить абсолютное значение переменной? Ответ: функция abs(value) возвращает абсолютное значение value. 7. Возможно ли в этой схеме организовать передачу данных через последовательный интерфейс? Ответ: Так как в данном упражнении необходимо большое количество цифровых портов, то приходится задействовать и порт 0. Так как он соединен с одним из каналов последовательного порта, то перед прошивкой микроконтроллера придется отключать провод, ведущий к пьезодинамику, а после прошивки подключать его обратно. Вывод: мы создали игру, в которой для победы нужнонажать кнопку 20 раз быстрее, чем соперник. |