Что нельзя делать с arduino: 10 способов убить контроллер

Мы купили Arduino Pro Mini, что делать дальше? — DRIVE2

Когда меня спрашивают: “Хочу научится программировать микроконтроллеры, с чего начать, что купить?”, то с моей точки зрения ответ однозначен: “Покупаем Arduino Pro Mini и пробуем, если все получается — переходим к более сложным вещам”.

Что такое Ардуино

Несмотря на название раздела не буду рассказывать, что такое Ардуино и откуда оно взялось, так как привел в свое время неплохую статью об этом — www.drive2.ru/b/2520138/ .

Просто вспомним, что под понятием Ардуино обычно понимают совокупность трех вещей: платы или платформы Arduino (в данном случае Arduino Pro Mini), среды разработки Arduino IDE и языка программирования C++ с набором специальных библиотек.

Любую из этих трех вещей мы можем подменить на аналог, но об этом мы поговорим позже. А пока просто скачаем Arduino IDE с официального сайта — www.arduino.cc/en/Main/Software и установим его на компьютер.

Что же мы купили?

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

Верхняя плата — это собственно и есть Arduino Pro Mini, нижняя — USB-UART / USB-TTL конвертер
Последний может выглядеть не так, как на фото, а иметь вид готового кабеля.

(Лично я советовал бы выбрать первый вариант, но это как говорится на вкус и цвет …)

Теперь о плате/платформе Arduino Pro Mini: Конструктивно она представляет собой плату с распаянным на ней микроконтролером, кнопкой RESET, микросхемой питания и прочей, не существенной для нас на данном этапе, периферией.
Существует две версии Pro Mini: одна работает от 3.

3В при частоте 8 МГц, другая — от 5В при 16 МГц. В основе платы лежит микроконтроллер Atmega 168 или Atmega 328 — отличие между ними заключается в объеме внутрисистемно программируемой Flash памяти — 16 или 32 кБайта. Это так называемая “память программ”, т.е.

память в которую будет записана программа и содержимое ее не будет изменятся в процессе работы. Напомню, что Atmega построен по так называемой Гарвардской архитектуре (www.drive2.ru/b/2506495/) в которой “память программ” и “память данных” реализованы отдельно, для большего быстродействия и надежности.

“Память данных” делится на 2 части: оперативную SRAM, которая что у 168, что у 328 составляет 1 Кб, и постоянную EEPROM (Electrically Erasable Programmable Read-Only Memory) объемом 512 байт, данные из которой не “теряются” при отключении питания.

В зависимости от исполнения на плате может быть 30, 32 или 34 вывода (PIN). На картинке ниже показана”максимальный” 34 пиновый вариант

Посмотрели? Страшно? Давайте разберемся что где.
GND — это у нас выводы куда подключается “земляные” провода, т.е. приходит/выводится “-” питания
VCC — плюсовые выводы для питания платы напряжением 5В (иногда 3,3В). Таке этот вывод моно использовать для подачу “наружу” опорного напряжение для цифровых входов.

RAW — вывод используется, если у нас нет стабилизированного напряжения 5В, но есть постоянное в диапазоне от 7 до 12В. Иногда указывают максимальное значение 30В — т.е. то напряжение которое микросхема питания может выдержать непродолжительное время не перегреваясь.

Помним, что в автомобиле диапазон напряжений от 12 до 15,5В, поэтому подключать RAW к “+” авто напрямую нельзя и нужно собрать схему по питанию следующего вида:

В принципе, заменив микросхему 7812 на 7805, можно питать Pro Mini и через вывод VCC

TXD и RXD — выводы UART/USART — www.drive2.ru/b/2602560/
RST — он же RESET — в мануале написано насчет него написано следующее “низкий уровень сигнала на выводе перезагружает микроконтроллер.

Обычно применяется для подключения кнопки перезагрузки на плате расширения, закрывающей доступ к кнопке на самой плате Arduino”. На деле это означает что когда этот вывод подключается к земле, происходит перезапуск (сброс) Arduino Pro Mini.

