CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

И один в поле воин...



Маленькие изыскания в вопросе использования одного пина Arduino для индикации. Причем я решил ограничиться вопросом подключения ТОЛЬКО светодиодов. Варианты с 1-wire или RS протоколами, а так же использование пина для ввода данных в данном опусе рассматриваться не будут

Человеческий мозг устроен таким образом, что самые интересные и невероятные решения проблемы рождаются в экстремальных ситуациях. Экстрима нам конечно же не нужно, мы просто смоделируем такую ситуацию. Представьте себе, что при проектировании некого устройства, у вас остался свободным только один пин ардуинки. Как же его по максимуму задействовать?.. Первое, что приходит в голову — подключить светодиод. Не спорю, даже один светодиод весьма много чего может сказать: горит, не горит, определенным образом подает вспышки и т.п. Вот пример. Все это имеет право на жизнь, но два светодиода — все же гораздо нагляднее.
Ага, два светодиода и всего один пин. Ну посмотрим…
Для удобства отладки и тестирования, я на скорую руку набросал отладочный cкетч и собрал простейшую схему на макетке с одной кнопкой. При нажатии на кнопку соответствующий выход меняет свое состояние. (Позже в перечень режимов добавился и Hi-Z). Чтобы понимать «что сейчас»- при режиме Hi-Z дополнительно светится встроенный светодиод на 13 пине.

//**************************************************
// Отладочный скетч опуса "И один в поле воин..."
// для robocraft.ru, кибервесна-2016
// при нажатии кнопки последовательно происходит переключение
// пина между след. состояниями: Hi-Z, HIGH, LOW
//**************************************************
#define ledPin 3
#define BUTTON_PIN 5
void setup() 
{
  pinMode(13, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);      // устанавливаем пин как вход
}

enum mode{p_HIGH, p_LOW, p_HZ, END}; // именнованные режимы
byte currentMode = p_HZ;
//==== Основной цикл ====
void loop() 
{
  
  if (digitalRead(BUTTON_PIN))
  {
    currentMode++;
    if (currentMode == END)
      {
        currentMode =0;
      }
  }
  // end if
  if (currentMode == p_HZ)
    {
      digitalWrite(13, HIGH);
    }
  else
  {
     digitalWrite(13, LOW);    
  }

 switch (currentMode)
 {
   case p_HIGH:
     pin_High();
   break;
   
   case p_LOW:
     pin_Low();
   break;
   
   case p_HZ:
     pin_Hz();
   break;
 }// end switch
 
 delay(200);
  
  
} //end main loop

//===============
void pin_High()
{
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
}
//===============
void pin_Low()
{
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}
//===============
void pin_Hz()
{
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(ledPin, INPUT);
}


Напомню, что пин может находится в состоянии LOW или HIGH. Попросту говоря, если в пин записан «0», то пин Arduino выступает в роли земли, а если «1» — в роли источника питания (правда весьма слабенького, с допустимым током до 40 мА). Записывая в пин то или иное состояние, мы реально сможем включать нужный нам светодиод. А что же со вторым светодиодом? Как его подключить? Первое, что пришло на ум — первый светодиод подключаем непосредственно к пину, а дальше использовать транзистор в качестве инвертора и второй светодиод подключить к инвертированному выходу.

Давайте и попробуем этот вариант.


Как это работает?
Когда в пине выставлен «0» транзистор T1 закрыт и ток течет по цепочке [+Vсс -> R3 -> Led2] и, соответственно, светится только красный светодиод. При записи в пин «1» — загорается зеленый светодиод, открывается транзистор и ток начинает течь по линии [+Vсс -> R3 -> T1(кэ)]. Налицо крупный недостаток такого варианта: при подаче уровня HIGH, кроме горящего нужного нам светодиода, транзистор T1 ТОЖЕ будет находиться в открытом состоянии и через него будет НАПРАСНО течь ток, как через байпас.

