Arduino:Примеры/BarometricPressureSensor

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

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


Использование SPI в считывании данных от датчика атмосферного давления[1]

Этот пример показывает, как использовать библиотеку SPI (Serial Peripheral Interface, т.е. «последовательный периферийный интерфейс») для считывания данных с датчика атмосферного давления SCP1000. Больше информации о SPI можно прочесть здесь.

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

  • Плата с датчиком атмосферного давления SCP1000;
  • Плата Arduino;
  • Макетная плата Breadboard или плата для прототипирования;

Цепь

Схема

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

В скетче ниже Arduino начинает с настройки регистров конфигурации SCP1000 – это происходит в блоке setup(). Далее в loop() он настраивает датчик таким образом, чтобы тот считывал данные в режиме высокого разрешения. Это значит, что данные об атмосферном давлении будут возвращены в 19-битном значении, а о температуре – в 16-битном. Далее это 16-битное значение будет поделено на 20, чтобы получить температуру в градусах по Цельсию, а затем показано на Serial Monitor.

Разобравшись с температурой, скетч возьмется за данные о давлении. Он будет считывать их в два этапа: сначала «верхние» 3 бита, а затем «нижние» 16. Далее он сольет эти два значения в одну целочисленную переменную – сначала сдвинет первые 3 бита при помощи битового сдвига, а потом соединит их с оставшимися 16 битами при помощи побитового «ИЛИ». Затем это 19-битное значение будет поделено на 4, чтобы получить давление в Паскалях.

/*
Показ данных от датчика атмосферного давления SCP1000
 
Показывает на Serial Monitor данные от датчика атмосферного давления.
Использует библиотеку SPI. Более подробно об SCP1000 читайте тут:
http://www.sparkfun.com/commerce/product_info.php?products_id=8161
http://www.vti.fi/en/support/obsolete_products/pressure_sensors

Скетч адаптирован к SCP1000-примеру Нейтана Зидле (Nathan Seidle) для PIC:
http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip

Цепь:
* Датчик SCP1000 подсоединен к 6-ому, 7-ому, 10-ому, 11-ому, 12-ому и 13-ому контактам Arduino
* DRDY – 6-ой контакт
* CSB – 7-ой контакт
* MOSI – 11-ый контакт
* MISO – 12-ый контакт
* SCK – 13-ый контакт
 
Создан 31 июля 2010,
модифицирован 14 августа 2010 Томом Иго (Tom Igoe).
*/

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

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

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

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

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

  // Конфигурируем SCP1000 таким образом, чтобы итоговые данные были менее «шумными»:
  writeRegister(0x02, 0x2D);
  writeRegister(0x01, 0x03);
  writeRegister(0x03, 0x02);
  // Даем датчику время настроиться:
  delay(100);
}

void loop() {
  // Выбираем режим высокого разрешения:
  writeRegister(0x03, 0x0A);

  // Ничего не делаем до тех пор, пока контакт Data Ready не получит значение HIGH:
  if (digitalRead(dataReadyPin) == HIGH) {
    // Считываем данные о температуре:
    int tempData = readRegister(0x21, 2);

    // Конвертируем их в градусы Цельсия и отображаем на Serial Monitor:
    float realTemp = (float)tempData / 20.0;
    Serial.print("Temp[C]=");  //  "Температура[Цельсии]="
    Serial.print(realTemp);


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

    // Считываем «нижние» 16 битов в данных о давлении:
    unsigned int pressure_data_low = readRegister(0x20, 2);
    // Соединяем обе части в 19-битное число:
    long pressure = ((pressure_data_high << 16) | pressure_data_low)/4;

    // Показываем давление:
    Serial.println("\tPressure [Pa]=" + String(pressure));  // "\tДавление[Паскали]="
  }
}

// считываем или записываем данные в регистр SCP1000:
unsigned int readRegister(byte thisRegister, int bytesToRead ) {
  byte inByte = 0;           // входящий байт от SPI
  unsigned int result = 0;   // возвращенный результат
  Serial.print(thisRegister, BIN);
  Serial.print("\t");
  // SCP1000 ждет, что имя регистра будет в «верхних» 6 битах байта,
  // поэтому смещаем биты влево на два бита:
  thisRegister = thisRegister << 2;
  // Теперь соединяем адрес и команду в один байт:
  byte dataToSend = thisRegister & READ;
  Serial.println(thisRegister, BIN);
  // Даем контакту Chip Select значение LOW, чтобы выбрать девайс:
  digitalWrite(chipSelectPin, LOW);
  // Отсылаем девайсу регистр, который вы хотите сосчитать:
  SPI.transfer(dataToSend);
  // Отсылаем значение «0», чтобы сосчитать первый возвращенный байт:
  result = SPI.transfer(0x00);
  // Уменьшаем количество байтов, которые осталось прочитать:
  bytesToRead--;
  // Если еще остались байты, которые можно прочесть... :
  if (bytesToRead > 0) {
    // ...сдвигаем первый байт влево и берем второй байт:
    result = result << 8;
    inByte = SPI.transfer(0x00);
    // Соединяем байт, который мы только что взяли, с предыдущим:
    result = result | inByte;
    // Уменьшаем количество байтов, который осталось прочесть:
    bytesToRead--;
  }
  // Даем контакту Chip Select значение LOW, чтобы отменить выбор девайса:
  digitalWrite(chipSelectPin, HIGH);
  // Возвращаем результат:
  return(result);
}


// Эта функция отправляет на SCP1000 команду записи:
void writeRegister(byte thisRegister, byte thisValue) {

  // SCP1000 ждет, что адрес регистра будет в «верхних» 6 битах байта,
  // поэтому сдвигаем биты влево на две позиции:
  thisRegister = thisRegister << 2;
  // Теперь соединяем адрес регистра и команду в одном байте:
  byte dataToSend = thisRegister | WRITE;

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

  SPI.transfer(dataToSend); // отсылаем месторасположение регистра
  SPI.transfer(thisValue);  // отсылаем значение, которое будет записано в регистр

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

См.также

  1. Arduino SPI LIbrary
  2. SPIDigitalPot

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