Выводы обозначенные на плате цифрами с 2 до 13 — цифровые выводы (Обязательно читаем — www.drive2.ru/b/2528993/), могут настраиваться как вход или выход. Выводы работают при напряжении 3,3 В. Каждый вывод имеет нагрузочный резистор (стандартно отключен) 20-50 кОм и может пропускать до 40 мА.

Они могут выводить значения только высокого (3,3В или 5В в зависимости от версии) или низкого (0В) уровня. Некоторое из них обозначенные на схеме выше как PWM могут выводить ШИМ сигнал (www.drive2.ru/b/2558797/) с разрешением 8 бит (от 0 до 255)
Выводы А0-А7 — аналоговые входы с 10 битным АЦП (www.

drive2.ru/b/2558839/). В зависимости от исполнения платы их может быть от 4 до 8. Эти выводы могут также работать как цифровые.
DTR (Data Terminal Ready) — Готовность приемника данных.

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

Подключаемся

Схема подключения достаточно простая и ошибиться достаточно сложно

Единственное что посоветую использовать не идущие в комплекте провода, а купить разъем питания на 6 контактов с шагом контактов 2,54мм. Он называется NS25 — 2,54 мм и такой же на 5 контактов для подключения к USB-UART / USB-TTL конвертеру.

После подключения у меня получилось так

Можно выпаять гребенку на конвертере и припаяться проводами непосредственно к плате — это позволит отказаться от одного из разьемных соединений и защитить конвертер, одев на него термоусадку.

Как видно используется только по 4 провода — это связано с тем, что у меня на обоих конвертерах нет вывода DTR

Что такое DTR и что делать если его нет?

Данный вывод предназначен для того, чтобы USB-serial контроллер Arduino перезагружал МК каждый раз, когда терминальная программа (в т.ч. Serial monitor, встроенный в ПО Arduino IDE) устанавливает соединение. Реализовано это следующим образом: у USB-serial контроллера вывод DTR (Data Terminal Ready) связан с выводом RESET.

Если программа, работающая с виртуальным последовательным портом, использует DTR, то при установке соединения МК перезагружается.Само по себе это обеспечивает беспроблемную загрузку скетча из Arduino IDE — МК перезагружается перед загрузкой кода. В этом смысле автоматическая перезагрузка облегчает жизнь. Кроме того, перезагрузка при подключении терминала тоже может оказаться удобной, т.к.

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

В случае, если этот вывод отсутствует, то у нас есть 3 варианта1) Купить другой конвертер 🙂

2) Распаять вывод самому. (Как это сделать написано здесь — new-tech.in.ua/tips/109-usb-uart-converter)

3) Отправлять на перезагрузку вручную при помощи кнопки RESET расположенной на плате — об этом ниже.

Подключаем плату к компьютеру

Я не буду рассказывать как устанавливать драйвера конвертера и Arduino IDE — все достаточно стандартно.
Если все сделали правильно, то при подключении конвертера в системе появится виртуальный СОМ — порт. Это легко увидеть:

На правой картинке появляется дополнительный порт СОМ10 (у вас номер может быть другим) — его нужно выбрать, клацнув по нему мышкой.Далее проверяем правильность указания платы, программатора — все должно быть как на картинке выше.

Указываем микроконтроллер 168 или 328, 5В или 3,3В

Почувствуем себя программистами

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

Читайте также:  Kit-наборы raspberry pi: обзор лучших вариантов

Листинг программы:

//Процедура инициализацииvoid setup() {// инициализируем вывод 13 на вывод.pinMode(13, OUTPUT);

}

// Основное тело программыvoid loop() {digitalWrite(13, HIGH); // включаем светодиод (Подаем сигнал высокого уровня на вывод 13)delay(500); // ждем 500 милисекунд (в стандартном примере 1000, что означает одну секунду)digitalWrite(13, LOW); // выключаем светодиод (Подаем сигнал низкого уровня на вывод 13)delay(500); // ждем 500 милисекунд после чего идем опять в начало основной программы}
Данная программа будет выполняться по кругу пока включен микроконтроллер.

“Заливаем” программу

Тут все просто — нажимаем на кнопочку “вгрузить”

