В первом материале, рассказывающем об обучающем наборе «Цифровая лаборатория» NR05, мы в общих чертах описали принципы построения, состав набора и плату расширения.



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

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

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

Рассмотрим самое простейшее исполнительное устройство – светодиод. В набор входит трехцветный (RGB – Red, Green, Blue) яркий светодиод. Из трех цветов такого светодиода с помощью изменения интенсивности каждого из них, в силу особенностей человеческого глаза можно получить любой цвет. Такой метод получения цвета называется аддитивным смешением цветов и используется, например, в телевизорах и мониторах. Смешав три цвета в равных пропорциях, мы получим белый цвет.



Подключим светодиод к разъему XP15 платы расширения, который дополнительно промаркирован «RGB_LED» с помощью четырех проводов или переходника. Мы применяем светодиод с общим катодом (общим «минусом»), поэтому самый длинный вывод светодиода подсоединяется к контакту GND («Ground»), а остальные выводы светодиода соединяем с контактами RED/D5 (красный), BLUE/D6 (синий), GREEN/D9 (зеленый).



D5, D6 и D9 – это цифровые выводы Ардуино, на которых можно получить широтно-импульсную модуляцию (ШИМ) для управления яркостью светодиода. В обучающем пособии приведен необходимый минимум теории ШИМ и способ реализации этой модуляции в Ардуино.



Приведем код программы (скетча), управляющей яркостью свечения RGB-светодиода:

Спойлер
//  Управляем цветом RGB светодиода
//-----------------------------------------------------------------------
//называем выводы соответственно цвету
int redPin = 5;
int greenPin = 9;
int bluePin = 6;
//-----------------------------------------------------------------------
/* Эта функция будет выполнена 1 раз в момент запуска программы Arduino
в нашем случае она пустая*/
void setup() 
{

}

//-----------------------------------------------------------------------
/* Эта функция будет выполнена после функции setup и будет бесконечное число раз повторятся после своего окончания.*/

void loop() {
   /* Цикл будет повторятся 256 раз. Каждое повторение переменная value будет увеличивать свое значение на 1.*/
   for(int value = 0 ; value <= 255; value ++) { 
    //яркость красного уменьшается от максимума к 0
    analogWrite(redPin, 255-value);
    //яркость зеленого увеличивается
    analogWrite(greenPin, value);
    //синий не горит 
    analogWrite(bluePin, 0);
    // Выдержим паузу в 30 миллисекунд
    delay(30);
  }

  /* Цикл будет повторятся 256 раз. Каждое повторение переменная value будет увеличивать свое значение на 1.*/
  for(int value = 0 ; value <= 255; value ++) { 
    //красный не горит
    analogWrite(redPin, 0);
    //яркость зеленого уменьшается от максимума к 0
    analogWrite(greenPin, 255-value);
    //яркость синего увеличивается
    analogWrite(bluePin, value);
    // Выдержим паузу в 30 миллисекунд
    delay(30);
  }

  /* Цикл будет повторятся 256 раз. Каждое повторение переменная value будет увеличивать свое значение на 1.*/
  for(int value = 0 ; value <= 255; value ++) { 
    //яркость красного увеличивается
    analogWrite(redPin, value);
    //зеленый не горит
    analogWrite(greenPin, 0);
    //яркость синего уменьшается от максимума к 0
    analogWrite(bluePin, 255-value);
    // Выдержим паузу в 30 миллисекунд
    delay(30);
  }

 // Функция loop начнет выполняться сначала 
}



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

Спойлер
//  Управляем цветом RGB светодиода
//-----------------------------------------------------------------------
//называем выводы соответственно цвету
int redPin = 5;
int greenPin = 9;
int bluePin = 6;
//задаем переменные для значений ШИМ
int pwmRed;
int pwmGreen;
int pwmBlue;
//-----------------------------------------------------------------------
// Подключаем библиотеку LiquidCrystalRus
#include <LiquidCrystalRus.h>
// Подключаем библиотеки, которые использует LiquidCrystalRus
#include <LiquidCrystalExt.h>
#include <LineDriver.h>

//-----------------------------------------------------------------------
/* Инициализируем дисплей, объясняя программе куда подключены линии RS,EN,DB4,DB5,DB6,DB7 */
LiquidCrystalRus lcd(A1, A2, A3, 2, 4, 7);

