Мы не выдаем Китай за Италию. Платы от российского производителя по сниженным ценам.

Новинки: Power DC Shield, Светодиодная лента, Freeduino Mini, модули USB Host, Relay.

Web-сервер с модулем E-Shield

Данный пример демонстрирует, как с помощью модуля E-Shield и стандартной библиотеки Ethernet можно реализовать на Freeduino простой Web-сервер. Предполагается версия ПО Arduino не ниже 0.12 – с этой версии в состав входит библиотека Ethernet.

Наш Web-сервер будет очень простым – при получении запроса он будет измерять значения на всех шести аналоговых входах, и выдавать их клиенту. Таким образом, набрав в любом браузере (Firefox/Opera/Internet Explorer) IP адрес устройства мы увидим значения аналоговых входов.

Разберем исходный код:

#include <Ethernet.h>          //Подключаем описание библиотеки ethernet

//Здесь задается MAC адрес и IP адрес устройства.
//В данном примере предполагается, что IP адрес компьютера, с которого
//будем обращаться к устройству будет любым из сети 192.168.1.x,
//и маска 255.255.255.0
//MAC адрес можно задать любой, лишь бы он не пересекался с имеющимися в сети
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };

Server server(80);   //Создаем сервер, слушающий 80й порт (80 – это порт HTTP)

void setup()
{
  Ethernet.begin(mac, ip);   //Инициализируем Ethernet модуль
  server.begin();            //Начинаем ожидать соединений на 80 порту
}

void loop()
{
  //Если кто-то установил соединение с нашим сервером, следующая строчка
  //создаст объект-клиент.
  Client client = server.available();
  if (client) {  //если client не нулевой (т.е. соединение есть)
    //...значит кто-то подключился. Согласно протокола HTTP клиент
    //шлет довольно сложный запрос, но мы не будет его разбирать -
    //нам достаточно дождаться окончания запроса.
    //Запрос заканчивается пустой строкой, поэтому мы просто дождемся
    //получения символа '\n', перед которым тоже были получены '\n' и '\r'.

    //current_line_is_blank - это переменная-флаг. Она равна true, если
    //вновь полученная от клиента строка пустая, т.е. в полученных данных
    //не встретилось символов отличных от '\n' и '\r'.
    //Будем выставлять переменную current_line_is_blank в false при
    //получении любого отличного от '\n' и '\r' символа
    boolean current_line_is_blank = true;
    while (client.connected()) {   //пока клиент подключен
      if (client.available()) {    //если от него пришел символ
        char c = client.read();    //читаем этот символ
        //Если получен перевод строки ('\n') и current_line_is_blank == true,
        //значит мы получили пустую строку, т.е. запрос клиента окончен –
        //можно слать ответ
        if (c == '\n' && current_line_is_blank) {
          //шлем стандартный HTTP заголовок
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();     //он тоже заканчивается пустой строкой!
         
          //выдаем поочередно значения 6 аналоговых входов
          for (int i = 0; i < 6; i++) {
            client.print("analog input ");
            client.print(i);
            client.print(" is ");
            client.print(analogRead(i));
            client.println("<br>");   //HTML тэг <br> - перевод строки
          }
          break;   //работа окончена – можно выходить из цикла while
        }
        if (c == '\n') {  //если получен перевод строки, значит началась новая
          //строка. Выставим флаг current_line_is_blank = true
          current_line_is_blank = true;
        } else if (c != '\r') { //если получен любой другой символ, отличный
          //от возврата каретки ('\r'), значит получаемая строка непустая
          current_line_is_blank = false;
        }
      }
    }
    //небольшая пауза, чтобы данные успели уйти
    delay(1);
    //разрываем соединение с клиентом
    client.stop();
  }
}

Вот как выглядит результат в браузере:

Здесь мы специально запросили у устройства ресурс "abracadabra ", чтобы показать, что содержимое HTTP запроса игнорируется, и всегда генерируется страничка со значениями аналоговых входов.

Web-сервер с модулем WiFly

Компания Roving Networks выпускает ряд модулей для сетей Wi-Fi, управляемых командами по простому последовательному интерфейсу под общим именем WiFly.

Одним из них является модуль RN-171-XV, который может быть легко подключен к Arduino-совместимой плате с помощью XBee Shield.

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

