Использование Arduino для считывания датчика барометрического давления через SPI
В данном примере показано, как использовать библиотеку связи SPI (Serial Peripheral Interface, последовательный периферийный интерфейс) для чтения данных от датчика барометрического (атмосферного) давления SCP1000. Для более подробной информации об этой библиотеке смотрите статью «Библиотека SPI для Arduino»
Необходимые комплектующие
- плата Arduino или Genuino;
- плата с датчиком давления SCP1000;
- перемычки.
Схема
Барометрический датчик давления SCP1000 может считывать и давления воздуха, и температуру и сообщать о них через соединение SPI. Подробнее о регистрах управления SCP1000 смотрите в техническом описании.
Код программы
Код ниже начинается с установки регистров конфигурации SCP1000 в функции setup()
. В основном цикле он устанавливает датчик в режим считывания в высоком разрешении, что означает, что датчик вернет 19-битное значение для показаний давления и 16 бит для температуры. Реальные показания в градусах Цельсия – это 16-разрядный результат, деленный на 20.
Затем программа считывает два байта температуры. Как только она получит температуру, то сразу считывает давление в двух частях. Сначала Arduino считывает самые старшие 3 бита, а затем младшие 16 бит. Затем программа объединяет эти два значения в одно длинное целое с помощью побитового сдвига старших битов, а затем используем побитовое ИЛИ, чтобы объединить их с младшими 16-тью битами. Реальное давление в паскалях – это 19-разрядный результат, деленный на 4.
/*
Схема:
Датчик SCP1000 подключен к выводам 6, 7, 10 - 13:
DRDY: вывод 6
CSB: вывод 7
MOSI: вывод 11
MISO: вывод 12
SCK: вывод 13
*/
// датчик взаимодействует через шину SPI, поэтому подключаем библиотеку:
#include <SPI.h>
// Адреса регистров памяти датчика
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();
// настроить выводы готовности данных и выбора чипа:
pinMode(dataReadyPin, INPUT);
pinMode(chipSelectPin, OUTPUT);
// настроить SCP1000 на малошумящую конфигурацию:
writeRegister(0x02, 0x2D);
writeRegister(0x01, 0x03);
writeRegister(0x03, 0x02);
// дать датчику время для настройки:
delay(100);
}
void loop() {
// выбрать режим высокого разрешения
writeRegister(0x03, 0x0A);
// ничего не делать, пока на выводе готовности данных не появится лог.1:
if (digitalRead(dataReadyPin) == HIGH) {
// прочитать данные температуры
int tempData = readRegister(0x21, 2);
// преобразовать температуру в градусы Цельсия и отобразить ее:
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; // нам необходимы биты только с 2 по 0
// прочитать 16 младших битов данных давления:
unsigned int pressure_data_low = readRegister(0x20, 2);
// объединить две части в одно 19-разрядное число:
long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4;
// display the temperature:
Serial.println("\tPressure [Pa]=" + String(pressure));
}
}
// прочитать или записать регистр 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);
// установить на выводе выбора чипа лог. 0, чтобы выбрать датчик:
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--;
}
// установить на выводе выбора чипа лог. 1, чтобы отменить выбор датчика:
digitalWrite(chipSelectPin, HIGH);
// вернуть результат:
return (result);
}
// Отправить команду записи на SCP1000
void writeRegister(byte thisRegister, byte thisValue) {
// SCP1000 ждет имя регистра в старших 6 битах байта.
// Поэтому сдвигаем биты влево на два разряда:
thisRegister = thisRegister << 2;
// теперь объединяем адрес регистра с командой в один байт:
byte dataToSend = thisRegister | WRITE;
// установить на выводе выбора чипа лог. 0, чтобы выбрать датчик:
digitalWrite(chipSelectPin, LOW);
SPI.transfer(dataToSend); // отправить расположение регистра
SPI.transfer(thisValue); // отправить значение для записи в регистр
// установить на выводе выбора чипа лог. 1, чтобы отменить выбор датчика:
digitalWrite(chipSelectPin, HIGH);
}