Но, несмотря на распространенность n-p-n транзисторов, свет клином на них не сошелся. Может не совсем это верно, но я почему-то запомнил такую фразу:"n-p-n транзистор нужен, чтобы тянуть к земле, а p-n-p — к питанию". Автора этой фразы уже не установить, но я достаточно часто ею пользуюсь. А давайте попробуем вариант с p-n-p транзистором.



Как это работает?
Когда в пине выставлен «0» транзистор открыт и ток течет по цепочке [+Vсс -> Т1(эк) -> R3 -> Led2] и светится только красный светодиод. При записи в пин «1» — ток течет из пина Ардуино через резистор R1 и загорается зеленый светодиод led1, транзистор T1 закрыт. Вот, уже ГОРАЗДО лучше…

Однако, есть более простой вариант: два последовательно включенных светодиода с токоограничивающими резисторами. Кстати, такое решение я впервые увидел в подборке типовых схем подключения — ABC ArduinoBasicConnection



Как это работает?
Тут все просто. При «1» на пине, ток будет течь по цепочке [pin -> led2 -> R2]. В случае «0» на пине — ток пойдет по цепи [+Vcc -> R1 -> led1 -> pin]. Что же, вполне неплохо и работоспособно.

Все вышеперечисленные варианты схем имели один очень важный недостаток. У нас получалось, что либо один светодиод горит, либо другой. Выключить оба светодиода (в описанных выше схемах) не представляется возможным. Или нет? Может как нибудь можно? Да-да-да… напрягаем извилины. Пин может находиться еще и в состоянии Hi-Z pinMode(pin, INPUT). С точки зрения схемотехники я рассматриваю это состояние как будто этой части с Ардуино вообще в схеме и нет. Проверяем на последней схеме. Блин! А при таком состоянии пина (INPUT) у нас оба светодиода тускло подсвечиваются, значит по всей нашей цепочке течет, пусть и незначительный, но ток, достаточный для свечения светодиодов. Не есть хорошо :(
А давайте попробуем немного изменить последнюю схему, добавив парочку диодов. Ну и что мы имеем в таком варианте?



Как это работает?
Чтобы диод начал открываться, необходима разность потенциалов между анодом и катодом порядка 0.5 вольт минимум. Для светодиода эта величина составляет >1.5 вольта (в зависимости от типа и цвета светодиода). При напряжении питания 5 вольт, мы получаем 0.5В х 4+1.5В х 2 = 5 вольт. Следовательно, все диоды находятся в закрытом состоянии. При выставлении на пине «1» ток будет течь по цепи D3 -> D4 -> R2 -> LED2. Круто! Теперь есть возможность включать (правда, по отдельности) каждый светодиод и гасить оба.

А давайте задействуем этот режим по полной. Ведь можно к одному пину подключить 3 светодиода и управлять включением каждого из них. Забегая вперед, скажу, что к сожалению в таком варианте выключить все светодиоды ТЕПЕРЬ ТОЧНО не получится. Думаю, что в ряде случаев, этим недостатком вполне можно пренебречь. По сути, эта схема — это чуть расширенная версия предыдущей. Добавлен узел, который будет активен когда pin Ардуино будет находится в состоянии Hi-Z.



Как это работает?
пин = HIGH. Т1 — закрыт, Т2 — открыт. Ток протекает по цепи [Pin -> D3 -> D4 -> R5 -> Led3]
пин = LOW. Т1 — открыт, Т2 — закрыт. Ток протекает по цепи [+Vcc -> D1 -> D2 -> R4 -> Led2]
пин = INPUT. Диоды D1, D2, D3, D4 — закрыты и незначительный микроток не достаточен для зажигания Led2 и Led3. Т1 и Т2 — открыты. Ток протекает по цепи [+Vcc -> T1(эк) -> R1 -> Led1 -> T2(кэ)]


Кстати, последний вариант подключения 3-х светодиодов мне ОЧЕНЬ понравился и я произвел для него замеры напряжений на разных участках цепи.

Небольшое видео работы такого варианта схемы.


А теперь ВООБЩЕ трэш! А восемь светодиодов можем? Можем, да хоть 16… правда необходимо задействовать микросхему 74HC164 (или несколько, если хотим каскадировать включение). Этот вариант схемы подсмотрен у небезызвестного DiHalt-а. Итак, эта микросхема — ни что иное, как сдвиговый регистр. Но, в отличии от горячо мною любимой микросхемы 74HC595, у 74HC164 нету “защелки”. Т.е. данные СРАЗУ попадают на выходы. Это и хорошо и плохо… Хорошо: не нужен дополнительный сигнал на “защелку”; плохо: все продвижения данных будут видны красивыми “переливами”.


Линию RESET мы использовать не будем, а сразу заблокируем ее подтянув к питанию. Два входа данных (A, B) чаще всего объединяют, и тактовым входом (Clock, он же CLK) обеспечивают продвижение битиков по регистру. Ага, все же нужно два пина как минимум: 1-для выставления данных, 2-для тактирования. И тут на помощь к нам приходит “Интегрирующая RC-цепочка”


Выходным напряжением в интегрирующей цепи является напряжение на конденсаторе. Естественно, если конденсатор разряжен, оно равно нулю. При подаче импульса напряжения на вход цепи, конденсатор начнет накапливать заряд, и накопление будет происходить по экспоненциальному закону, соответственно и напряжение на нем будет нарастать по экспоненте от нуля до своего максимального значения. Более научную версию с формулами можно прочитать тут. Резистор ограничивает ток заряда конденсатора, поэтому чем больше его сопротивление, тем больше время заряда конденсатора. Также и для конденсатора — чем больше емкость, тем большее время он заряжается.

Если мы пустим через такую RC-цепочку длинный импульс, то конденсатор успеет как полностью зарядиться, так и полностью разрядиться. Если подадим короткий импульс, по времени намного меньше чем постоянная времени t, то напряжение на конденсаторе изменится совершенно незначительно. Я бы здесь провел аналогию с автомобилем: если при движении по дороге резко нажать на педаль газа и отпустить, то стрелка тахометра просто “взлетит”, а вот стрелка спидометра лишь немного изменить свое положение.

Как это работает?
Выставляем на пин нужный нам битик и ждем пока значение на выходе RC-цепочки не «устаканится» до нужного значения и делаем весьма короткий тактовый “дрыг”. Выставленный бит попадает на выход регистра. И так 8 раз :) Понятное дело, что тактовый импульс снимается до RC цепи, а данные — после.
Схема такая:

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