//вспомогательная функция - делает паузу и очищает входной буфер
//в данном простом примере мы не анализируем ответы модуля, а
//просто игнорируем их - это не очень корректно, и не рекомендуется
//в серьезных проектах, но это сильно упрощает понимание протокола
void DelayAndClear()
{
  delay(1000);
  while (Serial.available() > 0) Serial.read();
}

void setup()
{
  delay(2000);
  Serial.begin(9600);
  Serial.print("$$$"); DelayAndClear();                   //командный режим
  Serial.println("set wlan join 0"); DelayAndClear();     //отключаем авто-соединение с сетью
  Serial.println("set ip dhcp 0"); DelayAndClear();       //отключаем DHCP
  //выставляем IP адрес и маску
  Serial.println("set ip address 192.168.1.177"); DelayAndClear();
  Serial.println("set ip mask 255.255.255.0"); DelayAndClear();
  Serial.println("set comm remote 0"); DelayAndClear();   //отключаем стандартный ответ
  Serial.println("set ip localport 80"); DelayAndClear(); //будем слушать 80 порт (HTTP)
  Serial.println("set wlan auth 4"); DelayAndClear();     //выбираем WPA2-аутентификацию
  //выставляем WPA ключ
  Serial.println("set wlan phrase MYPASSWORD"); DelayAndClear();
  delay(1000); DelayAndClear(); //нужна небольшая пауза после установки ключа
  //подключаемся к сети с указанным именем
  Serial.println("join MYNETWORK"); DelayAndClear();
  //организуем паузу - модуль подключается к сети не мгновенно
  //более правильным было бы выполнять анализ ответа модуля
  delay(1000); DelayAndClear();
  delay(1000); DelayAndClear();
  delay(1000); DelayAndClear();
  delay(1000); DelayAndClear();
  Serial.println("exit"); DelayAndClear();                //выходим из командного режима
}

void loop()
{
  //Согласно протокола HTTP клиент
  //шлет довольно сложный запрос, но мы не будет его разбирать -
  //нам достаточно дождаться окончания запроса.
  //Запрос заканчивается пустой строкой, поэтому мы просто дождемся
  //получения символа '\n', перед которым тоже были получены '\n' и '\r'.
  //current_line_is_blank - это переменная-флаг. Она равна true, если
  //вновь полученная от клиента строка пустая, т.е. в полученных данных
  //не встретилось символов отличных от '\n' и '\r'.
  //Будем выставлять переменную current_line_is_blank в false при
  //получении любого отличного от '\n' и '\r' символа
  boolean current_line_is_blank = true;

  while (Serial.available()==0); //ожидаем появления принятого символа

  //устанавливаем время таймаута, чтобы разорвать соединение, если
  //от клиента не получен нормальный запрос
  unsigned long timeout = millis() + 5000;  
  while (millis() < timeout)
  {
    while (Serial.available()==0); //ожидаем появления принятого символа
    char c = Serial.read();        //читаем этот символ
    //Если получен перевод строки ('\n') и current_line_is_blank == true,
    //значит мы получили пустую строку, т.е. запрос клиента окончен –
    //можно слать ответ
    if (c == '\n' && current_line_is_blank) {
      //шлем стандартный HTTP заголовок
      Serial.println("HTTP/1.1 200 OK");
      Serial.println("Content-Type: text/html");
      Serial.println();     //он тоже заканчивается пустой строкой!
      //выдаем поочередно значения 6 аналоговых входов
      for (int i = 0; i < 6; i++) {
        Serial.print("analog input ");
        Serial.print(i);
        Serial.print(" is ");
        Serial.print(analogRead(i));
        Serial.println("<br>");   //HTML тэг <br> - перевод строки
      }
      break;   //работа окончена – можно выходить из цикла while
    }
    if (c == '\n') {  //если получен перевод строки, значит началась новая
      //строка. Выставим флаг current_line_is_blank = true
      current_line_is_blank = true;
    } else if (c != '\r') { //если получен любой другой символ, отличный
      //от возврата каретки ('\r'), значит получаемая строка непустая
      current_line_is_blank = false;
    }
  }
  delay(1000);                              //небольшая пауза, чтобы данные успели уйти
  Serial.print("$$$"); DelayAndClear();     //командный режим
  Serial.println("close"); DelayAndClear(); //закрываем соединение
  Serial.println("exit"); DelayAndClear();  //выходим из командного режима
}

Конечный результат в браузере выглядит идентично: