Arduino:Примеры/BarometricPressureWebServer

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Веб-сервер, публикующий данные от датчика атмосферного давления[1]

Этот пример показывает, как при помощи SPI-соединения считывать данные с датчика атмосферного давления SCP1000, а также то, как потом публиковать эти данные в интернет при помощи тандема Arduino и Ethernet Shield, работающих в качестве простого веб-сервера. Используя библиотеку Ethernet, ваш девайс будет отвечать на HTTP-запросы посредством передачи браузеру HTML-кода для отображения данных о температуре и атмосферном давлении, считанных с датчика.

Настроив цепь и загрузив скетч (см. ниже), просто введите в браузере IP-адрес Ethernet Shield, и на экране появятся данные от датчика.

Более подробно о том, как работает датчика атмосферного давления, можно узнать из примера «Использование SPI для считывания данных с датчика атмосферного давления».

Необходимое оборудование

  • Плата с датчиком атмосферного давления SCP1000;
  • Сетевой модуль Arduino Ethernet Shield;

Цепь

Датчик атмосферного давления нужно подсоединить к 6-ому, 7-ому, 11-ому, 12-ому и 13-ому контактам тандема «Arduino и Shield», а также запитать его через выходной 3,3-вольтовый контакт. Контакт DRDY (Data Ready, т.е. «данные готовы для считывания») подключите к 6-ому цифровому контакту, а контакт CSB (Chip Select; т.е. «выбор ведомого устройства») – к 7-ому.

Контакт MOSI (Master Out, Slave In; для передачи данных от ведущего устройства к ведомому) должен быть подключен к 11-ому цифровому контакту, а его «брат-близнец» MISO (Master In, Slave Out; для передачи данных от ведомого устройства к ведущему) – к 12-ому. И, наконец, контакт SCK (Serial Clock; для передачи последовательного тактового сигнала) подключите к 13-ому цифровому контакту, а также убедитесь, что оба устройства подключены к одной и той же «земле».

Закончив с подключением контактов, подсоедините Ethernet Shield к сети при помощи Ethernet-кабеля. Кроме того, вам надо будет поменять сетевые настройки, чтобы они соответствовали вашей сети.

Модуль Ethernet Shield крепится поверх платы Arduino.

Схема

Код

/*
Отображение данных от датчика атмосферного давления SCP1000

Этот скетч служит для вывода данных от датчика атмосферного давления на веб-страницу.
Более подробно об этом датчике можно прочесть тут:
- http://www.sparkfun.com/commerce/product_info.php?products_id=8161
- http://www.vti.fi/en/support/obsolete_products/pressure_sensors

Этот скетч создан на основе примера Нэйтана Зидле (Nathan Seidle) для PIC:
http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip
 
Цепь:
Датчик SCP1000 подключен к 6-ому, 7-ому, 11-ому, 12-ому и 13-ому цифровым контактам.
* DRDY – к 6-ому
* CSB – к 7-ому
* MOSI – к 11-ому
* MISO – к 12-ому
* SCK – к 13-ому

Создан 31 июля 2010 Томом Иго (Tom Igoe)
*/

#include <Ethernet.h>
// Датчик коммуницирует через SPI, поэтому подключаем соответствующую библиотеку:
#include <SPI.h>


// Здесь указываем MAC-адрес для Ethernet-контроллера:
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// Указываем IP-адрес контроллера:
IPAddress ip(192,168,1,20);
IPAddress gateway(192,168,1,1); 
IPAddress subnet(255, 255, 255, 0);


// Инициализируем библиотеку Ethernet Server
// с необходимыми для нас IP-адресом и портом
// (порт 80 используется для HTTP по умолчанию):
EthernetServer server(80);


// Адреса регистров памяти датчика:
const int PRESSURE = 0x1F;      // 3 самых важных бита данных о давлении
const int PRESSURE_LSB = 0x20;  // 16 менее важных битов данных о давлении
const int TEMPERATURE = 0x21;   // 16 битов данных о температуре

// Контакты, которые используются для подключения к датчику 
// (другие необходимые вам контакты управляются библиотекой SPI):
const int dataReadyPin = 6;
const int chipSelectPin = 7;

float temperature = 0.0;
long pressure = 0;
long lastReadingTime = 0;

void setup() {
  // Запускаем библиотеку SPI:
  SPI.begin();

  // Запускаем Ethernet-соединение и работу сервера:
  Ethernet.begin(mac, ip);
  server.begin();

  // Инициализируем контакты Data Ready (DRDY) и Chip Select (CSB):
  pinMode(dataReadyPin, INPUT);
  pinMode(chipSelectPin, OUTPUT);

  Serial.begin(9600);

  // Настраиваем SCP1000, чтобы в данных было меньше шума:
  writeRegister(0x02, 0x2D);
  writeRegister(0x01, 0x03);
  writeRegister(0x03, 0x02);

  // Даем немного времени датчику и Ethernet Shield – чтобы настроиться:
  delay(1000);

  // Выставляем датчик в режим высокого разрешения – чтобы начать считывание:
  writeRegister(0x03, 0x0A);

}

void loop() { 
  // Проверяем данные от датчика не чаще одного раза в секунду:
  if (millis() - lastReadingTime > 1000){
    // Если данные готовы, приступаем к их считыванию.
    // Ничего не делам, пока контакт DRDY не получит значение HIGH:
    if (digitalRead(dataReadyPin) == HIGH) {
      getData();
      // Делаем временную отметку о времени последнего считывания:
      lastReadingTime = millis();
    }
  }

  // Слушаем входящие Ethernet-соединения:
  listenForEthernetClients();
}

void getData() {
  Serial.println("Getting reading");  //  "Начинаем считывание"
  // Считываем данные о температуре:
  int tempData = readRegister(0x21, 2);

  // Конвертируем их в градусы Цельсия и выводим на экран:
  temperature = (float)tempData / 20.0;

  // Считываем 3 самых важных бита в данных о давлении:
  byte  pressureDataHigh = readRegister(0x1F, 1);   
  pressureDataHigh &= 0b00000111; // вам нужны лишь биты со 2-ого по 0-ой

  // Считываем другие 16 битов данных о давлении:
  unsigned int pressureDataLow = readRegister(0x20, 2);    
  // Соединяем обе части в одного 19-битное число:
  pressure = ((pressureDataHigh << 16) | pressureDataLow)/4;

  Serial.print("Temperature: ");  //  "Температура: "
  Serial.print(temperature);
  Serial.println(" degrees C");  //  " градусов Цельсия"
  Serial.print("Pressure: " + String(pressure));  //  "Давление: "
  Serial.println(" Pa"); //  " паскалей"
}
void listenForEthernetClients() {
  // Слушаем подключающихся клиентов:
  EthernetClient client = server.available();
  if (client) {
    Serial.println("Got a client");  //  "Клиент подключен"
    // HTTP-запрос заканчивается пустой линией: 
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // Если вы добрались до конца строки (получили символ новой строки),
        // и эта строка – пустая, это значит, что это конец HTTP-запроса,
        // так что теперь можно слать ответ:
        if (c == '\n' && currentLineIsBlank) {
          // Отправляем стандартный для HTTP-ответа заголовок:
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          // Передаем считанные данные (в HTML-формате):
          client.print("Temperature: ");
          client.print(temperature);
          client.print(" degrees C");
          client.println("<br />");
          client.print("Pressure: " + String(pressure));
          client.print(" Pa");
          client.println("<br />");  
          break;
        }
        if (c == '\n') {
          // Начинаем новую строку:
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // У нас есть символ в текущей строке:
          currentLineIsBlank = false;
        }
      }
    }
    // Даем браузеру немного времени, чтобы получить данные:
    delay(1);
    // Прерываем соединение:
    client.stop();
  }
} 

// Передаем на SCP1000 команду записи:
void writeRegister(byte registerName, byte registerValue) {
  // SCP1000 ожидает, что имя регистра указано в первых («верхних») шести битах байта:
  registerName <<= 2;
  // Сама команда (считывание или запись) располагается в двух последних («нижних») битах:
  registerName |= 0b00000010; // команда записи

  // Даем контакту Chip Select значение LOW, чтобы выбрать девайс:
  digitalWrite(chipSelectPin, LOW); 

  SPI.transfer(registerName); // отсылаем адрес регистра
  SPI.transfer(registerValue); // отсылаем значение, чтобы записать его в регистр 

  // Даем контакту Chip Select значение HIGH, чтобы отменить выбор девайса:
  digitalWrite(chipSelectPin, HIGH); 
}


// Считываем данные из регистра SCP1000:
unsigned int readRegister(byte registerName, int numBytes) {
  byte inByte = 0;           // данные, считанные через SPI 
  unsigned int result = 0;   // результат, который нужно вернуть 

  // SCP1000 ожидает, что название регистра будет в первых («верхних») шести битах байта:
  registerName <<=  2;
  // Команда (считывание или запись) идет в последних («нижних») двух битах:
  registerName &= 0b11111100; // команда считывания

  // Даем контакту Chip Select значение LOW, чтобы выбрать девайс:
  digitalWrite(chipSelectPin, LOW); 
  // Отсылаем девайсу информацию о регистре, данные которого хотим сосчитать:
  int command = SPI.transfer(registerName); 
  // Отсылаем «0», чтобы сосчитать первый возвращенный байт:
  inByte = SPI.transfer(0x00); 
  
  result = inByte;
  // Если было возвращено более одного байта, 
  // перемещаемся от первого байта ко второму:
  if (numBytes > 1){
    result = inByte << 8;
    inByte = SPI.transfer(0x00); 
    result = result |inByte;
}
  // Даем контакту Chip Select значение HIGH, чтобы отменить выбор девайса:
  digitalWrite(chipSelectPin, HIGH); 
  // Возвращаем результат:
  return(result);
}

См.также

  1. Arduino Ethernet Shield
  2. Getting started with the ethernet shield
  3. Ethernet library
  4. ChatServer
  5. ChatClient
  6. WebClient
  7. WebServer
  8. PachubeClient?
  9. PachubeClientString?
  10. BarometricPressureWebServer
  11. UDPSendReceiveString
  12. UdpNtpClient

Внешние ссылки