Если вывод DTR не подключен, то нажимаем на плате кнопку RESET и не отпускаем пока внизу окна Arduino IDE не появится надпись “вгружаем” — этот момент важно не пропустить, иначе микроконтроллер не будет своевременно перезагружен и заливка программы не состоится. Если DTR подключен, то просто ждем

Если все мы сделали правильно, то вскоре мы увидим надпись “вгрузили” и светодиод начнет мигать с периодом 0,5с.

Послесловие

Я не рассказывал как припаивать “гребенку” к плате — если вы не умеете это делать, то сначала научитесь паять.
Как подключать всевозможную периферию можно подглядеть здесь — www.drive2.ru/c/1735998/
И вообще очень рекомендую к прочтению книгу Улли Соммер “Программирование микроконтроллерных плат Arduino/Freeduino” (она есть в интернете и ее несложно найти).

Источник: https://www.drive2.com/b/2642464/

Секретный вольтметр в Arduino — измерение напряжения батареи средствами микроконтроллера

В основном перевод статьи Secret Arduino Voltmeter – Measure Battery Voltage с некоторыми дополнениями.

Мало известная фишка Ардуино и многих других AVR чипов это возможность измерить внутренний источник опорного напряжения 1.1 В.

Эта функция может быть использована для повышения точности функции Arduino — analogRead () при использовании стандартного опорного напряжения 5 В (на платформах с напряжением питания 5 В) или 3.3 В (на платформах с напряжением питания 3.3 В).

Она также может быть использована для измерения Vcc, поданного на чип, обеспечивая средство контроля напряжения батареи без использования драгоценных аналоговый выводов.

Мотивация

Есть, по крайней мере, две причины для измерения напряжения, питающего наш Arduino (Vcc). Одним из них является наш проект, питающийся от батареи, если мы хотим следить за уровнем напряжения батареи.

Кроме того, когда питание от батареи (Vcc) не может быть 5,0 вольт(например питание от 3-х элементов 1.

5 В), а мы хотим сделать аналоговые измерения более точными — мы должны использовать либо внутренний источник опорного напряжения 1,1 В либо внешний источник опорного напряжения. Почему?

Обычно предполагают при использовании analogRead () то, что аналоговое напряжение питания контроллера составляет 5.0 вольт, когда в действительности это может быть совсем не так(например питание от 3-х элементов 1.5 В).

Официальная документация Arduino даже может привести нас к этому неправильному предположению. Дело в том, что питание не обязательно 5,0 вольт, независимо от текущего уровня это питание подано на Vcc чипа.

Если наше питание не стабилизировано или если мы работаем от аккумулятора, это напряжение может меняться совсем немного. Вот пример кода, иллюстрирующий эту проблему:

double Vcc = 5.0; // не обязательно правда int value = analogRead(0); / читаем показания с А0 double volt = (value / 1023.0) * Vcc; // верно только если Vcc = 5.0 вольт Для того чтобы измерить напряжение точно, необходимо точное опорное напряжение. Большинство чипов AVR обеспечивает три источника опорного напряжения:

  • внешний источник опорного наптяжения, на ардуинке подписан  AREF. Выбор: analogReference(EXTERNAL);
  • Vcc — источник питания самого контроллера. Выбор: analogReference(DEFAULT).

В Arduino нельзя просто взять и подключить Vcc к аналоговому пину напрямую — по умолчанию AREF связан с Vcc и вы всегда будете получать максимальное значение 1023, от какого бы напряжения вы не питались. Спасает подключение к AREF источника напряжения с заранее известным, стабильным напряжением, но это — лишний элемент в схеме.

Еще можно соединить Vcc с AREF через диод: падение напряжение на диоде заранее известно, поэтому вычислить Vcc не составит труда. Однако, при такой схеме через диод постоянно протекает ток, сокращая жизнь батареи, что тоже не очень удачно.

Источник внешнего опорного напряжения является наиболее точным, но требует дополнительных аппаратных средств. Внутренний ИОН стабильным, но не точен + / — 10% отклонение. Vcc является абсолютно ненадежен в большинстве случаев.