К сожалению, у меня не оказалось одинарного 7-ми сегментного индикатора, зато “до фига” сдвоенных. Я оставил место под перемычку, запаяв которую, можно сделать вывод одинаковой информации сразу на две половинки индикатора.

Итого: три провода (питание, земля и управляющий) :) Ниже код, который демонстрирует банальный отсчет от 0 до 9


//задержка нужная для заряда-разряда конденсатора (подобрана экспериментально)
#define led_delay 10
//Пин подключения платы индикации
#define outPin 8
// таблица кодов для индикации 7-сегментника
//                                0   1    2    3    4    5   6    7    8   9 
const byte PROGMEM Encode7seg[]={252,192, 181, 213, 201, 93, 125, 196, 253,221};

void setup() 
{
  pinMode(outPin,OUTPUT);
}


//демонстрашка простого отсчета от 0 до 9
void loop() 
{
  for (byte z=0;z<10;z++)
  {
    byte num_out=pgm_read_byte(&Encode7seg[z]);
  
    out7seg(num_out);
    delay(500);
  }

}// end main loop

//=====================
// void output 7segment
void out7seg(byte out_byte)
{
  for (byte i=0;i<8;i++)
  {
    digitalWrite(outPin,((out_byte>>i) & 0x01)); //выделяем нужный бит и выставляем на линию
    delay(led_delay);//ждем, пока RC цепочка устаканится в нужном значении
    digitalWrite(outPin,LOW);//делаем быстрый синхроимпульс
    digitalWrite(outPin,HIGH);    
  }//end for
}


А ниже можно посмотреть результат работы


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

P.S. Буду очень-очень рад, если кому-то этот материал будет полезен :)

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

RSS свернуть / развернуть

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