// Эта функция будет выполнена 1 раз в момент запуска программы Arduino
void setup() 
{
  // Инициализируем LCD - 16 символов, 2 строки
  lcd.begin(16, 2);
  // Курсор находится на первой строке (верхней) и первом слева символе  
  lcd.print(" RED GREEN BLUE");
  
}

//-----------------------------------------------------------------------
// Эта функция будет выполнена после функции setup и будет бесконечное число раз повторятся после своего окончания.

void loop() {
   /* Цикл будет повторятся 256 раз. Каждое повторение переменная value будет увеличивать свое значение на 1.*/
   for(int value = 0 ; value <= 255; value ++) { 
    pwmGreen = value;
    pwmRed = 255 - value;
    //яркость красного уменьшается от максимума к 0
    analogWrite(redPin, pwmRed);
    //яркость зеленого увеличивается
    analogWrite(greenPin, pwmGreen);
    //синий не горит 
    analogWrite(bluePin, 0);
    // Выдержим паузу в 30 миллисекунд
    delay(30);
    Display();
  }

  /* Цикл будет повторятся 256 раз. Каждое повторение переменная value будет увеличивать свое значение на 1.*/
  for(int value = 0 ; value <= 255; value ++) { 
    pwmBlue = value;
    pwmGreen = 255 - value;
    //красный не горит
    analogWrite(redPin, 0);
    //яркость зеленого уменьшается от максимума к 0
    analogWrite(greenPin, pwmGreen);
    //яркость синего увеличивается
    analogWrite(bluePin, pwmBlue);
    // Выдержим паузу в 30 миллисекунд
    delay(30);
    Display();
  }

  /* Цикл будет повторятся 256 раз. Каждое повторение переменная value будет увеличивать свое значение на 1.*/
  for(int value = 0 ; value <= 255; value ++) { 
    pwmRed = value;
    pwmBlue = 255 - value;
    //яркость красного увеличивается
    analogWrite(redPin, pwmRed);
    //зеленый не горит
    analogWrite(greenPin, 0);
    //яркость синего уменьшается от максимума к 0
    analogWrite(bluePin, pwmBlue);
    // Выдержим паузу в 30 миллисекунд
    delay(30);
    Display();
  }

 // Функция loop начнет выполняться сначала 
}

// функция выводит на индикатор значения переменных, задающих ШИМ
void Display(){
 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(1,1);
 lcd.print(pwmRed);
 lcd.setCursor(6,1);
 lcd.print(pwmGreen);
 lcd.setCursor(11,1);
 lcd.print(pwmBlue);
}



Теперь рассмотрим пример использования встроенных в плату кнопок.



В общем случае каждая кнопка подключается к отдельному цифровому выводу Ардуино и программа последовательно опрашивает эти выводы для того, чтобы определить, какая кнопка нажата. Для экономии выводов Ардуино, которые необходимо задействовать для определения нажатия кнопки в плате расширения набора «Цифровая лаборатория» используется «аналоговая» клавиатура, подключенная всего к одному аналоговому входу Ардуино. Такой способ часто используются в бытовой технике. Программа измеряет выходное напряжение на выходе делителя напряжения, которое зависит от того, какая кнопка нажата. В обучающем пособии рассмотрена теория такого делителя и способ его применения в клавиатуре. Недостатком такого способа является то, что кнопки можно нажимать только по одной, последовательно.

Загрузим в Ардуино соответствующую программу:

Спойлер
//  Подключаем аналоговую клавиатуру и на дисплее выводи номер нажатой кнопки
//-----------------------------------------------------------------------
// Обязательно подключаем стандартную библиотеку LiquidCrystal
#include <LiquidCrystal.h>

// Определяем сколько кнопок у нас подключено
#define NUM_KEYS 5
// Для каждой кнопки заносим калибровочные значения(выведены экспериментально)
int  adcKeyVal[NUM_KEYS] = {30, 150, 360, 535, 760};
//-----------------------------------------------------------------------
// Инициализируем дисплей, объясняя программе куда подключены линии RS,EN,DB4,DB5,DB6,DB7
LiquidCrystal lcd(A1, A2, A3, 2, 4, 7);