Выбор внутреннего источника опорного напряжения является недорогим и стабильным, но большую часть времени, мы хотели бы измеряет большее напряжение чем 1.1 В, так что использование Vcc является наиболее практичным, но потенциально наименее точным.

В некоторых случаях оно может быть очень ненадежным!

Как это сделать

Многие чипы AVR включая серию ATmega и ATtiny обеспечивают средства для измерения внутреннего опорного напряжения. Зачем это нужно? Причина проста — путем измерения внутреннего напряжения, мы можем определить значение Vcc. Вот как:

  1. Установить источник опорного напряжения по умолчанию: analogReference(DEFAULT); . Используем как источник — Vcc.
  2. Снять показания АЦП для внутреннего источника 1.1 В.
  3. Расчитать значение Vcc основываясь на измерении 1.1 В по формуле:

Vcc * (Показания АЦП) / 1023 = 1.1 В

Из чего следует:

Vcc = 1,1 В * 1023 / (Показания АЦП)

Собираем все вместе и получаем код:

long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(75); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low  = ADCL; // must read ADCL first – it then locks ADCH   uint8_t high = ADCH; // unlocks both long result = (high

Источник: http://blog.unlimite.net/?p=25

Arduino UNO урок 3 – Тайминг

Обратимся к первому уроку, где мы управляли LED. Между включением и выключением которого была секундная задержка.

В используемой там программе (см. код ниже) был один очень большой недостаток. Для выдержки паузы между вкл/выкл LED в 1 сек. нами была использована функция delay(). В это время контроллер не может выполнять другие команды в главной функции loop()

/* Мигание LED * ———— * * Включает и выключает светодиод (LED) подсоединенный * к выходу 13, с интервалом в 2 секунды * */ int ledPin = 13; // LED подсоединен к выводу 13 void setup()
{ pinMode(ledPin, OUTPUT); // устанавливаем вывод 13 как выход
} void loop()
{ digitalWrite(ledPin, HIGH); // включаем LED delay(1000); // пауза 1 секунда digitalWrite(ledPin, LOW); // выключаем LED delay(1000); // пауза 1 секунда
}

Первое, что мы сделаем, это внесем небольшие корректировки в функцию loop(). Чтобы сделать код более компактным и изящным, заменим 2 пары строчек на одну пару. Вместо установки значения в HIGH, а затем обратно в LOW, мы получим текущее значение ledPin и проинвертируем его. Т.е. если оно было HIGH, то станет LOW и наоборот.

void loop()
{ digitalWrite(ledPin, !digitalRead(ledPin)); // включаем/выключаем LED delay(1000); // задержка 1 сек.
}

Отлично! Теперь мы усовершенствуем функцию delay(). Взамен, мы будем использовать функцию millis(). Данная функция возвращает количество миллисекунд, прошедшее с момента запуска текущей программы. Функция переполнится (вернется в нуль) приблизительно через 50 суток работы программы.

Альтернативной функцией является micros(), которая возвращает количество микросекунд, прошедшее с момента запуска текущей программы. Функция переполнится (вернется в нуль) приблизительно через 70 минут работы программы.

В нашем уроке мы будем использовать функцию millis():

