Применение цифровых датчиков давления 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/. Я в свое время перешел на него и до сих пор безмерно счастлив. Характеристики лучше и стабильнее. Цена меньше.
Недавні записи
- Text to speech. Українська мова
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
Tags
docker sensors rtc led timer wifi remap sms css websocket mongodb bme280 rfid bluetooth esp8266 nodemcu bkp piezo bmp280 i2c mpu-6050 encoder examples avr brushless ngnix nvic displays bldc java-script pmsm barometer pwm lcd ethernet stm32 raspberry-pi capture usart gpio exti atmega meteo solar smd dma adc eeprom eb-500 flask python ssd1306 uart options flash mpx4115a html gps st-link 3d-printer servo dc-dc foc git books battery hih-4000 watchdog dht11 web tim programmator ssd1331 mpu-9250 usb rs-232 motor max1674 soldering
Архіви