//-----------------------------------------------------------------------
// Эта функция будет выполнена 1 раз в момент запуска программы Arduino
void setup() 
{
  // Инициализируем LCD как обычно -16 символов и 2 строки
  lcd.begin(16, 2);
  // Курсор находится на первой строке (верхней) и первом слева символе  

  // И напишем на дисплее Keyboard
  lcd.print("Keyboard");  
 
  // Выдержим паузу в 2000 миллисекунд= 2 секунды
  delay(2000); 
}

//-----------------------------------------------------------------------
// Эта функция будет выполнена после функции setup и будет бесконечное число раз повторятся после своего окончания.

void loop() {
  // Заводим переменную с именем key
  int key;
  
  // Записываем в эту переменную номер нажатой кнопки, вызывая на исполнение нижеописанную функцию get_key
  key = get_key();
 
  // Очищаем дисплей от всех надписей 
  lcd.clear();
  // Курсор находится на первой строке (верхней) и первом слева символе 
 
  // И напишем какую кнопку нажали. О- ни одна кнопка не нажата 
  lcd.print(key); 
  
  // Выдержим паузу в 100 миллисекунд= 0,1 секунду
  delay(100);
 // Функция loop начнет выполняться сначала 
}

//-----------------------------------------------------------------------
// Эта функция будет выполнена только когда ее вызвали из программы
// Функция читает значение с АЦП, куда подключена аналоговая клавиатура
// и сравнивает с калибровочными значениями, определяя номер нажатой кнопки
int get_key()
	{
	  int input = analogRead(A6);
	  int k;
	  for(k = 0; k < NUM_KEYS; k++) 
	    if(input < adcKeyVal[k]) 
	      return k + 1;     
	  return 0;
	}



Для отображения информации о том, какая кнопка нажата, используется LCD-индикатор. Если нажимать кнопки, то на индикаторе будет отображаться номер нажатой кнопки.

Функция get_key возвращает целое число, соответствующее номеру нажатой кнопки, которое может быть использовано в основной программе. Калибровочные значения, с которыми сравнивается напряжение с выхода делителя, определены экспериментальным путем с помощью вот такой программки:

#include <LiquidCrystal.h>
LiquidCrystal lcd(A1, A2, A3, 2, 4, 7);
void setup() 
{
  lcd.begin(16, 2);
  lcd.print("Press keys");  
  delay(2000); 
}
void loop() {
  
  int input = analogRead(A6);
  lcd.clear();
  lcd.print(input); 
  delay(100);
}


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

• при нажатии на кнопку 1 (крайнюю слева) загорается красный свет, на кнопку 2– зеленый, 3 – синий. При повторном нажатии на кнопку соответствующий свет гаснет. На индикаторе отображается, какие цвета включены.
• при нажатии на кнопку 4 включенные и выключенные цвета меняются местами
• при нажатии на кнопку 5 все цвета гаснут.

Вот один из возможных вариантов такого скетча:

Спойлер
//  Используем аналоговую клавиатуру вместе с RGB-светодиодом
//-----------------------------------------------------------------------
// Обязательно подключаем стандартную библиотеку LiquidCrystal
#include <LiquidCrystal.h>

// Определяем сколько кнопок у нас подключено
#define NUM_KEYS 5
// Для каждой кнопки заносим калибровочные значения(выведены экспериментально)
int  adcKeyVal[NUM_KEYS] = {30, 150, 360, 535, 760};
#define redLED 5
#define greenLED 9
#define blueLED 6
//-----------------------------------------------------------------------
// Инициализируем дисплей, объясняя программе куда подключены линии RS,EN,DB4,DB5,DB6,DB7
LiquidCrystal lcd(A1, A2, A3, 2, 4, 7);
int redLEDstate = 0;
int greenLEDstate = 0;
int blueLEDstate = 0;
int flag = 0;

//-----------------------------------------------------------------------
// Эта функция будет выполнена 1 раз в момент запуска программы Arduino
void setup() 
{
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);
  // Инициализируем LCD как обычно -16 символов и 2 строки
  lcd.begin(16, 2);
  // Курсор находится на первой строке (верхней) и первом слева символе  

  // И напишем на дисплее текст
  lcd.print("Try Keys + LEDs");  
 
  // Выдержим паузу в 1000 миллисекунд= 1 секунда
  delay(1000); 
  // и очистим экран индикатора
  lcd.clear();
}

//-----------------------------------------------------------------------
// Эта функция будет выполнена после функции setup и будет бесконечное число раз повторятся после своего окончания.

