Pull to refresh

Интерактивная карта из Arduino или по следам «Админского светофора»

Reading time4 min
Views6.7K
Для системного администратора, работающего у интернет провайдера, очень часто возникает задача мониторинга большого числа активного оборудования. Конечно для этих целей можно использовать nagios, cacti, zabbix и подобные им средства мониторинга. Но у всех у них есть один существенный недостаток — необходимо использовать браузер как средство отображения состояния контролируемых узлов сети.
Ознакомивших с «админским светофором» возникла идея создания интерактивной карты города, с расположенными на ней светодиодами: красный — узел недоступен, зеленый — доступен. Но если использовать описанный метод зажигания светодиодов, то понадобится 2 x n, где n — количество контролируемых узлов. Таким образом для контролирования 10 узлов понадобится 20 выводов. Понятно что указанный способ для решения задачи, в случае контролирования более чем 5 узлов, не подходит.

Итак, каким же способом можно уменьшить количество используемых выходов? С ходу в голову приходит использование дешифратора. Способ хороший, но необходимо придумать свой шифр, в котором необходимо учесть все возможные комбинации работы контролируемых узлов. Способ хороший, но не очень хорошо поддающейся масштабированию.
Более удачным видится способ преобразования последовательного сигнала в параллельный. То есть от платы с arduino уходит последовательный сигнал, а в дополнительной схеме уже реализуется управление светодиодами. По этому пути и пойдем.
И так нам понадобится:
  • разработать схему преобразования последовательного сигнала в параллельный;
  • создать выходной каскад со светодиодами для отображения состояния;
  • разработать алгоритм записи нужной информации в схему;
  • реализовать алгоритм опроса узлов сети.


Разработка схемы

Для преобразования последовательного сигнала будем использовать сдвиговый регистр. Под рукой была парочка 74ALS164, вот их и задействуем. Первым делом топаем на сайт производителя и качаем datasheet. У данного регистра имеются:
  • вход сброса CLR;
  • вход тактирования CLK;
  • 2 сигнальных входа A и B;
  • 8 выходов.

По таблице истинности видно что сброс происходит при нулем значении на входе CLR. Запись данных в регистр осуществляется по фронту сигнала CLK. Входной сигнал формируется из сигналов A и B через логическое умножение (И). Таким образом один из сигнальных входов, например B, можно смело подвести к уровню логической 1. Во время работы необходимо присутствие на входе CLR уровня логической единицы. Управляя входом A можно заносить необходимую информацию в регистр. Стробирование на входе CLK позволит добиться однозначности входных и выходных данных.
Но если использовать всего 1 микросхему, то у нас имеется всего 8 выходов. Да не густо. Но тут на помощь приходит каскадирование. То есть если соединить восьмой выход первого регистра с входом A второго, то данные будут заносится во второй регистр с задержкой в 8 тактов.

Выходной каскад

Для управления светодиодами можно использовать 2 вывода на узел, то есть зажигать красный светодиод или зеленый. Но в таком случае произойдет удвоение числа необходимых регистров. Что бы этого избежать будем использовать включение светодиодов по схеме:
image
В этом случае необходимо будет подобрать значения сопротивления резисторов для подходящего свечения светодиодов в случаях горения красного и зеленого светодиодов.
После разводки и пайки получилось следующее:
image
На отладочной плате присутствует 2 сдвиговых регистра и 10 пар светодиодов. К сожалению 4 желтых светодиода в центре платы не горят, очень похоже на битые выводы регистров, но для отладки хватит.

Разработка алгоритма записи

Итак у нас есть схема управления горения светодиодов. Необходимо организовать переключение горения с красного на зеленый и обратно, в любом разряде регистров. Для этого будет использоваться массив битов, каждый бит соответствует одному узлу и двум светодиодам: 1 горит зеленый, 0 – красный. Подавая эту последовательность битов на выход arduino и тактируя каждый разряд выводом CLK мы произведем запись в регистры. Для обеспечения однозначности перед каждой записью новой информации будем производить сброс регистров подавая на вход CLR логический ноль.