/* Мигание LED Версия 2 * ———————— * Включает и выключает светодиод (LED) подсоединенный * к выходу 13, с интервалом в 2 секунды используя функцию millis() * */
int ledPin = 13; // LED подсоединен к выводу 13
unsigned long currentTime;
unsigned long loopTime; void setup()
{ pinMode(ledPin, OUTPUT); // устанавливаем вывод 13 как выход currentTime = millis(); // считываем время, прошедшее с момента запуска программы loopTime = currentTime; } void loop()
{ currentTime = millis(); // считываем время, прошедшее с момента запуска программы if(currentTime >= (loopTime + 1000)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда digitalWrite(ledPin, !digitalRead(ledPin)); // включаем/выключаем LED loopTime = currentTime; // в loopTime записываем новое значение } // Здесь могут быть другие команды
}

Читайте также:  Управление движением робота с одного джойстика

В данном примере мы ввели две дополнительные переменные currentTime и loopTime. В функции setup() обе переменные имеют одно и тоже значение.

В функции loop(), переменная currentTime каждый раз обновляется в цикле.

Когда currentTime больше чем loopTime на 1 секунду (loopTime + 1000), то LED меняет свое состояние, а переменной loopTime присваивается текущее значение currentTime.

Обратите внимание, что в данном примере мы не использовали функцию delay() и процессор может выполнять другие операции.

Оригинал статьи на английском языке (перевод Колтыков А.В. для сайта cxem.net)

Оригинал статьи

Источник: http://cxem.net/arduino/arduino5.php

Подключение двигателей к Arduino

Рассмотрим подключение электродвигателя постоянно тока к Arduino. У электродвигателя 2 контакта и чтобы заставить его работать, нужно к одному контакту подвести питание, а к другому — землю.

При этом, если поменять полярность, то мотор будет крутиться в противоположную сторону.

Однако, эта простота только видима, ведь моторы нельзя напрямую подключать к микроконтроллеру!

Для управления двигателями применяют драйверы двигателей. Мы будем использовать драйвер L293D.

Чтобы правильно подключить драйвер нужно знать его распиновку (какая нога за что отвечает).

Обратите внимание на выемку с одной стороны. Она нужна для позиционирования микросхемы. На схеме выемка находится вверху.

L293D может управлять двумя моторами, условно левая половина для одного мотора, правая — для другого. Рассмотрим назначение каждой ножки драйвера.

Enable 1,2 — включает/выключает возможность управления мотором с левой стороны. Зачастую имеет смысл держать его включенным (подавать 5в).

Input 1 и 2 — подключаются к портам Arduino и управляют работой мотора с левой стороны.

Output 1 и 2 — к этим ножкам подводятся контакты первого мотора.

GND — земля.

Vcc 2 — питание моторов (5в либо сколько необходимо моторам).

Vcc 1 — питание драйвера (5в).

Input 3 и 4 — подключаются к портам Arduino и управляют работой мотора с правой стороны.

Output 3 и 4 — к этим ножкам подводятся контакты второго мотора.

Enable 3,4 — включает/выключает возможность управления мотором с правой стороны. Зачастую имеет смысл держать его включенным (подавать 5в).

Вот более наглядная схема:

RA 0, 1, 2, 3 — подключаются к портам Arduino.

Теперь рассмотрим подключение и управление 1 и 2 моторами.

Подключим мотор к пинам 7 и 8.

Для управление вращением используется знакомая вам команда digitalWrite, только мы должны посылать сигнал на каждый порт, при этом один должен быть HIGH, а другой — LOW.

Если же нужно остановить мотор, то на оба порта посылаем LOW. Напишем программу, которая вращает мотор в одну сторону, останавливает его на 1 секунду, вращает в другую сторону и снова останавливает на 1 секунду.

123456789101112131415161718192021222324252627282930 int m1 = 7; // 1 контакт мотораint m2 = 8; // 2 контакт мотораvoid setup() {  // обозначаем порты как выходы  pinMode (m1, OUTPUT);  pinMode (m2, OUTPUT);}void loop() {  // запускаем мотор в одну сторону на секунду  digitalWrite(m1, HIGH);  digitalWrite(m2, LOW);  delay(1000);  // останавливаем мотор на секунду  digitalWrite(m1, LOW);  digitalWrite(m2, LOW);  delay(1000);  // запускаем мотор в другую сторону на секунду  digitalWrite(m1, LOW);  digitalWrite(m2, HIGH);  delay(1000);  // останавливаем мотор на секунду  digitalWrite(m1, LOW);  digitalWrite(m2, LOW);  delay(1000);}

Теперь подключим 2 мотора:

Чаще всего 2 мотора используются для приводной платформы. Напишем программу, по которой платформа 2 секунды едет вперед и разворачивается в течение 1 секунды.

1234567891011121314151617181920212223242526272829 int m11 = 7; // 1 контакт 1 мотораint m12 = 8; // 2 контакт 1 мотораint m21 = 5; // 1 контакт 2 мотораint m22 = 6; // 2 контакт 2 мотораvoid setup() {  // обозначаем порты как выходы  pinMode (m11, OUTPUT);  pinMode (m12, OUTPUT);  pinMode (m21, OUTPUT);  pinMode (m22, OUTPUT);}void loop() {  // запускаем тележку вперед на 2 секунды  digitalWrite(m11, HIGH);  digitalWrite(m12, LOW);  digitalWrite(m21, HIGH);  digitalWrite(m22, LOW);  delay(2000);  // разворачиваем тележку 1 секунду  digitalWrite(m11, LOW);  digitalWrite(m12, HIGH);  digitalWrite(m21, HIGH);  digitalWrite(m22, LOW);  delay(1000);}

Если у вас тележка едет не вперед, а например, назад, или разворачивается, то вы можете исправить это одним из следующих способов:

  • Изменить порты в программе.
  • Поменять местами порты на Arduino.

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

Источник: http://studrobots.ru/dc-motors-arduino/

Как подключить джойстик к Arduino

  • Arduino (или совместимая плата);
  • двухосевой джойстик (вот такой);
  • 3 резистора номиналом 220 Ом;
  • 1 RGB (например, таких) или 3 обычных светодиода (вот таких); можно воспользоваться готовым модулем, который содержит необходимые резисторы и удобные выводы для подключения к Arduino.

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

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

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

Принципиальная схема аналогового джойстика

Здесь outX, outY – выходы для снятия показаний по осям X и Y; outSw – вывод тактовой кнопки. Vcc и GND – питание и земля, соответственно.

2Схема подключения аналогового джойстика к Arduino

Подключим джойстик по приведённой схеме. Аналоговые выходы X и Y джойстика подключим к аналоговым входам A1 и A2 Arduino, выход кнопки SW – к цифровому входу 8. Питание джойстика осуществляется напряжением +5 В.

Схема подключения аналогового джойстика к Arduino

В результате должно получиться примерно так, как на фотографии.

Аналоговый джойстик, подключённый к Arduino

3Считывание показаний с аналогового джойстика

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

const int switchPin = 8; // кнопка джойстика const int pinX = A1; // Ось X джойстика const int pinY = A2; // Ось Y джойстика const int ledPin = 13; void setup() { pinMode(ledPin, OUTPUT) pinMode(pinX, INPUT); pinMode(pinY, INPUT); pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // включаем встроенный подтягивающий резистор Serial.begin(9600); } void loop() { int ledState = digitalRead(switchPin); // считываем состояние кнопки digitalWrite(ledPin, ledState); // вкл./выкл. светодиод по нажатию кнопки int X = analogRead(pinX); // считываем аналоговое значение оси Х int Y = analogRead(pinY); // считываем аналоговое значение оси Y Serial.print(X); // Выводим значение в Serial Monitor Serial.print(” “); // табуляция Serial.println(Y); } Значения X и Y с аналогового джойстика,выведенные в монитор последовательного порта

Объявим пины, зададим им режимы работы. Обратите внимание, в процедуре setup() мы подали на вход switchPin высокий уровень.

Этим мы включили встроенный подтягивающий резистор на этом порту. Если его не включить, то, когда кнопка джойстика не нажата, 8-ой порт Arduino будет висеть в воздухе и ловить наводки.

Это повлечёт за собой нежелательные хаотичные ложные срабатывания.

В процедуре loop() мы постоянно опрашиваем состояние кнопки и отображаем его с помощью светодиода на выходе 13. Из-за того, что вход switchPin подтянут к питанию, светодиод постоянно горит, а при нажатии кнопки гаснет, а не наоборот.

Далее мы считываем показания двух потенциометров джойстика – выхода осей X и Y. Arduino имеет 10-разрядные АЦП, поэтому значения, снимаемые с джойстика, лежат в диапазоне от 0 до 1023. В среднем положении джойстика, как видно на иллюстрации, снимаются значения в районе 500 – примерно середина диапазона.

Обратите внимание, что показания по осям X и Y в нейтральном положении ручки джойстика могут быть разные, и не равняться ровно 512.

Читайте также:  Будущее человечества или наша жизнь в 2116 году - arduino+

4 Управление яркостью и цветом светодиодас помощью аналогового джойстика и Arduino

Обычно джойстик используют для управления электродвигателями. Но почему бы не использовать его, например, для управления яркостью светодиода? Давайте подключим по приведённой схеме RGB светодиод (или три обычных светодиода) к цифровым портам 9, 10 и 11 Arduino, не забывая, конечно, о резисторах.

Подключение RGB светодиода и джойстика к Arduino

Будем менять яркость соответствующих цветов при изменении положения джойстика по осям, как показано на рисунке.

Из-за того, что джойстик может быть не точно отцентрирован производителем и иметь середину шкалы не на отметке 512, а варьироваться в диапазоне примерно от 490 до 525, то светодиод может слегка светиться даже когда джойстик находится в нейтральном положении. Если вы хотите, чтобы он был полностью выключен, то внесите в программу соответствующие поправки.

Диаграмма распределения яркости красного, синего и зелёного каналов светодиода в зависимости от положения ручки джойстика

Ориентируясь на приведённую диаграмму, напишем скетч управления Arduino яркостью RGB светодиода с помощью джойстика.

const int pinRed = 9; const int pinGreen = 10; const int pinBlue = 11; const int swPin = 8; const int pinX = A1; // X const int pinY = A2; // Y const int ledPin = 13; boolean ledOn = false; // текущее состояние кнопки boolean prevSw = false; // предыдущее состояние кнопки void setup() { pinMode(ledPin, OUTPUT); pinMode(pinRed, OUTPUT); pinMode(pinGreen, OUTPUT); pinMode(pinBlue, OUTPUT); pinMode(pinX, INPUT); pinMode(pinY, INPUT); pinMode(swPin, INPUT); digitalWrite(swPin, HIGH); // включаем встроенный подтягивающий резистор } void loop() { if (isLedOn()) freeMode(); // если нажата кнопка и горит светодиод на пине 13, включаем режим “фонарик” else discoMode(); // иначе включаем “цветомузыку” } boolean isLedOn() { // Определяем нажатие кнопки if (digitalRead(swPin) == HIGH && prevSw == LOW) { ledOn = !ledOn; prevSw = HIGH; } else prevSw = digitalRead(swPin); digitalWrite(ledPin, ledOn); // включаем светодиод на пине 13 return ledOn; } void freeMode() { // Режим “фонарик” int X = analogRead(pinX); // считываем положение джойстика int Y = analogRead(pinY); int RED = map(Y, 512, 1023, 0, 255); // маппинг значений int GREEN = map(X, 512, 1023, 0, 255); int BLUE = map(X, 511, 0, 0, 255); analogWrite(pinRed, RED); // включение каналов R,G,B analogWrite(pinGreen, GREEN); analogWrite(pinBlue, BLUE); } void discoMode() { // Режим “цветомузыка” for (int i=0; i

Сначала объявим соответствие пинов и две переменные – ledOn и prevSw – для работы с кнопкой. В процедуре setup() назначим пинам функции и подключим к пину кнопки подтягивающий резистор командой digitalWrite(swPin, HIGH).

В цикле loop() определяем нажатие кнопки джойстика. При нажатии на кнопку переключаем режимы работы между режимом «фонарика» и режимом «цветомузыки».

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

Функция map() очень полезна и удобна в применении. Она переносит измеренные значения (отНижнего, отВерхнего) по осям джойстика в желаемый диапазон яркости (кНижнему, кВерхнему). Можно то же самое сделать обычными арифметическими действиями, но запись с помощью функции map() существенно короче.

https://www.youtube.com/watch?v=dsrpx1t_a1M

В режиме discoMode() три цвета попеременно набирают яркость и гаснут. Чтобы можно было выйти из цикла при нажатии кнопки, каждую итерацию проверяем, не была ли нажата кнопка.

В результате получился фонарик из трёхцветного RGB светодиода, яркость свечения каждого цвета которого задаётся с помощью джойстика. А при нажатии на кнопку происходит включение режима «цветомузыка». Я сделал специальную печатную плату с Arduino Pro Mini и джойстиком, и у меня он используется в качестве ночника для ребёнка 🙂

Управление яркостью и цветом RGB светодиода с помощью аналогового джойстика, подключённого к Arduino

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

Источник: https://soltau.ru/index.php/arduino/item/384-kak-podklyuchit-dzhojstik-k-arduino

Прерывания на всех пинах Arduino

Автор: Илья Дубков. Категория: Блог.

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

Все знают, что у Arduino на пинах 2 и 3 есть внешние прерывания INT0 и INT1, которые включаются функцией attachInterrupt(interrupt, function, mode). У них можно настраивать режим срабатывания – по логическому уровню, по смене состояния, по нарастающему фронту, по спадающему фронту. Это все очень круто, но пинов с внешним прирыванием только два.

Кроме INT0 и INT1 на каждом (почти) пине Atmega328 есть прерывания, которые называются PCINT (Pin Change Interrupts). Эти прерывания герерируются, когда изменяется состояния пина. Все такие прерывания делятся на три группы, поскольку их много, а регистры для их управления восьмибитные. Прерывание PCI0 генерируется, когда изменяется состояние любого пина из PCINT0…

PCINT7, при условии  что прерывание на этом пине разрешено. Аналогично PCI1 генерируется при смене состояния пинов PCINT8…PCINT14, а прерывание PCINT2 генерируется при смене состояния пинов PCINT16…PCINT23.

Для того, чтобы разрешить прерывание на пине, требуется записать единицу в соответствующий бит регистра PCMSK0, PCMSK1 или PCMSK2, в зависимости от того, к какой группе относится пин. 

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

Пин Arduino Порт ATmega Пин порта Линия PCINT Группа PCINT
PD 16 2
1 PD 1 17 2
2 PD 2 18 2
3 PD 3 19 2
4 PD 4 20 2
5 PD 5 21 2
6 PD 6 22 2
7 PD 7 23 2
8 PB
9 PB 1 1
10 PB 2 2
11 PB 3 3
12 PB 4 4
13 PB 5 5
A0 PC 8 1
A1 PC 1 9 1
A2 PC 2 10 1
A3 PC 3 11 1
A4 PC 4 12 1
A5 PC 5 13 1

Итого можно сделать двадцать входов с прерываниями. Сделаем ULTIMATE версию, в которой все доступные нам пины будут работать источниками прерываний.

Сначала переведем все пины в режим вход с подтяжкой (то, что в Arduino называется INPUT_PULLUP). Для этого в регистрах DDRB, DDRC, DDRD должны быть записаны 0, а в регистрах PORTB, PORTC, PORTD должны быть записаны 1 для всех пинов, которые мы используем.

Поскольку значения по умолчанию в регистрах DDRx и так 0, ничего с ними делать не будем. А вот в регистры PORTx попишем. Смотрим в таблице какие пины в каких портах надо активировать, и для простоты пишем в двоичном виде значения для регистров.

Справа младший бит (нулевой пин порта), слева старший (седьмой пин порта):

PORTB = 0b00111111; PORTC = 0b00111111; PORTD = 0b11111111;

Теперь разрешим прерывание на каждой линии, сделав запись в регистры PCMSK0…PCMSK2:

PCMSK2 = 0b11111111; PCMSK1 = 0b00111111; PCMSK0 = 0b00111111;

Теперь разрешим уже сами прерывания в общем:

Бит 0 в регистре PCICR отвечает за группу 0, бит 1 за группу 1, бит 2 за группу 2. Разрешили все три группы.

Теперь напишем обработчики прерываний. Трерываний у нас три, и их векторы называются PCINT0_vect, PCINT1_vect и PCINT2_vect.

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

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

Для опроса состояния пина нужно прочитать регистр PINx и выделить в нем бит, соответствующий нашему пину.
Например, выражение

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

Для пинов ардуино с 0 по 7 обработчик будет выглядеть вот так:

ISR(PCINT2_vect) {     if (!(PIND & (1 

Источник: http://arduinonsk.ru/blog/87-all-pins-interrupts

Ссылка на основную публикацию
Adblock
detector