void loop() {
  // Заводим переменную с именем key
  int key;
  // Записываем в эту переменную номер нажатой кнопки, вызывая на исполнение нижеописанную функцию get_key
  key = get_key();
  // Если нажата кнопка, меняем состояние соответствующего цвета на противоположное
  // C помощью переменной flag не допускаем изменения состояния цвета, если кнопка нажата и не отпущена
     if(key == 1 && flag == 0) {                                              
        digitalWrite(redLED, !digitalRead(redLED));
        flag = 1;
      }
     if(key == 2 && flag == 0) {  // можно написать короче: if(key == 2 && !flag)                                            
        digitalWrite(greenLED, !digitalRead(greenLED));
        flag = 1;
      }
    if(key == 3 && !flag)  {                                              
        digitalWrite(blueLED, !digitalRead(blueLED));
        flag = 1;
      }
    if(key == 4 && !flag)  {                                              
        digitalWrite(redLED, !digitalRead(redLED));
        digitalWrite(greenLED, !digitalRead(greenLED));
        digitalWrite(blueLED, !digitalRead(blueLED));
        flag = 1;
      }
    if(key == 5 && !flag){                                              
        digitalWrite(redLED, LOW);
        digitalWrite(greenLED, LOW);
        digitalWrite(blueLED, LOW);
        flag = 1;
      }
    // если кнопка была нажата и отпущена, разрешаем изменение состояния цвета
    if(!key && flag) // соответствует if(key == 0 && flag == 1)
      {
        flag = 0;
      }        
   // проверяем состояние каналов светодиода и выводим на индикатор, какой цвет включен
   if (digitalRead(redLED)) { // соответсвует if (digitalRead(redLED) == 1)
         lcd.setCursor(0,0);
         lcd.print("Red");
        }
        else {
         lcd.setCursor(0,0);
         lcd.print("   ");
        }
   if (digitalRead(greenLED)) {
         lcd.setCursor(5,0);
         lcd.print("Green");
        }
        else {
         lcd.setCursor(5,0);
         lcd.print("     ");
        }
    if (digitalRead(blueLED)) { 
         lcd.setCursor(11,0);
         lcd.print("Blue");
        }
        else {
         lcd.setCursor(11,0);
         lcd.print("    ");
        }

 // Функция loop начнет выполняться сначала 
}

//-----------------------------------------------------------------------
// Эта функция будет выполнена только когда ее вызвали из программы
// Функция читает значение с АЦП, куда подключена аналоговая клавиатура
// и сравнивает с калибровочными значениями, определяя номер нажатой кнопки
int get_key()
	{
	  int input = analogRead(A6);
	  int k;
	  for(k = 0; k < NUM_KEYS; k++) 
	    if(input < adcKeyVal[k]) 
	      return k + 1;     
	  return 0;
	}



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



Как видим, возможности платы расширения набора «Цифровая лаборатория» позволяют удобно, наглядно и быстро осваивать практику работы с Ардуино и подсоединяемыми дополнительными модулями.

В следующей статье мы рассмотрим взаимодействие Ардуино с Андроид-смартфоном по технологии Bluetooth с использованием платы расширения. Программировать смартфон будем с помощью проекта MIT App Inventor, который разработан и поддерживается Массачусетским Технологическим Интститутом.

Комментарии (5)


  1. bazis13
    03.03.2016 18:26
    +1

    Для тех, кому понравился набор, похожий собирается из
    arduino uno — $3
    sensor shied — $2
    lcd 1602 keypad — $3
    Датчики — $2-5


  1. r00tGER
    04.03.2016 09:10
    +1

    Видел такие наборы в «Чип и Дип» (да, да, эти ребята тоже знают толк в ценах).
    И, что хочу сказать — новичку лучше начинать с развития навыка заказа комплектующих из Китая.


  1. jehy
    04.03.2016 11:37
    +1

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


  1. Arezus
    04.03.2016 16:32

    А ничего, что у вас на все три анода идет одинаковый резистор в 270 Ом, хотя падение напряжения на каждом переходе разное?


    1. AlNinyo
      11.03.2016 00:22

      Ничего :) Я в своих проектах ВСЕ светодиоды (5 мм) спокойно подключаю через 100-240 Ом и ни разу проблем не было. Всё работает как надо, даже светодиодные кубики.