Разработка алгоритма опроса узлов

За основу взять код из «админского светофора», но не производится замер времени соединения, а только сам факт его установки или не установки. Используется двумерный массив адресов узлов и массив выходных данных, которые будут заноситься в регистры. Для простоты отладки будем проверять всего 5 узлов.

Код достаточно простой и с комментариями:
//Определим выходные пины
#define SIG 7 // сигнал
#define CLK 6 // тактирование
#define RST 5 // сброс

// подключаем необходимые библиотеки
#include <SPI.h>
#include <Ethernet.h>

//производим инициализацию ethernet shield
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // мак адрес
byte ip[] = {192,168,2,177}; // ip адрес
// массив с контролируемыми узлами
byte pingAddr[][4] = { {172,2,0,5},
                       {172,2,0,6},
                       {172,2,0,7},
                       {172,2,0,8},
                       {172,2,0,9} };
// массив выходных данных
bool out[] = {0,0,0,0,0};
// шлюз и маска
byte gateway[] = {192,168,2,1};
byte subnet[] = {255,255,255,0};

// буфер для отладки
char buffer[256];

// функция проверки доступности хоста
void checkHost(int i)
{
  Client client(pingAddr[i], 80);
  // если соедениться не удается
  if(!client.connect()) {
    // выводим вообщение об этом
    sprintf(buffer, "Connection failed for %d.%d.%d.%d",
    pingAddr[i][0],pingAddr[i][1],pingAddr[i][2],pingAddr[i][3]);
    Serial.println(buffer);
    // и если горит зеленый диод, переключим на на красный
    if(out[i] == 1) {
      out[i] = 0;
      // выведем новые значения в регистры
      setMap();
    }
  // если удалось соединиться
  } else {
    // и горит красный, то включим зеленый
    if(out[i] == 0) {
      out[i] = 1;
      setMap();
    }
  }
  client.stop();
}

// функция вывода массива данных
void setMap()
{
  // сбросим все регистры
  digitalWrite(RST, LOW);
  delay(5);
  digitalWrite(RST, HIGH);
  int i;
  // организуем последовательный вывод
  for(i=0;i<5;i++)
  {
    // если 0 то низкий уровень
    if(out[i]==0)
      digitalWrite(SIG, LOW);
      // если 1 то высокий
    else
      digitalWrite(SIG, HIGH);
    // сделаем паузу во избежание гонок
    delay(1);
    // дадим фронт записи
    digitalWrite(CLK, HIGH);
    delay(1);
    digitalWrite(CLK, LOW);
    // снимаем высокий уровень с сигнальной линии
    digitalWrite(SIG, LOW);
  }
}

void setup()
{
  // инициализируем ethernet shield
  Ethernet.begin(mac, ip, gateway, subnet);
  // последовательный порт
  Serial.begin(9600);
  // настраеваем порты ввода/вывода
  pinMode(SIG, OUTPUT); // signal
  pinMode(CLK, OUTPUT); // CLK
  pinMode(RST, OUTPUT); // reset
  // выставляем начальное состояние
  digitalWrite(CLK, LOW);
  digitalWrite(SIG, LOW);
  digitalWrite(RST, HIGH);
}

// основной цикл
void loop()
{
  int i;
  // для каждого хоста из массива
  for(i=0;i<5;i++){
    // произвести проверку
    checkHost(i);
    delay(1000);
  }
  // отдохнуть 5 секунд, и по новой
  delay(5000);
}


Вот и все.
Теперь осталось найти нужного размера карту города, прикрепить в нужных местах светодиоды и наблюдать за доступностью узлов в реальном времени и не вставая с места.
Tags:
Hubs:
Total votes 26: ↑24 and ↓2+22
Comments30

Articles