Современные информационные технологии/Компьютерная

advertisement
Современные информационные технологии/Компьютерная инженерия
Мясищев А.А.
Хмельницкий национальный университет, Украина
Web-сервер на ENC28J60 и микроконтроллере AVR
для управления устройствами по TCP/IP сети
Для удаленного управления устройствами, снятия параметров с
датчиков используются микроконтроллеры AVR. Для их подключения к сети
наиболее популярны микросхемы W5100 и ENC28J60. В первой микросхеме
аппаратно реализованы TCP/IP и Ethernet протоколы, а во второй - лишь
Ethernet. Несмотря на это контроллер ENC28J60 в настоящее время является
наиболее популярным. Для него также существует несколько библиотек для
работы в сети с различными сервисами. Здесь предлагается схема
подключения ENC28J60, например к ATmega128L, а также программа,
которая позволит функционировать устройству в режиме простейшего web –
сервера, управляющего 3-мя устройствами и снимающего показания с
датчика
температуры
DS18B20.
Однако
на
сегодняшний
день
целесообразность самостоятельного проектирования схемы под сомнением
благодаря дешевизне готовых модулей, однако, иногда отдельный модуль
неприемлем, а спроектированное устройство может быть дешевле, чем
собранное из модулей. Для подключения к Ethernet по витой паре
рассмотрим, например, разъем HR911105A, который является наиболее
оптимальным вариантом использования совместно с ENC28J60. Он является
дешевым и доставаемым. На его основе представлена схема на рисунке 1. В
качестве контроллера выбрана микросхема ENC28J60 в корпусе DIP28. На
схеме внимание заслуживает резистор R13, например, в описании ENC28J60
он указан как 2kОм. Однако у некоторых ревизий ENC28J60 есть более
оптимальные значения резистора. Так для ревизии 1 и 4 резистор должен
иметь значение 2,7кОм, а для ревизии 5 и 7 - 2,32кОм. Узнать ревизию
можно только путем чтением соответствующего регистра. С этой целью
вначале на монтажной плате устанавливается
ENC28J60, затем читается
ревизия, и только потом устанавливается необходимый по номиналу
резистор. Однако, установка номиналов резистора 2,32кОм или 2кОм,
обеспечивает работоспособность схемы на рис.1, однако может снизиться
дальность работы. Но
для условий офиса, дисплейного класса это
приемлемо.
Рис.1. Схема контроллера ENC28J60 с использованием разъема HR911105A
Досель L1 для работы микросхемы ENC28J60 не нужен, он
используется в качестве
фильтра. Если устройство не содержит
подверженных помехам частей, таких как радио - модули, точные ADC и
тому подобное он может отсутствовать.
В качестве дросселя можно
использовать кольцо из феррита диаметром 5мм с несколькими витками
повода или резистор на 0 Ом.
Полярность включения желтого светодиода (выводы 9 и 10 разъема
HR911105A) определяет режим работы микросхемы ENC28J60 - полу
дуплекс или полный дуплекс. В документации к микросхеме включение
представлено как на рисунке 2.
Рис.2. Полярность включения желтого светодиода
Однако возможна модернизация представленной схемы в целях
упрощения или использования имеющихся в распоряжении деталей. В случае
отсутствия разъема HR911105A можно использовать трансформаторы,
которые устанавливаются на сетевых картах компьютеров. Например, на
рис.3 представлена схема включения фильтра-трансформатора 20F001N
YCL. Обозначения на схеме рисунка 3 точки A B C D соответствуют
обозначениям схемы рисунка 1. К этим точкам выполняется подключение
трансформатора
вместо
разъема
HR911105A.
Светодиоды,
которые
находятся в разъеме HR911105A, при подключении трансформатора
устанавливаются дополнительно.
Рис.3. Подключение трансформатора 20F001N YCL.
В некоторых случаях из-за отсутствия Ethernet - трансформаторов,
разъемов типа HR911105A или построения бюджетного варианта устройства
можно
выполнить
подключение
контроллера
ENC28J60
по
безтрансформаторной схеме при условии, что маршрутизатор находится в
непосредственной близости от созданного устройства. В этом случае схема
подключения представлена на рисунке 4.
Рис.4. Безтрансформаторная схема подключения.
При такой схеме подключения стандарт IEEE 802.3 не выполняется, но
устройство работает.
Теперь рассмотрим аппаратно – программное построение простого
web-сервера для снятия данных с температурного датчика DS18B20 фирмы
DALLAS
и
управления
двумя
исполнительными
устройствами
(светодиодами) по TCP/IP сети с использованием распространенных
микроконтроллеров AVR и контроллера ENC28J60. Предполагается, что наш
сервер подключен к сети Интернет через ADSL маршрутизатор и имеет
локальный ip-адрес. В качестве микроконтроллера выбран ATmega128L,
который имеет достаточную SRAM память для размещения данных,
необходимых
для
функционирования
web-сервера.
На
рисунке
5
представлена схема подключения ATmega128L к температурному датчику,
двум светодиодам и шине SPI, которая используется для работы с сетевым
модулем ENC28J60.
Рис.4. Схема подключения ATmega128L
Несмотря на то, что при последовательном программировании
ATmega128 используется тот же модуль SPI что и при обычной работы
микроконтроллера, имеется одно важное отличие: выводы MOSI/MISO
модуля ввода-вывода SPI, которые совмещены с PB2 и PB3, не используются
при
программировании.
Вместо
них
при
последовательном
программировании используются PE0 и PE1 для ввода и вывода данных.
Поэтому на рис.1 отдельно представлена шина для программирования (Serial
programming). Шина, обозначенная на рис.1 как SPI ENC28J60 подключается
к модулю с чипом ENC28J60, схема которого представлена на рисунке 1.
На рисунке 5 представлена фотография собранного устройства на
монтажной плате. На ней также помечены основные функциональные
элементы.
Программирование
устройства
выполнялось
с
помощью
интегрированной среды разработки Arduino. Достоинство ее в том, что в ней
находится много полезных
библиотек, в частности для работы с шиной
OneWire и чипом ENC28J60.
Рис. 5. Фотография web-сервера на монтажной плате
В программной среде Arduino описаны порты ввода-вывода для
ограниченного числа микроконтроллеров. Поэтому проблема состоит в том,
чтобы описать расположение выводов контроллера
ATmega128 в самой
среде разработки так и в библиотеке для чипа ENC28J60. Для этого
корректируем
файл
1.0.3\hardware\arduino\variants\standard\pins_arduino.h.
Вместо
static const uint8_t SS
= 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK
= 13;
записываем
static const uint8_t SS
= 8;
d:\arduino-
static const uint8_t MOSI = 10;
static const uint8_t MISO = 11;
static const uint8_t SCK
= 9;
В файле d:\arduino-1.0.3\libraries\etherShield\enc28j60.c библиотеки ENC28J60
также выполняем исправления.
Вместо
#define ENC28J60_CONTROL_CS
10
#define SPI_MOSI
11
#define SPI_MISO
12
#define SPI_SCK
13
Записываем
#define ENC28J60_CONTROL_CS
8
#define SPI_MOSI
10
#define SPI_MISO
11
#define SPI_SCK
9
Ниже приведена программа для управления тремя светодиодами
(исполнительными механизмами) и считывания температуры с датчика
DS18B20. Следует обратить внимание, что по сравнению с заданием в начале
странички программа расширена до 3-х светодиодов. Они подключены к
выводам микроконтроллера 28, 30, 32.
#include "etherShield.h"
#include "ETHER_28J60.h"
#include <OneWire.h>
#include <stdio.h>
static uint8_t mac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
static uint8_t ip[4] = {192, 168, 1, 100}; static uint16_t port = 80;
ETHER_28J60 e; OneWire ds(6); char buf[30];
void setup()
{
e.setup(mac, ip, port);
pinMode(3, OUTPUT); pinMode(5, OUTPUT); pinMode(7, OUTPUT); }
int freeRam () { extern int __heap_start, *__brkval; int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
float temp()
{ byte i; byte data[10]; byte addr[8]; float celsius;
ds.search(addr); ds.reset(); ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(800);
ds.reset(); ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();}
int raw = (data[1] << 8) | data[0];
unsigned char t_mask[4] = {0x7, 0x3, 0x1, 0x0};
byte cfg = (data[4] & 0x60) >> 5;
raw &= ~t_mask[cfg];
celsius = (float)raw / 16;
return celsius;}
void loop()
{
char* buffer;
if (buffer = e.serviceRequest())
{
e.print("<FONT size=5 color=green>Web - сервер на базе <font
color=red>ATmega128L</FONT> и контроллера <font color=blue>
ENC28J60</font></FONT><BR>");
e.print("<hr>");
char r=buffer[3]; char g=buffer[7]; char b=buffer[11];
if( r==0x31) digitalWrite(3,HIGH); if( r==0x30) digitalWrite(3,LOW);
if( g==0x31) digitalWrite(5,HIGH); if( g==0x30) digitalWrite(5,LOW);
if( b==0x31) digitalWrite(7,HIGH); if( b==0x30) digitalWrite(7,LOW);
e.print("<FORM action=''>");
e.print("<FONT size=4 color=red>Красный светодиод:</FONT><BR>");
e.print("<INPUT type='radio' name='r' value='1'>ON<br>");
e.print("<INPUT type='radio' name='r' value='0'CHECKED>OFF<br><br>");
e.print("<FONT size=4 color=green>Зеленый светодиод:</FONT><BR>");
e.print("<INPUT type='radio' name='g' value='1'>ON<br>");
e.print("<INPUT type='radio' name='g' value='0'CHECKED>OFF<br><br>");
e.print("<FONT size=4 color=blue>Синий светодиод:</FONT><BR>");
e.print("<INPUT type='radio' name='b' value='1'>ON<br>");
e.print("<INPUT type='radio' name='b' value='0'CHECKED>OFF<br>");
e.print("<INPUT type='submit' value='Ввести'></FORM>");
float aa=temp(); dtostrf(aa,5,2,buf);
e.print("<FONT size=4 color=red>Температура в градусах:</FONT><BR>");
e.print(buf); e.print("<br>");
if (digitalRead(3)){ e.print("<font size=4 color=red>Красный светодиод
ВКЛЮЧЕН</font><br>"); }
else{ e.print("<font size=4 color=red>Красный светодиод
ВЫКЛЮЧЕН</font><br>"); }
if (digitalRead(5)){ e.print("<font size=4 color=green>Зеленый светодиод
ВКЛЮЧЕН</font><br>");}
else{ e.print("<font size=4 color=green>Зеленый светодиод
ВЫКЛЮЧЕН</font><br>"); }
if (digitalRead(7)){e.print("<font size=4 color=blue>Синий светодиод
ВКЛЮЧЕН</font><br>"); }
else{ e.print("<font size=4 color=blue>Синий светодиод
ВЫКЛЮЧЕН</font><br>"); }
e.print("<hr>");
e.print(freeRam());
e.print("Free SRAM:");
e.respond();
}
delay(1);
}
На рисунке 6 показан результат работы программы в web - браузере
Рис.6. Web - интерфейс сервера
Для
снятия
данных
с
температурного
датчика
дополнительно
используется библиотека OneWire. По опыту работы библиотеки etherShield
и ETHER_28J60 позволяют на запрос от клиента отправить только один
пакет. Поэтому создать страничку, размер которой не укладывается в один
пакет Ethernet(примерно 1500 байт) может привести к дополнительным
сложностям в написании программы. Также в памяти микроконтроллера
необходимо резервировать дополнительный буфер объемом 1500 байт. Для
того чтобы заработала программа для управления 3-мя светодиодами в файле
ETHER_28J60.cpp библиотеки ETHER_28J60 внесено следующее изменение:
#define BUFFER_SIZE 1500
В противном случае web - сервер зависал.
Ethernet модуль на базе чипа W5100 и библиотеки Ethernet от Arduino
позволяет обмениваться неограниченным количеством пакетов, поэтому на
его основе возможно создание простого универсального web - сервера.
Download