Отчёт по практике Arduino. Отчет. Программирование микроконтроллеров в среде Arduino
Скачать 2.74 Mb.
|
1. В каком случае оператор && возвращает значение «истина»? Ответ: когда оба операнда истинны. 2. Что такое «дребезг»? Ответ: ложный сигнал, возникающий в момент замыкания или размыкания пластин кнопки. 3. Каким образом осуществляется борьба с дребезгом контактов в программе? Ответ: выставляется задержка в 10 мс. 4. Как можно избежать явного указания значения уровня напряженияпри вызове digitalWrite()? Ответ: в качестве параметра передаем булеву переменную (ledEnabled). Вывод:программно реализован триггер с предотвращением эффекта«дребезга контактов» кнопки, подключенной к плате Arduino. Упражнение №11. Светильник с кнопочным управлением Цель: увеличение яркости свечения светодиода по нажатию однойкнопки, и уменьшение по нажатию другой. Рисунок 11.1 – Схема электрическая принципиальная Рисунок 11.2 – Схема, собранная в программной среде SimulIDE 1. Код изменён: шаг изменения яркости настраивается в одном месте. #define PLUS_BUTTON_PIN 2 #define MINUS_BUTTON_PIN 3 #define LED_PIN 9 int brightness = 100;int Delta = 80; boolean plusUp = true;boolean minusUp = true; voidsetup() { pinMode(LED_PIN, OUTPUT); pinMode(PLUS_BUTTON_PIN, INPUT_PULLUP); pinMode(MINUS_BUTTON_PIN, INPUT_PULLUP);} voidloop() { analogWrite(LED_PIN, brightness); plusUp = handleClick(PLUS_BUTTON_PIN, plusUp, Delta); minusUp = handleClick(MINUS_BUTTON_PIN, minusUp, -Delta);} boolean handleClick(intbuttonPin, boolean wasUp, intdelta) { boolean isUp = digitalRead(buttonPin); if (wasUp&& !isUp) { delay(10); isUp = digitalRead(buttonPin); if(!isUp)brightness = constrain(brightness + delta, 0, 255); } returnisUp;} Листинг 11.1 – Листинг программы 2. Создана еще одна функция и переделан код так, чтобы одна функция отвечала за отслеживание нажатий, а другая – за вычисление яркости светодиода и возвращала его в analogWrite(). #definePLUS_BUTTON_PIN 2 #defineMINUS_BUTTON_PIN 3 #defineLED_PIN 9 int brightness = 100; int Delta = 80; boolean plusUp = true; boolean minusUp = true; voidsetup() { pinMode(LED_PIN, OUTPUT); pinMode(PLUS_BUTTON_PIN, INPUT_PULLUP); pinMode(MINUS_BUTTON_PIN, INPUT_PULLUP);} voidloop() { analogWrite(LED_PIN, brightness); plusUp = handleClick(PLUS_BUTTON_PIN, plusUp, Delta); minusUp = handleClick(MINUS_BUTTON_PIN, minusUp, -Delta); } boolean handleClick(intbuttonPin, boolean wasUp, intdelta) { boolean isUp = digitalRead(buttonPin); if (wasUp&& !isUp) { brightnessCalc(buttonPin, delta, isUp); } return isUp; } Void brightnessCalc(int buttonPin, int delta, bool isUp) { delay(10); isUp = digitalRead(buttonPin); if(!isUp)brightness = constrain(brightness + delta, 0, 255); } Листинг 11.2 – Листинг программы Ответынавопросы: 1. Что необходимо для определения собственной функции? Ответ: указать сигнатуру функции, её имя и выполняемый блок кода. 2. Что означает ключевое слово void? Ответ: означает, что функция не возвращает значения. 3. Как ведет себя программа при упоминании одной переменной с разных сторон от оператора присваивания = ? Ответ: присваивает новое значение, в зависимости от выражения с правой стороны. Вывод: Я научился увеличению яркости свечения светодиода по нажатию однойкнопки, и уменьшение по нажатию другой. Упражнение №12. Кнопочные ковбои Цель: программно-аппаратная реализация игры на реакцию: кто быстрее нажмет кнопку по сигналу. Рисунок 12.1 – Схема электрическая принципиальная Рисунок 12.2 – Схема, собранная в программной среде SimulIDE 1. Создан напряженный вариант игры: интервал между сигналами в диапазоне от 10 до 15 секунд. #define BUZZER_PIN 12 #define PLAYER_COUNT 2 int buttonPins[PLAYER_COUNT] = { 3, 5 }; int ledPins[PLAYER_COUNT] = { 9, 11 }; voidsetup() { pinMode(BUZZER_PIN, OUTPUT); for (int player = 0; player pinMode(ledPins[player], OUTPUT); pinMode(buttonPins[player], INPUT_PULLUP); } } voidloop() { delay(random(10000, 15000)); tone(BUZZER_PIN, 3000, 250); for (int player = 0; ; player = (player + 1) % PLAYER_COUNT) { if(!digitalRead(buttonPins[player])) { digitalWrite(ledPins[player], HIGH); tone(BUZZER_PIN, 4000, 1000); delay(1000); digitalWrite(ledPins[player], LOW); break; } } } Листинг 12.1 – Листинг программы 2. В игре есть лазейка: кнопку можно зажать до сигнала «пли!» и таким образом сразу же выиграть. Лазейка устранена. #define BUZZER_PIN 12 #define PLAYER_COUNT 2 int buttonPins[PLAYER_COUNT] = { 3, 5 }; int ledPins[PLAYER_COUNT] = { 9, 11 }; boolean btnChe[PLAYER_COUNT]; void setup() { pinMode(BUZZER_PIN, OUTPUT); for (int player = 0; player {pinMode(ledPins[player], OUTPUT); pinMode(buttonPins[player], INPUT_PULLUP);}} void loop() { delay(random(2000, 5000)); for (int i = 0; i btnChe[i] = digitalRead(buttonPins[i]); tone(BUZZER_PIN, 3000, 250); for (int player = 0; ; player = (player + 1) % PLAYER_COUNT) { if (btnChe[player] && !digitalRead(buttonPins[player])) { digitalWrite(ledPins[player], HIGH); tone(BUZZER_PIN, 4000, 1000); delay(1000); digitalWrite(ledPins[player], LOW); break;}}} Листинг 12.2 – Листинг программы 3. Добавлены в игру еще два «ковбоя». Рисунок 12.3 – Схема, собранная в программной среде SimulIDE #defineBUZZER_PIN 12 #definePLAYER_COUNT 4 int buttonPins[PLAYER_COUNT] = { 3, 10, 5,6 }; int ledPins[PLAYER_COUNT] = { 9, 11,4,7 }; boolean btnChe[PLAYER_COUNT]; voidsetup() { pinMode(BUZZER_PIN, OUTPUT); for (int player = 0; player { pinMode(ledPins[player], OUTPUT); pinMode(buttonPins[player], INPUT_PULLUP); } } voidloop() { delay(random(2000, 5000)); for (int i = 0; i btnChe[i] = digitalRead(buttonPins[i]); tone(BUZZER_PIN, 3000, 250); for (int player = 0; ; player = (player + 1) % PLAYER_COUNT) { if (btnChe[player] && !digitalRead(buttonPins[player])) { digitalWrite(ledPins[player], HIGH); tone(BUZZER_PIN, 4000, 1000); delay(1000); digitalWrite(ledPins[player], LOW); break; } }} Листинг 12.3 – Листинг программы Ответы на вопросы: 1. Можно ли поместить в один массив элементы типа boolean и int? Ответ: нет, так как C++ язык со строгой типизацией. 2. Обязательно ли при объявлении массива заполнять его значениями? Ответ: нет. 3. Чем удобно использование массива? Ответ: наглядность кода, возможность обработки в цикле. 4. Как обратиться к элементу массива, чтобы прочитать его значение? Ответ: по имени массива, с указанием индекса элемента. 5. Почему для хранения времени прошлого сигнала мы используем переменную типа long? Ответ: потому что longможет хранить числа до 2 147 483 647, это больше чем int. 6. Чем отличаются инструкции continue и break? Ответ: первый прерывает текущую итерациюи переходит к следующей, а второй выходит из цикла. Вывод: Я научился создавать программно-аппаратную реализацию игры на реакцию: кто быстрее нажмет кнопку по сигналу. Упражнение №13. Секундомер Цель: управление работой семисегментного светодиодного индикатора, подключенного к плате Arduino. Рисунок 13.1 – Схема электрическая принципиальная Рисунок 13.2 – Схема, собранная в программной среде Tinkercad 1. Изменён код - индикатор отсчитывает десятые доли секунды. #defineFIRST_SEGMENT_PIN 2 #defineSEGMENT_COUNT 7 byte numberSegments[10] = { 0b00111111, 0b00001010, 0b01011101, 0b01011110, 0b01101010, 0b01110110, 0b01110111, 0b00011010, 0b01111111, 0b01111110, }; voidsetup() { for (int i = 0; i pinMode(i + FIRST_SEGMENT_PIN, OUTPUT); } voidloop() { int number = (millis() / 100) % 10; int mask = numberSegments[number]; for (int i = 0; i boolean enableSegment = bitRead(mask, i); digitalWrite(i + FIRST_SEGMENT_PIN, enableSegment); } } Листинг 13.1 – Листинг программы 2. Изменена программа- вместо символа «0» отображался символ «А». #define FIRST_SEGMENT_PIN 2 #define SEGMENT_COUNT 7 byte numberSegments[10] = { 0b01111011, 0b00001010, 0b01011101, 0b01011110, 0b01101010, 0b01110110, 0b01110111, 0b00011010, 0b01111111, 0b01111110, }; voidsetup() { for (int i = 0; i pinMode(i + FIRST_SEGMENT_PIN, OUTPUT); } voidloop() { int number = (millis() / 1000) % 10; int mask = numberSegments[number]; for (int i = 0; i boolean enableSegment = bitRead(mask, i); digitalWrite(i + FIRST_SEGMENT_PIN, enableSegment); } } Листинг 13.2 – Листинг программы 3. Дополнена схема и программа- сегмент-точка включается при прохождении четных чисел и выключается при нечетных. #define FIRST_SEGMENT_PIN 2 #define SEGMENT_COUNT 8 byte numberSegments[10] = { 0b00111111, 0b00001010, 0b01011101, 0b01011110, 0b01101010, 0b01110110, 0b01110111, 0b00011010, 0b01111111, 0b01111110, }; voidsetup() { for (int i = 0; i < SEGMENT_COUNT; ++i) pinMode(i + FIRST_SEGMENT_PIN, OUTPUT); } voidloop() { int number = (millis() / 1000) % 10; digitalWrite(9, number % 2 == false); int mask = numberSegments[number]; for (int i = 0; i < SEGMENT_COUNT; ++i) { boolean enableSegment = bitRead(mask, i); digitalWrite(i + FIRST_SEGMENT_PIN, enableSegment); } } Листинг 13.3 – Листинг программы Ответы на вопросы: 1. К которой ножке семисегментного индикатора нужно подключать землю? Ответ: 3 или 8. 2. Каким образом закодированные символы цифр? Ответ: в бинарном виде. 3. Как символы выводятся на индикатор? Ответ: через порты светодиодного индикатора Вывод: Я научился управлять работой семисегментного светодиодного индикатора, подключенного к плате Arduino. Упражнение №14. Счетчик нажатий Цель: отображение на семисегментном индикаторе, подключенном кплате Arduino, количество нажатий на кнопку (единицы). Рисунок 14.1 – Схема электрическая принципиальная Рисунок 14.2 – Схема, собранная в программной среде SimulIDE 1. Теперь shiftOut() отправляет биты, начиная со старшего. Счетчик по-прежнему показывает арабские цифры. #define DATA_PIN 13 #define LATCH_PIN 12 #define CLOCK_PIN 11 #define BUTTON_PIN 10 int clicks = 0; boolean buttonWasUp = true; byte segments[10] = { 0b01111101, 0b00100100, 0b01111010, 0b01110110, 0b00100111, 0b01010111, 0b01011111, 0b01100100, 0b01111111, 0b01110111 }; byte seg2[10]; voidsetup() { pinMode(DATA_PIN, OUTPUT); pinMode(CLOCK_PIN, OUTPUT); pinMode(LATCH_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); } voidloop() { int f = 0; for (int i = 7; i >= 0; --i) { boolean pro = bitRead(segments[clicks], i); bitWrite(seg2[clicks], f, pro); ++f; } if (buttonWasUp && !digitalRead(BUTTON_PIN)) { delay(10); if(!digitalRead(BUTTON_PIN)) clicks = (clicks + 1) % 10; } buttonWasUp = digitalRead(BUTTON_PIN); digitalWrite(LATCH_PIN, LOW); shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, seg2[clicks]); digitalWrite(LATCH_PIN, HIGH); } Листинг 14.1 – Листингпрограммы 2. Исключена кнопка из схемы и подключён фоторезистор (потенциометр в SimulIDE) .Индикатор цифрой показывает уровень освещенности. Рисунок 14.3 – Схема, собранная в программной среде SimulIDE #defineLDR_PIN A0 #defineDATA_PIN 13 #defineLATCH_PIN 12 #defineCLOCK_PIN 11 byte segments[10] = { 0b01111101, 0b00100100, 0b01111010, 0b01110110, 0b00100111, 0b01010111, 0b01011111, 0b01100100, 0b01111111, 0b01110111 }; voidsetup() { pinMode(DATA_PIN, OUTPUT); pinMode(CLOCK_PIN, OUTPUT); pinMode(LATCH_PIN, OUTPUT); } voidloop() { int val = analogRead(LDR_PIN); int frequency = map(val, 0, 255, 0, 8); digitalWrite(LATCH_PIN, LOW); shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, segments[frequency]); digitalWrite(LATCH_PIN, HIGH); } Листинг 14.2 – Листингпрограммы Ответы на вопросы: 1. Для чего нужны микросхемы? Для чего нужен выходной сдвиговый регистр? Ответ: МС используются как «шаблон», выходной сдвиговый регистр дает возможность сократить количество задействованных цифровых выходов, используя всего 3 вместо 8. 2. Как найти ножку микросхемы, на которую отправляются данные? Ответ: чтобы понять, откуда считать ножки, нужно найти полукруглую выемку на одной из сторон. Если мы расположим 74HC595 выемкой влево, то в нижнем ряду будут ножки (слева направо) 1–8, а в верхнем 16–9. 3. Что нужно сделать до и после отправки собственно данных на 74HC595? Ответ: для записи в 74HC595 нужно притянуть пин строба к земле.Чтобы переданный байт отразился на выходах Qx - подать на пин строба высоки сигнал. 4. Сколько данных можно передать с помощью shiftOut() и как управлять порядком их передачи? Ответ: 8 бит за один цикл. Режим записи битов: LSBFIRST начиная с младшего, или MSBFIRST начиная со старшего бита. Вывод: Я научился отображать различные данные на семисегментном индикаторе, подключенном к плате Arduino. Упражнение №15. Комнатный термометр Цель: создание устройства, измеряющего температуру окружающей среды и показывающего с помощью шкалы, на сколько градусов она превышает заданный порог. Рисунок 15.1 – Схема электрическая принципиальная Рисунок 15.2 – Схема, собранная в программной среде SimulIDE 1. Изменён код программы таким образом, чтобы индикатор включался при 0°С и его показания прирастали на одно деление каждые 5°С. #include #defineFIRST_LED_PIN 2 #defineLED_COUNT10 #defineTERMIST_B 4300 #defineVIN 5.0 voidsetup() { for (int i = 0; i voidloop() {float voltage=analogRead(A0)*VIN/1023.0;float r1=voltage/(VIN - voltage); float temperature = 1./(1./(TERMIST_B)*log(r1) + 1. / (25. + 273.)) - 273; for (int i = 0; i boolean enableSegment = (temperature >= 5 * i); digitalWrite(i + FIRST_LED_PIN, enableSegment);}} Листинг 15.1 – Листингпрограммы 2. Добавлен в схему пьезодинамик: при достижении температуры 25°С срабатывает звуковая сигнализация. #include #define FIRST_LED_PIN 2 #define LED_COUNT10 #define TERMIST_B 90000 #define VIN 5.0 Void setup() { for (int i = 0; i Void loop() { float voltage=analogRead(A0)*VIN/1023.0; float r1=voltage/(VIN - voltage); float temperature = 1./(1./(TERMIST_B)*log(r1) + 1. / (25. + 273.)) - 273; if (temperature >= 25) tone(12, 3500, 20); for (int i = 0; i boolean enableSegment = (temperature >= 5 * i); digitalWrite(i + FIRST_LED_PIN, enableSegment);}} Листинг 15.2 – Листингпрограммы Рисунок 15.3 – Схема, собранная в программной среде SimulIDE Ответы на вопросы: |