Применение цифровых датчиков давления HP03SA, HP03MA производства HopeRF (Hope Microelectronics) Китай. Схема, прошивка, исходный код.
HP03SA, HP03MA - недорогие цифровые датчики атмосферного давления, работающие по двухпроводному интерфейсу I2C.
HP03SA, HP03MA – миниатюрный гибридный модуль, изготавливаемого на основе пьезорезистивного датчика давления и интерфейсной микросхемы аналогово-цифровых преобразователя. Формат цифровых данных читается в виде 16-разрядного слова, соответствующего измеряемому ADC напряжению в зависимости от давления и температуры. Реальное разрешение - 15 разрядов.
HP03SA и HP03MA обладают малым током потребления около 500 микроампер и при этом могут питаться напряжением от 2.2В до 3.6В. В датчиках есть функция автоматического переключения в режим экономии энергии, т.е. спящий режим. Поэтому они идеально подходят для носимых устройств, где энергопотребление играет немаловажную роль.
Для связи с микроконтроллером используется 2-проводная последовательная шина I2C. С помощью дополнительной калибровки датчика производитель добивается более высокой точности измерений. Для этого во внутренней памяти датчиков хранятся 11 уникальных корректирующих коэффициентов. Вычисления температуры и давления выполняются с использованием этих коэффициентов. Поскольку в датчике имеется термодатчик, температура учитывается в вычислениях давления, чем достигается термостабилизация показаний датчика давления.
См. также Датчик малых давлений BMP085 и Atmega
Основные характеристики датчиков:
* встроенный датчик давления * абсолютный диапазон измеряемого давления: 300kPa…1100kPa * 16-разрядный ADC * 11 поправочных коэффициентов во внутренней памяти для программной компенсации * последовательный I2C-интерфейс * один вывод тактирования 32.768kHz * одна аппаратная линия сброса * высокая экономичность * разрешение ADC: 15bit * напряжение питания: 2.2V…3.6V * ток потребления в рабочем режиме: менее 500uA * ток потребления в режиме отключения: менее 1uA * внешние компоненты не требуются * разрешение датчика: 0.1kPa * относительная точность (750kPa…1100kPa): ±1kPa * абсолютная точность (750kPa…1100kPa): ±1.5kPa * максимальная ошибка по температуре (-20°C…+60°C): ±3kPa * долговременная стабильность (12 месяцев): 2kPa * зависимость от напряжения питания (2.4V…3.6V): ±1.5kPa * температурная точность: ±0.8°C
HP03SA имеет текстолитовое основание (9.5x9.0x4.8mm), удобное для ручного монтажа.
HP03MA имеет компактное текстолитовое основание (6.9x6.3x3.1mm) для автоматического монтажа. Также успешно монтируется вручную.
Оба рассчитаны на температурный диапазон: -20°C…+60°C.
HP03SA отличается от HP03MA исполнением корпуса. Все прочие характеристики одинаковы. На практике HP03SA показывали более стабильный результат и меньший разброс параметров в отличии от миниатюрных собратьев HP03MA.
На рисунках Приведены рекомендуемые в документации схемы сопряжения датчиков и микроконтроллеров. А так же схемы их корпусов.
Реальная схема может быть следующая:
Она отличается от предложенной схемы отсутствием подтягивающего резистора 10 КОм. В предложенном примере используется встроенные подтягивающие резисторы микроконтроллера серии ATmega.
Пример программы для Atmega8:
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "i2cmaster.h"
//#define F_CPU 3686400L
// Порт XCLR Датчика
#define XCLR_DDR DDRD
#define XCLR_PORT PORTD
#define XCLR PIND0
// Порт Тактирования АЦП Датчика
#define MCLK_DDR DDRD
#define MCLK_PORT PORTD
#define MCLK PIND1
// Калибровочные коэффициенты
long int c1, c2, c3, c4, c5, c6, c7, a, b, c, d;
// Значение АЦП
long int d1, d2;
// Температура
long int t;
// Давление
long int Pressure;
//#############################################################################
// Возведение двойки в степень
//
long int pow2(uint8_t i)
{
long int uiData;
uiData=2;
i=i-1;
while(i) {
uiData *= 2;
i--;
}
return uiData;
}
#define fospEEPROM_ADR 0xA0 // Адрес EEPROM
#define fospADC_ADR 0xEE // Адрес ADC
#define PRESSURE 0xF0
#define TEMPERATURE 0xE8
#define mm_rt_st 0.7500638 // мм. рт. ст. (@ 0 гр. C)
//#############################################################################
// Инициализация HP03
//
void HP03Init(void)
{
// Сброс HP03
XCLR_PORT &= ~(1<<XCLR);
_delay_ms(200);
XCLR_PORT |= (1<<XCLR);
_delay_ms(200);
XCLR_PORT &= ~(1<<XCLR);
_delay_ms(200);
}
//#############################################################################
// Считывает два байта
//
unsigned int HP03_Get2Bytes()
{
unsigned int HiTemp, LowTemp;
HiTemp=i2c_readAck();
LowTemp=i2c_readAck();
return (((int)HiTemp) << 8) + LowTemp;
}
//#############################################################################
// Чтение калибровочных коэффициентов из EEPROM (HP03)
//
void HP03ReadCoeff(void)
{
unsigned int ret;
ret = i2c_start(fospEEPROM_ADR); // Адрес EEPROM
if(ret)
{
// датчик не обнаружен
i2c_stop();
}
else
{
i2c_write(0x10); // Адрес коэффициентов в EEPROM
i2c_start(0xA1);
c1=HP03_Get2Bytes();
c2=HP03_Get2Bytes();
c3=HP03_Get2Bytes();
c4=HP03_Get2Bytes();
c5=HP03_Get2Bytes();
c6=HP03_Get2Bytes();
c7=HP03_Get2Bytes();
a = i2c_readAck();
b = i2c_readAck();
c = i2c_readAck();
d = i2c_readNak();
i2c_stop();
}
}
//#############################################################################
// Чтение данных АЦП (HP03)
//
unsigned int HP03ReadValue(unsigned char n)
{
unsigned int ret;
unsigned int temp;
temp = 0;
ret=i2c_start(fospADC_ADR); // Адрес ADC
if(ret)
{
// датчик не обнаружен
i2c_stop();
}
else
{
i2c_write(0xff);
i2c_write(n); // Pressure(0xF0), Temperature(0xE8)
i2c_stop();
_delay_ms(50);
i2c_start(fospADC_ADR); // Адрес ADC
i2c_write(0xfd);
i2c_rep_start(0XEF); // Адрес ADC
temp = HP03_Get2Bytes();
i2c_stop();
}
return temp;
}
//#############################################################################
// Вычисление температуры и атмосферного давления
// с учетом калибровочных коэффициентов
//
void PressureTemperatureMeasure(void)
{
long int dUT;
long int off, sens, x;
XCLR_PORT |= (1<<XCLR);
d1 = HP03ReadValue(PRESSURE);
d2 = HP03ReadValue(TEMPERATURE);
XCLR_PORT &= ~(1<<XCLR);
//if(d2 >= c5) { dUT = (d2-c5) - (((d2-c5)/pow2(7))*((d2-c5)/pow2(7))*a)/pow2(c); }
//else { dUT = (d2-c5) - (((d2-c5)/pow2(7))*((d2-c5)/pow2(7))*b)/pow2(c); }
if(d2 >= c5) { t = a; }
else { t = b; }
dUT = (d2-c5) - (((d2-c5)/pow2(7))*((d2-c5)/pow2(7))*t)/pow2(c);
t = (250 + ((dUT*c6)/pow2(16)) - dUT/pow2(d));///10; // Вычисляем температуру в градусах по шкале Цельсия
off = (c2+(c4-1024)*dUT/pow2(14))*4;
sens = c1+(c3*dUT)/pow2(10);
x = (sens*(d1-7168))/pow2(14)-off;
//Pressure = (x*100/pow2(5)+c7*10);
Pressure = ((x*100/pow2(5)+c7*10)/100)*mm_rt_st; // Вычисляем давление в миллиметрах ртутного столба
}
//=============================================================================
//#############################################################################
// Тактирование АЦП Датчика
// Тактовая частота процессора 3.6864 МГц
//
ISR(TIMER0_OVF_vect) {
if ((MCLK_PORT & (1<<MCLK)) == 0) {
MCLK_PORT |= (1<<MCLK);
}
else {
MCLK_PORT &= ~(1<<MCLK);
}
}
//#############################################################################
//#############################################################################
int main(void){
// Настраиваем порт для Сброса и Синхронизации датчика
XCLR_DDR |= (1<<XCLR);
MCLK_DDR |= (1<<MCLK);
// Настраиваем таймер для тактирования АЦП
TCCR0 = (1<<CS00);
// Разрешаем прерывания
TIMSK = (1<<TOIE0);
// Запускаем таймера
TCNT0 = 0;
sei();
i2c_init();
// TWI PULL UP Включаем внутренние подтягивающие резисторы, поэтому наружные резисторы можно не устанавливать.
PORTC |= ((1<<PINC4) | (1<<PINC5));
HP03Init();
HP03ReadCoeff();
while(1) {
PressureTemperatureMeasure();
// Выводим переменные
// t - температура
// Pressure - давление
}
}
P.S. В примере использована частота кварца 3.6864 МГц. Это абсолютно НЕ принципиально. Будет работать и от внутреннего RC-генератора. Хотя в документации указано, что АЦП датчика необходимо тактировать частотой 32768 Гц, это не обязательное условие. На практике АЦП датчика можно тактировать меньшей частотой. Я снижал до 15000 Гц, при этом работоспособность сохранялась.
См. также:
Индусский код в изобилии =)
степень двойки делается так: (1<<x) или макросом _BV(x) - сильно быстрее чем умножать
прерывание таймера (для тактирования датчика) вообще можно записать одной простой строкой:
ISR(TIMER0_OVF_vect){
MCLK_DDR ^= _BV(MCLK);
}
спасибо за примерыСпасибо за конструктивную критику. По первому пункту принимается. Именно двойку в степень проще смещением. Это факт. функция pow2 - раньше возводила в степень (больше 0) любое число. И была усечена именно для этого примера. Это не сложно заметить. Если Вам, как мне, придется, скажем, пересчитывать давление в высоту, понадобиться возводить в степень другие числа. Вернув функции второй параметр (вместо двойки), получим универсальный механизм. Что касается прерывания таймера (для тактирования датчика), то Ваш код, несмотря на то, что визуально выглядит проще, увы, в памяти занимает на 6 байт больше. Ну и по поводу MCLK_DDR тоже возникает вопрос...
Насчет памяти на XOR - не больше - факт, XOR в AVR одна команда eor на AMS оно как-то так (могу ошибаться): LDI r16, 1 IN r17, PORTD EOR r17,r16 OUT PORTD, r17 c if/else точно больше: 2 инструкции LDI, операция сравнения, три логические, и OUT/IN в любом случае больше. Про степень - я так и подумал;)
Ув. автор. Использую датчик HP03SA в своей конструкции. Контроллер PIC18F25K20. Столкнулся с проблемой - не могу вычитать коэффициенты в ЕЕПРОМ - вычитываются все ФФ, за исключением 2-х последних коэффициентов - 6 и 9 соотв. Меняя стартовый адрес ЕЕПРОМ, обчитал всю область вокруг, начиная с 00 - отличны от ФФ только эти 2 байта. Результат АЦП вычитывается вроде нормальный - по крайней мере, он меняется при изм. температуры. Ножка сброса устанавливается корректно - для чтения ЕЕПРОМ низкий, АЦП - высокий. Питание 3.3В, подтяжка шины - 10 кОм. Не сталкивались ли вы с битой ЕПРОМиной? Спасибо.
Была проблема с датчиками HP03MA (тот же датчик, но в другом корпусе). Тоже читались не все данные, но данные с АЦП считывались. Долго разбирался, оказалось, попалась бракованная партия. До сих пор 6 штук валяется. Другой вариант (маловероятный), существуют датчики HP02SA. Внешне один в один HP03SA. У них 5 коэфициентов и нельзя вычислить температуру, только давление. Стоят почти вдвое дешевле. Возможно, продавцы "попутали".
Спасибо за ответ. Вот сейчас для проверки еще раз вычитал область ЕЕПРОМ по адресам 0-64. Везде ФФ, и только в 2-х ячейках "6" и "9". Придется заказывать новый датчик, видимо...
Вопрос решился. Приехал другой датчик - все чудесно читается.
В даташите на этот НР03МА непонятно пронумерованы выводы в таблице, по отношению к схеме включения и размерам. Все наоборот. Где правда?
В документации на изображении http://www.avislab.com/blog/wp-content/uploads/2011/03/HP03M.png слева вид сверху, справа датчик перевернут. Обращайте внимание на метку (в виде точки), обозначающую первый вывод. Из за этого и путаница. P.S. Рекомендую обратить внимание на датчик давления bmp085 http://www.avislab.com/blog/bmp085/. Я в свое время перешел на него и до сих пор безмерно счастлив. Характеристики лучше и стабильнее. Цена меньше.
Tags
bme280 bmp280 gps mpu-6050 options stm32 ssd1331 ssd1306 eb-500 3d-printer soldering tim mpu-9250 dma watchdog piezo exti web raspberry-pi docker ngnix solar bluetooth foc html css brushless flask dc-dc capture gpio avr rs-232 mpx4115a atmega mongodb st-link barometer pwm nvic git java-script programmator dht11 hih-4000 pmsm encoder max1674 smd sensors rtc adc lcd motor timer meteo examples i2c usb flash sms rfid python esp8266 servo books bldc remap eeprom bkp battery ethernet uart usart displays led websocket nodemcu wifi
Архіви




