Arduino:Примеры/BarometricPressureSensor
Содержание | Знакомство с Arduino | Продукты | Основы | Справочник языка Arduino | Примеры | Библиотеки | Хакинг | Изменения | Сравнение языков Arduino и Processing |
Использование 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);
}
См.также
- Arduino SPI LIbrary
- SPIDigitalPot