7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
1

Работа с датчиком давления BME280. Обсуждение, обмен опытом

23.01.2017, 21:39. Показов 20614. Ответов 13
Метки нет (Все метки)

Доброго времени суток заглянувшему сюда.
Сказать, что датчик "сложный".. Думаю нет. Скорее несколько неординарный, имеющий специфические "заморочки".
И вот в связи с этим начата эта тема. Потому что "одной головы", предполагаю будет маловато
Итак: Имеется платформа на STM32F103C8T6 с выводом данных на LCD 1604. На настоящий момент на ней уже работает двухточечный термометр с датчиками DS1621. Обмен данными между MCU и датчиками - шина I2C. И вот в рамках расширения, так сказать и "углубления" в тему принято решение дополнить сей "сгусток технической мысли" датчиком давления и влажности от Bosch Sensortec BME280. На всякий случай замечу (может и не нужно было, но пусть будет), что проект некоммерческий. Создан "с нуля" 2 месяца назад. "С нуля" в отношении шины I2C и взаимодействия по ней MCU и датчиков. До этого момента, сказать, что я по отношению к DS1621 и I2C был "баран", это значит ничего не сказать.. Такая вот небольшая самокритика. Но "не святые горшки лепят" Код написан (язык С), всё функционирует. Используется программная реализация шины, код программы "регистровый". Мне ИМХО, "библиотечный" стиль как-то "не айс", пока, во всяком случае. Ну да ладно. Суть не в этом. А вот в чём.. Хотелось бы пообщаться с человеком (людьми), который уже имеет опыт и наработки по этому датчику и который может поделиться ими с нуждающимся (мной).
Теперь о том что уже "сделано" по датчику и что нужно.
1. Изучен даташит, ключевая информация переведена на русский язык.
2. Изучены принципы измерения величин RH; P; T, чтения их из датчика и структура их хранения во внутренних регистрах
3. Изучены принципы получения конечных (компенсированных) величин, а также их калибровочные параметры, структура их хранения во внутренних регистрах.
4. Написан код, который компонует из считанных регистров конечные калибровочные параметры (они хранятся внутри датчика "кусками" по 8, а иногда по 4 бита и в некоторых местах так, как будто бы "чёрт иголку в стоге сена искал")
Дальше пришлось сделать вынужденную остановку. Нужно осмыслить, и как следствие воплотить в код, так называемые "компенсационные вычисления". Вот здесь наваливается тяжёлый "тупняк". В даташите приведён готовый код компенсационных формул. Но.. Приношу свои извинения, как я ни "приглядываюсь" к этим формулам, я ни фига не могу понять что из чего вычитается, что на что умножается и делится и в конце концов что и куда в результате этих "безумных" вычислений записывается
Вот, например в даташите DS1621 приведена "человеческая", арифметическая формула вычисления температуры:
TEMPERATURE=TEMP_READ-0.25+(COUNT_PER_C-COUNT_REMAIN)/COUNT_PER_C
Никаких проблем. Написал код этого вычисления на С за минуту и всё работает. А вот в даташите BME280 подобные формулы для влажности, давления и температуры почему-то не приводятся. Злость моя безбрежна. А может тупость...
Вобщем отзовись, знающий человек! Может формулы эти злосчастные есть, а может растолкуешь как разобраться в том безумии, что приведено в даташите
В Bosch Sensortec я написал запрос на предмет получения компенсационных формул в арифметическом виде, но пока оттуда молчок..
Пока в этом не разберусь, толку, естественно никакого..
Надеюсь. Жду.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.01.2017, 21:39
Ответы с готовыми решениями:

BME280 сенсор давления температуры и влажности
Всем привет. Имею такую проблему с BME280 Все делаю по даташит. Температуру измеряет, а давление...

Герметизация корпуса с датчиком давления
Приветствую всех! Вопрос: как изготавливают корпуса по IP65-IP67 с датчиками давления воздуха...

Обмен опытом об iptables
Поделитесь своим опытом создания правил iptables. Например в каком порядке создавать правила и т д

Обмен опытом и сотрудничество
Здравствуйте, программисты, веб-мастера, дизайнеры. Рад буду пообщаться, обменяться опытом, и...

13
152 / 90 / 10
Регистрация: 02.04.2016
Сообщений: 306
25.01.2017, 20:29 2
Имеет смысл просто посмотреть реализацию работы с данным устройством у других и не усложнять себе жизнь. Например, выдрать формулы прямо с кода https://github.com/avislab/sen... /BME280.py
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
25.01.2017, 23:00  [ТС] 3
stend, За ссылку спасибо. Буду смотреть, изучать. Но вот закавыка-то какая. Не настолько я опытен в реверсном инжиниринге в области С Тяжеловато пока понимается чужой код, поэтому помощи и прошу у более опытных людей. Вот взял бы кто да помог "выдрать" эти злосчастные формулы. Была б и мне польза и может кому ещё
А по поводу "посмотреть у других", так инет копан-перекопан, всё что найдено крайне непонятно..
ХеХ..
Сорри за тупость. Стаж в С "с нуля" год с небольшим..

Добавлено через 22 минуты
"Увидел" я в этом коде тот кусок, который отвечает за компенсационные вычисления. Понятнее, чем в даташите, но всё равно пока что крайне тяжковато. Уж очень там все вычисления "заворачиваются" друг за друга. Никто ж комментарии в коде не пишет, к сожалению (понятно что никто никому ничего не должен) Но с комментами было бы намного попроще..
Нужно брать бумагу, карандаш и разбирать "по кирпичикам". Ооох, тяжко мне
Да и Bosch Sensortec чё-то пока молчит как рыба об лёд
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
30.01.2017, 20:48  [ТС] 4
Юххуу!..Пошла "жара".. Считаны калибровочные параметры. Выведены на LCD. Радостно, однако!
Процесс прошёл безо всяких "косяков". "Пилим" дальше!
Достойный "противник"..

Добавлено через 18 часов 0 минут
Может кому-то, кто будет осваивать BME280 пригодится информация для оценки правильности считывания калибровочных параметров:
Кликните здесь для просмотра всего текста
Сначала значения 8-битных, "исходных" калибровочных регистров:
ТЕМПЕРАТУРА.
Адрес Данные
0x88 = 0x81
0x89 = 0x6F
0x8A = 0xAC
0x8B = 0x68
0x8C = 0x32
0x8D = 0x00
***
ДАВЛЕНИЕ.
Адрес Данные
0x8E = 0x28
0x8F = 0x90
0x90 = 0x80
0x91 = 0xD6
0x92 = 0xD0
0x93 = 0x0B
0x94 = 0x3F
0x95 = 0x18
0x96 = 0xFC
0x97 = 0xFF
0x98 = 0xF9
0x99 = 0xFF
0x9A = 0xAC
0x9B = 0x26
0x9C = 0x0A
0x9D = 0xD8
0x9E = 0xBD
0x9F = 0x10
***
ВЛАЖНОСТЬ.
Адрес Данные
0xA1 = 0x4B
0xE1 = 0x71
0xE2 = 0x01
0xE3 = 0x00
0xE4 = 0x12
0xE5 = 0x0F
0xE6 = 0x00
0xE7 = 0x1E
А вот это уже скомпонованные из вышеприведённых, калибровочные константы:
ТЕМПЕРАТУРА.
dig_T1 = 0x6F81
dig_T2 = 0x68AC
dig_T3 = 0x0032
***
ДАВЛЕНИЕ.
dig_P1 = 0x9028
dig_P2 = 0xFFFFD680
dig_P3 = 0x0BD0
dig_P4 = 0x183F
dig_P5 = 0xFFFFFFFC
dig_P6 = 0xFFFFFFF9
dig_P7 = 0x26AC
dig_P8 = 0xFFFFD80A
dig_P9 = 0x10BD
***
ВЛАЖНОСТЬ.
dig_H1 = 0x4B
dig_H2 = 0x0171
dig_H3 = 0x00
dig_H4 = 0x012F
dig_H5 = 0x0000
dig_H6 = 0x1E

Пришлось немного поднапрячь мозжечок и написать процедуру извлечения сих калибровок из BME280. Сложновато всё это как-то организовано... Но судя по сложности, датчик должен быть достойный..
Работа продолжается, как будет что новое, буду писать.
P.S.
До чего ж дошёл прогресс, уму непостижимо. В какого-то "клопа", размером с торец спички, впихнули стоко всякой всячины..

Добавлено через 5 часов 4 минуты
Итак.. Все калибровочные параметры считаны, неоднократно проверены. Всё работает правильно. Все исходные регистры калибровок и результирующие их значения, скомпонованные из исходных регистров отображаются на LCD. Следующим этапом был запуск измерения P; RH; T и считывание его результатов с выводом на LCD. Всё считалось, но результаты измерений получены как значения по сбросу датчика (0x80). После уточнения информации в даташите было выяснено, что измерение P; RH; T выполняется только при включенном оверсэмплинге для каждого параметра. Без включения сей опции величины P; RH; T имеют значения 0x80, т.е. измерение их фактически отключено.
Такая вот информация. Может кому пригодится.
Завтра буду допиливать. Результат будет сообщён.

Добавлено через 23 часа 23 минуты
Считаны и выведены на LCD некомпенсированные "Raw" значения P; RH; T.
ВНИМАНИЕ! Оверсэмплинг влажности нужно конфигурировать ДО записи данных в регистр ctrl_meas, иначе данные оверсэмплинга влажности не будут восприняты датчиком и как следствие некомпенсированное значение влажности будет оставаться 0x80.
Между записью данных в различные регистры конфигурации временные задержки не требуются.
Порядок записи в регистры, при которых датчик гарантированно конфигурируется следующий:
1. Запись в регистр config.
2. Запись в регистр ctrl_hum
3. Запись в регистр ctrl_meas
Ну теперь осталось "пропустить" некомпенсированные "Raw" значения P; RH; T через компенсационные формулы.
Пилим..

Добавлено через 22 часа 51 минуту
stend, Ещё раз благодарю за полезную ссылку там компенсационные формулы приведены в адекватном виде, конечно при более вдумчивом изучении.
Температура уже вычислена и выведена на LCD! Надеюсь, что с давлением и влажностью проблем не возникнет.
Хотелось бы заметить, что принцип "Спасение утопающих-дело рук самих утопающих" самый верный. И ещё очень верны высказывания "Глаза боятся, а руки делают" и "Не святые горшки лепят".. Покумекал башкой немного и вот результат налицо.
Итак можно подвести итог.. BME280 побеждён!
Пилю дальше, "обновки" выложу. Как закончу все параметры, выложу код функции компенсационных вычислений. На пользу народу.
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
31.01.2017, 20:53  [ТС] 5
stend, Расписываюсь в своём собственном тупизме (самокритика). Сорри. Код по указанной ссылке абсолютно аналогичен коду, приведённому в даташите, в Приложении "А". Нужно было просто сесть, успокоиться и не дёргаясь и нервничая проштудировать код. С каждым "проходом" становилось всё понятнее и понятнее. В итоге.. Фууфф!! на дисплей добавилось давление в мм.рт.ст. Вечером допилю влажность и видал я BME280... Ну и хочется заметить, что датчик безумнейший, в смысле быстродействия, точности и чувствительности. Не зря я его выбрал, всё ж интуиция на "железо" в очередной раз не подвела..


Добавлено через 8 часов 36 минут
Вот готовая процедура компенсационных вычислений. Ко всем "даташитным" именам компенсационных параметров добавлен префикс "PS1"-идентификатор датчика 1. Имена входных и выходных параметров описаны в "шапке" процедуры.
Код:
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//****************************<<<--Процедура вычисления компенсированных значений T; P; %RH BME280-->>>*******************************************
// Входные и выходные параметры:                                                                                                                                                                                                                                *                                                                                                                               *
// PS1T_Raw PressureSensor1TemperatureRaw. Некомпенсированное значение измеренной тепературы                                                                                                       *                                                                                                                                                              *
// PS1T_Cmp. PressureSensor1TemperatureCompensated. Вычисленное компенсированное значение измеренной тепературы                                                                   *                                                                           * 
// PS1P_Raw PressureSensor1PressureRaw. Некомпенсированное значение измеренного давления                                                                                                                *
// PS1P_Pa_Cmp PressureSensor1PressurePascalsCompensated. Вычисленное компенсированное значение измеренного давления в Паскалях.                              *
// PS1PmmHg_Cmp PressureSensor1PressureMillimetersHydrargyrum. Значение давления в мм.рт.ст.                                                                                                      *
// PS1H_Raw PressureSensor1HumidityRaw. Некомпенсированное значение измеренной влажности.                                                                                                               *
// PS1H_Cmp PressureSensor1HumidityCompensated. Вычисленное компенсированное значение измеренной влажности.                                                                            *
//************************************************************************************************************************************************
void ClcCmpVals()   // CalculationCompensatedValues Функция вычисления компенсированных значений T; P; %RH
{
int var1;                   // Переменная 1 промежуточных компенсационных вычислений
int var2;                   // Переменная 2 промежуточных компенсационных вычислений
int t_fine;             // Переменная точной температуры компенсационных вычислений
int p;                      // Переменная промежуточных компенсационных вычислений давления
int var_H;              // Переменная промежуточных компенсационных вычислений влажности
//************************************************************************************************************************************************
//--------------------------------------<<<Вычисление компенсированоого значения T-->>>-----------------------------------------------------------
    var1=(PS1T_Raw/16384.0-PS1dig_T1/1024.0)*PS1dig_T2;
    var2=((PS1T_Raw/131072.0-PS1dig_T1/8192.0)*(PS1T_Raw/131072.0-PS1dig_T1/8192.0))*PS1dig_T3;
    t_fine=var1+var2;
    PS1T_Cmp=t_fine/5120.0;
//--------------------------------------<<<Вычисление компенсированоого значения P-->>>-----------------------------------------------------------
    var1=(t_fine/2.0)-64000.0;
    var2=var1*var1*PS1dig_P6/32768.0;
    var2=var2+var1*PS1dig_P5*2.0;
    var2=(var2/4.0)+(PS1dig_P4*65536.0);
    var1=(PS1dig_P3*var1*var1/524288.0+PS1dig_P2*var1)/524288.0;
    var1=(1.0+var1/32768.0)*PS1dig_P1;
    p=1048576.0-PS1P_Raw;
    p=(p-(var2/4096.0))*6250.0/var1;
    var1=PS1dig_P9*p*p/2147483648.0;
    var2=p*PS1dig_P8/32768.0;
    PS1P_Pa_Cmp=p+(var1+var2+PS1dig_P7)/16.0;
    PS1PmmHg_Cmp=PS1P_Pa_Cmp/100*0.750063755419211;
//--------------------------------------<<<Вычисление компенсированоого значения %RH-->>>---------------------------------------------------------
    var_H   =   t_fine - 76800.0;
    var_H   =   (PS1H_Raw   - (PS1dig_H4 * 64.0 + PS1dig_H5 / 16384.0 * var_H))*
    (PS1dig_H2 / 65536.0 * (1.0 + PS1dig_H6 / 67108864.0 * var_H * (1.0 + PS1dig_H3 / 67108864.0 * var_H)));
    PS1H_Cmp = var_H * (1.0 - PS1dig_H1 * var_H / 524288.0);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Единственное сомнение какое-то есть у меня по поводу измеренной влажности. В комнате показывает 16,96%, хотя если пару секунд подышать на датчик, то влажность исправно поднимается аж до 80++% При этом к температуре и давлению абсолютно никаких претензий. Т проверена по термометру на DS1621, P проверена по барометру. И то и другое "тютелька в тютельку"
Но это уже "техника".. Главное, что всё измеряется.

Добавлено через 9 минут
Если к датчику приблизить смоченную ватку, показания поднимаются до 90% с небольшим. Типа похоже что валидно измеряет. Дальше будет видно..
0
0 / 0 / 0
Регистрация: 18.12.2016
Сообщений: 4
31.01.2017, 20:56 6
Спасибо за ответы)
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
01.02.2017, 14:22  [ТС] 7
Рад поделиться

Добавлено через 13 часов 13 минут
Так, коллеги! вношу коррективы в код. СОРРИ!!! Найден небольшой "косяк", который произошёл по причине "горя от ума".
Это касается секции вычисления давления.
Как это было и к чему привело:
Когда я написал секцию вычисления давления и первый раз её запустил, то давление отобразилось в полном соответствии с настоящим, метеорологическим, механическим барометром: 769,7 мм.рт.ст.
Секция писалась в соответствии с документом: https://github.com/avislab/sen... /BME280.py и я как-то интуитивно, что ли, вобщем не знаю как это получилось, но не стал использовать сначала локальную переменную "р", а в конце, как результат вычислений "pressure", а сразу поставил в эту "безумную" формулу уже глобальную переменную PS1P_Cmp, значение которой постепенно изменяясь в результате расчётов и превращается в давление в паскалях. И вот с этим вариантом кода я с первого раза получил идеально измеренное давление.
Потом, когда я стал "подчищать" код, дописывать комменты, вобщем "наводить порядок", то вдруг обратил внимание, что в вычислениях сначала фигурирует "р", а уже в последней формуле результирующее значение присваивается "pressure".
Ну я взял и переписал. Ввёл локальную переменную "р", а результат "погрузил" в глобальную PS1P_Cmp. Скомпилировал и успокоился. Но не придал значения, что показания стали ровно на 10 мм.рт.ст. меньше Видать вечернее пиво и общая перегруженность черепка сыграло роль.. И вот, на следующий день, утром я замечаю, что давление на дисплее 757мм.рт.ст, а механический барометр показывает 767!!! Паника была невероятной. Ведь я точно помню первое значение давления:1026,2 hPa (769,7мм.рт.ст.). Началась возня. Перепроверка того, что переписывалось. И вот открываю я даташит. А там "р" принимает участие в вычислениях с самого начала и она же является результатом вычислений. Подставляю вместо "р" PS1P_Cmp и получаю идеальные показания!!!
Косяк налицо. Подозреваю, что и с влажностью такая же история, но эти "раскопки" будут позже..
Исправленный код:
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void ClcCmpVals()   // CalculationCompensatedValues Функция вычисления компенсированных значений T; P; %RH
{
int var1;                   // Переменная 1 промежуточных компенсационных вычислений
int var2;                   // Переменная 2 промежуточных компенсационных вычислений
int t_fine;             // Переменная точной температуры компенсационных вычислений
int var_H;              // Переменная промежуточных компенсационных вычислений влажности
//************************************************************************************************************************************************
//--------------------------------------<<<Вычисление компенсированоого значения T-->>>-----------------------------------------------------------
    var1=(PS1T_Raw/16384.0-PS1dig_T1/1024.0)*PS1dig_T2;
    var2=((PS1T_Raw/131072.0-PS1dig_T1/8192.0)*(PS1T_Raw/131072.0-PS1dig_T1/8192.0))*PS1dig_T3;
    t_fine=var1+var2;
    PS1T_Cmp=t_fine/5120.0;
//--------------------------------------<<<Вычисление компенсированоого значения P-->>>-----------------------------------------------------------
    var1=(t_fine/2.0)-64000.0;
    var2=var1*var1*PS1dig_P6/32768.0;
    var2=var2+var1*PS1dig_P5*2.0;
    var2=(var2/4.0)+(PS1dig_P4*65536.0);
    var1=(PS1dig_P3*var1*var1/524288.0+PS1dig_P2*var1)/524288.0;
    var1=(1.0+var1/32768.0)*PS1dig_P1;
    PS1P_Cmp=1048576.0-PS1P_Raw;
    PS1P_Cmp=(PS1P_Cmp-(var2/4096.0))*6250.0/var1;
    var1=PS1dig_P9*PS1P_Cmp*PS1P_Cmp/2147483648.0;
    var2=PS1P_Cmp*PS1dig_P8/32768.0;
    PS1P_Cmp=PS1P_Cmp+(var1+var2+PS1dig_P7)/16.0;
    PS1PmmHg_Cmp=PS1P_Cmp/100*0.750063755419211;
//--------------------------------------<<<Вычисление компенсированоого значения %RH-->>>---------------------------------------------------------
    var_H=t_fine-76800.0;
    var_H=(PS1H_Raw-(PS1dig_H4*64.0+PS1dig_H5/16384.0*var_H))*
    (PS1dig_H2/65536.0*(1.0+PS1dig_H6/67108864.0*var_H*(1.0+PS1dig_H3/67108864.0*var_H)));
    PS1H_Cmp=var_H*(1.0-PS1dig_H1*var_H/524288.0);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Добавлено через 2 часа 59 минут
Окончательно проверенный код компенсации. Все параметры вычисляются корректно. Температура проверена другим термометром, давление - механическим метеорологическим барометром. Влажность на улице - через сообщения аэропортовой метеослужбы (t воздуха, точка росы), подстановкой этих величин в спецтаблицу.
Всё сошлось.
Больше ковырять не нужно. Фуффф!!
Код:
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//****************************<<<--Процедура вычисления компенсированных значений T; P; %RH BME280-->>>*******************************************
//  Входные и выходные параметры: (глобальные переменные)                                                                                                                                                                               *                                                                                                                               *
//  PS1T_Raw PressureSensor1TemperatureRaw. Некомпенсированное значение измеренной тепературы                                                                                                      *                                                                                                                                                              *
//  PS1T_Cmp. PressureSensor1TemperatureCompensated. Вычисленное компенсированное значение измеренной тепературы                                                              *                                                                           * 
//  PS1P_Raw PressureSensor1PressureRaw. Некомпенсированное значение измеренного давления                                                                                                               *
//  PS1P_Cmp PressureSensor1PressureCompensated. Вычисленное компенсированное значение измеренного давления в Паскалях.                                                   *
//  PS1PmmHg_Cmp PressureSensor1PressureMillimetersHydrargyrum. Значение давления в мм.рт.ст.                                                                                                         *
//  PS1H_Raw PressureSensor1HumidityRaw. Некомпенсированное значение измеренной влажности.                                                                                                          *
//  PS1H_Cmp PressureSensor1HumidityCompensated. Вычисленное компенсированное значение измеренной влажности.                                                                       *
//************************************************************************************************************************************************
void ClcCmpVals()   // CalculationCompensatedValues Функция вычисления компенсированных значений T; P; %RH
{
int var1;                   // Переменная 1 промежуточных компенсационных вычислений
int var2;                   // Переменная 2 промежуточных компенсационных вычислений
int t_fine;             // Переменная точной температуры компенсационных вычислений
//************************************************************************************************************************************************
//--------------------------------------<<<Вычисление компенсированоого значения T-->>>-----------------------------------------------------------
    var1=(PS1T_Raw/16384.0-PS1dig_T1/1024.0)*PS1dig_T2;
    var2=((PS1T_Raw/131072.0-PS1dig_T1/8192.0)*(PS1T_Raw/131072.0-PS1dig_T1/8192.0))*PS1dig_T3;
    t_fine=var1+var2;
    PS1T_Cmp=t_fine/5120.0;
//--------------------------------------<<<Вычисление компенсированоого значения P-->>>-----------------------------------------------------------
    var1=(t_fine/2.0)-64000.0;
    var2=var1*var1*PS1dig_P6/32768.0;
    var2=var2+var1*PS1dig_P5*2.0;
    var2=(var2/4.0)+(PS1dig_P4*65536.0);
    var1=(PS1dig_P3*var1*var1/524288.0+PS1dig_P2*var1)/524288.0;
    var1=(1.0+var1/32768.0)*PS1dig_P1;
    PS1P_Cmp=1048576.0-PS1P_Raw;
    PS1P_Cmp=(PS1P_Cmp-(var2/4096.0))*6250.0/var1;
    var1=PS1dig_P9*PS1P_Cmp*PS1P_Cmp/2147483648.0;
    var2=PS1P_Cmp*PS1dig_P8/32768.0;
    PS1P_Cmp=PS1P_Cmp+(var1+var2+PS1dig_P7)/16.0;
    PS1PmmHg_Cmp=PS1P_Cmp/100*0.750063755419211;
//--------------------------------------<<<Вычисление компенсированоого значения %RH-->>>---------------------------------------------------------
    PS1H_Cmp=t_fine-76800.0;
    PS1H_Cmp=(PS1H_Raw-(PS1dig_H4*64.0+PS1dig_H5/16384.0*PS1H_Cmp))*
    (PS1dig_H2/65536.0*(1.0+PS1dig_H6/67108864.0*PS1H_Cmp*(1.0+PS1dig_H3/67108864.0*PS1H_Cmp)));
    PS1H_Cmp=PS1H_Cmp*(1.0-PS1dig_H1*PS1H_Cmp/524288.0);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
05.03.2017, 18:00  [ТС] 8
Небольшое дополнение: Всё же я склонился к тому, что вычисление всех трёх величин (а так и указано изначально, в даташите) лучше выполнять по отдельности. Потому, что может возникнуть надобность "отключить" какую-либо величину и вычислять её не будет нужно (вызывать соответствующую процедуру).
В случае независимых процедур вычисления для каждой величины переменная t_fine должна быть объявлена как глобальная, т.к. её значение используется для вычисления давления и влажности.
Вот окончательный "обкатанный" на платформе с двумя датчиками BME280 код вычислений:
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//****************************<<<--Процедура вычисления компенсированного значения T BME280#-->>>*************************************************
//  Аргументы функции и выходные параметры:                                                                                                                                                                                                            *                                                                                                                               *
//  SlvX SlaveX Условный номер целевого BME280#                                                                                                                                                                                                     *
//  S1T_Raw Sensor1TemperatureRaw. Некомпенсированное значение T  BME280 1.(Addr=0x76)                                                                                                 *                                                                                                                                                              *
//  S1T_Cmp Sensor1TemperatureCompensated. Вычисленное компенсированное значение T BME280 1.(Addr=0x76)                                                               *                                                                           * 
//  S2T_Raw Sensor1TemperatureRaw. Некомпенсированное значение T  BME280 2.(Addr=0x77)                                                                                                 *                                                                                                                                                              *
//  S2T_Cmp Sensor1TemperatureCompensated. Вычисленное компенсированное значение T   BME280 2.(Addr=0x77)                                                             *
//************************************************************************************************************************************************
void ClcT(uint8_t SlvX)
{
int var1,var2;  // Переменные промежуточных компенсационных вычислений
    if (SlvX==1)    // Проверка адресации BME280 (1).
{                               // Адресован BME280 (1). Вычисление компенсированного значения T;
    var1=(S1T_Raw/16384.0-S1dig_T1/1024.0)*S1dig_T2;
    var2=((S1T_Raw/131072.0-S1dig_T1/8192.0)*(S1T_Raw/131072.0-S1dig_T1/8192.0))*S1dig_T3;
    Tfine=var1+var2;
    S1T_Cmp=Tfine/5120.0;
}
    if (SlvX==2)    // Проверка адресации BME280 (2).
{                               // Адресован BME280 (2). Вычисление компенсированного значения T;
    var1=(S2T_Raw/16384.0-S2dig_T1/1024.0)*S2dig_T2;
    var2=((S2T_Raw/131072.0-S2dig_T1/8192.0)*(S2T_Raw/131072.0-S2dig_T1/8192.0))*S2dig_T3;
    Tfine=var1+var2;
    S2T_Cmp=Tfine/5120.0;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//****************************<<<--Процедура вычисления компенсированного значения P BME280#-->>>*************************************************
// Аргументы функции и выходные параметры:                                                                                                                                                                                                             *                                                                                                                               *
// SlvX SlaveX Условный номер целевого BME280#                                                                                                                                                                                                  *
// S1P_Raw Sensor1TemperatureRaw. Некомпенсированное значение T   BME280 1.(Addr=0x76)                                                                                                             *                                                                                                                                                              *
// S1P_Cmp Sensor1TemperatureCompensated. Вычисленное компенсированное значение T BME280 1.(Addr=0x76)                                                                          *                                                                             * 
// S2P_Raw Sensor2TemperatureRaw. Некомпенсированное значение P   BME280 2.(Addr=0x77)                                                                                                             *                                                                                                                                                              *
// S2P_Cmp Sensor2TemperatureCompensated. Вычисленное компенсированное значение P(Pa) BME280 2.(Addr=0x77)                                                        *
// S1PmmHg_Cmp Sensor1PressureMillimetersHydrargirym Значение Р(mmHg) BME280 1.(Addr=0x76)                                                                                                    *
// S2PmmHg_Cmp Sensor2PressureMillimetersHydrargirym Значение Р(mmHg) BME280 2.(Addr=0x77)                                                                                                    *
//************************************************************************************************************************************************
void ClcP(uint8_t SlvX)
{
int var1,var2;  // Переменные промежуточных компенсационных вычислений
    if (SlvX==1)    // Проверка адресации BME280 (1).
{                             // Адресован BME280 (1). Вычисление компенсированного значения P;
    var1=(Tfine/2.0)-64000.0;
    var2=var1*var1*S1dig_P6/32768.0;
    var2=var2+var1*S1dig_P5*2.0;
    var2=(var2/4.0)+(S1dig_P4*65536.0);
    var1=(S1dig_P3*var1*var1/524288.0+S1dig_P2*var1)/524288.0;
    var1=(1.0+var1/32768.0)*S1dig_P1;
    S1P_Cmp=1048576.0-S1P_Raw;
    S1P_Cmp=(S1P_Cmp-(var2/4096.0))*6250.0/var1;
    var1=S1dig_P9*S1P_Cmp*S1P_Cmp/2147483648.0;
    var2=S1P_Cmp*S1dig_P8/32768.0;
    S1P_Cmp=S1P_Cmp+(var1+var2+S1dig_P7)/16.0;
    S1PmmHg_Cmp=S1P_Cmp/100*0.750063755419211;
}
    if (SlvX==2)    // Проверка адресации BME280 (2).
{                             // Адресован BME280 (2). Вычисление компенсированного значения P;
    var1=(Tfine/2.0)-64000.0;
    var2=var1*var1*S2dig_P6/32768.0;
    var2=var2+var1*S2dig_P5*2.0;
    var2=(var2/4.0)+(S2dig_P4*65536.0);
    var1=(S2dig_P3*var1*var1/524288.0+S2dig_P2*var1)/524288.0;
    var1=(1.0+var1/32768.0)*S2dig_P1;
    S2P_Cmp=1048576.0-S2P_Raw;
    S2P_Cmp=(S2P_Cmp-(var2/4096.0))*6250.0/var1;
    var1=S2dig_P9*S2P_Cmp*S2P_Cmp/2147483648.0;
    var2=S2P_Cmp*S2dig_P8/32768.0;
    S2P_Cmp=S2P_Cmp+(var1+var2+S2dig_P7)/16.0;
    S2PmmHg_Cmp=S2P_Cmp/100*0.750063755419211;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//****************************<<<--Процедура вычисления компенсированного значения RH BME280#-->>>************************************************
// Аргументы функции и выходные параметры:                                                                                                                                                                                                             *                                                                                                                               *
// SlvX SlaveX Условный номер целевого BME280#                                                                                                                                                                                                  *
// S1H_Raw Sensor1HumidityRaw. Некомпенсированное значение RH BME280 1.(Addr=0x76)                                                                                                         *                                                                                                                                                              *
// S1H_Cmp Sensor1HumidityCompensated. Вычисленное компенсированное значение RH BME280 1.(Addr=0x76)                                                                  *                                                                           * 
// S2H_Raw Sensor2HumidityRaw. Некомпенсированное значение RH BME280 2.(Addr=0x77)                                                                                                         *                                                                                                                                                              *
// S2H_Cmp Sensor2HumidityCompensated. Вычисленное компенсированное значение RH BME280 2.(Addr=0x77)                                                                  *
//************************************************************************************************************************************************
void ClcRH(uint8_t SlvX)
{
    if (SlvX==1)    // Проверка адресации BME280 (1).
{                               // Адресован BME280 (1). Вычисление компенсированного значения RH;
    S1H_Cmp=Tfine-76800.0;
    S1H_Cmp=(S1H_Raw-(S1dig_H4*64.0+S1dig_H5/16384.0*S1H_Cmp))*
    (S1dig_H2/65536.0*(1.0+S1dig_H6/67108864.0*S1H_Cmp*(1.0+S1dig_H3/67108864.0*S1H_Cmp)));
    S1H_Cmp=S1H_Cmp*(1.0-S1dig_H1*S1H_Cmp/524288.0);
}
    if (SlvX==2)    // Проверка адресации BME280 (2).
{                               // Адресован BME280 (2). Вычисление компенсированного значения RH;
    S2H_Cmp=Tfine-76800.0;
    S2H_Cmp=(S2H_Raw-(S2dig_H4*64.0+S2dig_H5/16384.0*S2H_Cmp))*
    (S2dig_H2/65536.0*(1.0+S2dig_H6/67108864.0*S2H_Cmp*(1.0+S2dig_H3/67108864.0*S2H_Cmp)));
    S2H_Cmp=S2H_Cmp*(1.0-S2dig_H1*S2H_Cmp/524288.0);
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1
0 / 0 / 0
Регистрация: 10.02.2017
Сообщений: 1
29.03.2017, 01:54 9
Большое спасибо!

Нет ли тут ошибки:

// S1P_Raw Sensor1TemperatureRaw. Некомпенсированное значение T BME280 1.(Addr=0x76) * *
// S1P_Cmp Sensor1TemperatureCompensated. Вычисленное компенсированное значение T BME280 1.(Addr=0x76) * *
// S2P_Raw Sensor2TemperatureRaw. Некомпенсированное значение P BME280 2.(Addr=0x77)

?

Поделитесь процедурой инициализации. В какие регистры, что кладем для запуска преобразований.
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
29.03.2017, 20:21  [ТС] 10
Vital_Grigoryev, Проверю. Отвечу. Только что увидел пост

Добавлено через 36 минут
Vital_Grigoryev, Спасибо за указание на ошибки. Исправлено. Это комментарии. Ошибки в них не опасны. Только неприличны..
Теперь об инициализации.. Я-то поделюсь чем захотите. Но всё же для того чтобы понять что зачем и куда писать, нужно проштудировать и хорошо усвоить раздел даташита 5.4 Описание регистров. Тогда уже тупо процедурой конфигурации пишешь куда что надо и получаешь неизменно превосходный результат. Но конфигурация всё ж не самая "эротичная" часть работы с этим датчиком. Гораздо "интереснее" процедура пакетного считывания и компоновки калибровочных параметров, а также пакетное чтение и компоновка некомпенсированных значений T;P;RH. Достаточно "достойна" также процедура компенсационных вычислений.. Но датчик достойнейший! Респект и уважуха Bosch Sensortec! Типа DHT-22 и иже с ним ИМХО полный отстой..
Итак. Посмотрите даташит и потом уже в более конкретизированной форме запросите какие процедуры вам нужны. Помогу чем смогу.

Добавлено через 8 часов 47 минут
А последовательность "ввода в строй" BME280 такая: (просто пооперационно, в общих чертах).
1. Подача питания, соответственно.
2. Пакетное считывание, компоновка и сохранение калибровочных параметров T;P;RH. (в каждом экземпляре BME280 они индивидуальны).
3. Запись требуемых параметров (соответственно предполагаемому режиму работы датчика) в регистр "config".
4. Запись требуемых параметров (соответственно предполагаемому режиму работы датчика) в регистр "ctrl_hum"
5. Запись требуемых параметров (соответственно предполагаемому режиму работы датчика) в регистр "ctrl_meas"
После этих операций датчик или уже выполняет циклические измерения выбранных параметров или готов к однократным измерениям по команде (в зависимости от того как он был сконфигурирован).
Далее, в зависимости от выбранного режима работы (непрерывный/по команде):
В случае непрерывного циклического измерения:
1. Чтение некомпенсированного значения T. (Если выбрано измерение при конфигурации).
2. Чтение некомпенсированного значения P. (Если выбрано измерение при конфигурации).
3. Чтение некомпенсированного значения RH. (Если выбрано измерение при конфигурации).
.. С использованием ранее считанных и сохранённых калибровочных параметров:
4. Вычисление компенсированного значения T. (Если необходимо).
5. Вычисление компенсированного значения P. (Если необходимо). (Вычисление значения P в мм.рт.ст. Если необходимо).
6. Вычисление компенсированного значения RH. (Если необходимо).
7. Вывод полученных значений на устройство индикации. (Запись полученных значений в архив (EEPROM) Если необходимо).
-Как-то вот так

Добавлено через 5 минут
В случае измерения по команде, перед чтением некомпенсированных значений T;P;RH каждый раз подаётся команда запуска однократного измерения.
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
22.04.2017, 20:47  [ТС] 11
Небольшое дополнение к "работе с BME280", касающееся измерения атмосферного давления, которое, возможно поможет кому-либо в понимании предмета и в достижении практических результатов при написании программы..
Датчик измеряет абсолютное атмосферное давление, которое имеет место, естественно там где он расположен. Этого достаточно, если стоит задача осуществлять обыкновенные метеонаблюдения. Но если возникнет необходимость соотносить измеренное абсолютное давление с результатами измерений других метеостанций, или выполнять расчёты, касающиеся барометрического нивелирования, то здесь понадобится определение, как минимум двух дополнительных величин, таких как барическая ступень и атмосферное давление, приведённое к уровню моря (авиационная аббревиатура "QNH").
Раскрывать толкование этих величин в рамках поста не буду, т.к. в сети информации хоть лопатой отгребай..
А вот как они вычисляются математически и программно, так это пожалуйста. На понимание предмета были "угроблены" несколько десятков часов времени, но опыт, как говорится, бесценен.
Итак, математическая формула вычисления значения барической ступени (h) в метрах, на высоте расположения датчика (Pизм):
h=8000/Pизм*(1+0,003663*To)
Где:
Ризм - давление в точке измерения.
To - температура воздуха в точке измерения.
0,003663=1/273 - температурный коэффициент расширения смеси газов из которой состоит воздух атмосферы.
Код процедуры:
C
1
h=8000/P_mmHg*(1+.003663*To);
**
Теперь, используя значение барической ступени в точке измерения можно рассчитать приведённое к уровню моря атмосферное давление:
Р прив = Ризм ± (Hизм/h)
Где:
Ризм -давление в точке измерения.
Hизм - высота точки измерения над уровнем моря.
h - значение барической ступени в точке измерения (м).
Ризм+(Hизм/h) если точка измерения выше уровня моря.
Ризм-(Hизм/h) если точка измерения ниже уровня моря.
Код процедуры:
C
1
PRmmHg=PAmmHg+(Alt/h);
..Успехов в "работе с BME280"
1
0 / 0 / 0
Регистрация: 19.02.2020
Сообщений: 1
19.02.2020, 06:36 12
Приветствую!
Хочу добавить свои "пять копеек" в очеловечивание кода вычисления компенсированных значений. В даташите есть два варианта алгоритмов вычисления, один на 23й странице, он же повторён на 50й, другой в приложении на 49й странице.
Для этого вооружимся ручкой, бумагой, знаниями математики за третий класс, и немного знаниями о теории программирования.
Начнём с первого варианта алгоритма.
Из знаний о программировании, вспомним что сдвиг двоичного числа вправо или влево эквивалентен делению-умножению его на степень двойки.
Сдвиг влево равен умножению (N<<x = N*2x) Например N<<3 = N*23 = N*8
Сдвиг вправо, это деление (N>>x = N/2x) Например N>>4 = N/24 = N/16

Погнали! Первая формула. Строка из даташита:
var1 = ((((adc_T>>3) –((BME280_S32_t)dig_T1<<1))) * ((BME280_S32_t)dig_T2)) >> 11;
Отбросим операции приведения типов и раскроем некоторые скобки:
var1 = ((adc_T/8 -dig_T1*2)*dig_T2) / 2048
Ну вот, уже немного интереснее, не правда ли? Вынесем множитель при dig_T1 за скобку.
var1 = ((adc_T/16 -dig_T1)*dig_T2) / 1024
Оставим пока так. Возьмемся за вторую формулу:
var2 = (((((adc_T>>4) –((BME280_S32_t)dig_T1)) * ((adc_T>>4) –((BME280_S32_t)dig_T1))) >> 12) * ((BME280_S32_t)dig_T3)) >> 14;
Вот это частокол из скобок! но на самом деле не все так страшно.
var2 = (((adc_T/16 - dig_T1) * (adc_T/16 - dig_T1) / 4096) * dig_T3) / 16384
Полегчало, но ненамного. Если присмотреться, в первой и второй формулах есть одинаковые части. это (adc_T/16 - dig_T1). Сделаем как в школе учили. Примем их за х:

https://www.cyberforum.ru/cgi-bin/latex.cgi?x =  \frac {adcT}{16} - digT1

Перепишем первую и вторую формулы через х:

https://www.cyberforum.ru/cgi-bin/latex.cgi?\large var1 = \frac {x * digT2}{1024}

https://www.cyberforum.ru/cgi-bin/latex.cgi?\large var2 = \frac {\frac {x * x * digT3}{4096}}{16384} = \frac {x ^ 2 * digT3}{4096 *16384} = \frac {x ^ 2 * digT3}{67108864}

Тут уже просматривается что-то понятное человеку. Хотя смущает огромное число в знаменателе второй формулы.

Далее из даташита:
t_fine = var1 + var2;

https://www.cyberforum.ru/cgi-bin/latex.cgi?t_fine = \frac {x * digT2}{1024} + \frac {x ^ 2 * digT3}{67108864}

вынесем за скобки первый знаменатель:

https://www.cyberforum.ru/cgi-bin/latex.cgi?t_fine = (x * digT2 + \frac {x ^ 2 * digT3}{65536}) / 1024

Итого:
x = adc_t / 16 - dig_T1;
t_fine = (x * dig_T2 + x *x * digT3 / 65536) / 1024;

Вот как то так частокол из скобок превратился во вполне читабельную форму из всего двух строчек кода.
Если взять код со страницы 49 и проделать те же манипуляции раскрывая скобки и приводя знаменатели, получим ту же формулу.
Что за чудо-программисты у производителя рожали сей мозголомный нечитаемый говнокод, непонятно. Возможно им платят за строки кода, а не за за удобство восприятия и понимания конечным потребителем.
Претензии к этим чудо программерам возникают когда мы читаем код дальше, и видим формулу преобразования переменной t_fine в конечную температуру. Код со страницы 49:
T = (var1 + var2) / 5120.0;
то есть
T = t_fine / 5120
Тут всё довольно понятно, формула выдаёт корректные значения температуры.
Теперь со страницы 50:
T = (t_fine * 5 + 128) >> 8;
T = (t_fine * 5 + 128) /256;
Раскроем скобки
T = t_fine * 5 / 256 + 0.5;
WTF!!!! это совсем не похоже на предыдущее T = t_fine / 5120
Долго ломал голову, но догадался. Поделим первую формулу на вторую отбросим для простоты число 128:

https://www.cyberforum.ru/cgi-bin/latex.cgi?\large {\frac {5*t_fine}{256}} /  {\frac {t_fine}{5120}}

=

https://www.cyberforum.ru/cgi-bin/latex.cgi?\large {\frac {5*t_fine}{256}} *  {\frac {5120}{t_fine}}

=

https://www.cyberforum.ru/cgi-bin/latex.cgi?{\frac {5*5120}{256}} = 100

!!!!

То есть формула во втором случае выдаёт значения в СТО РАЗ БОЛЬШЕ!!!
Кто нибудь из программистов производителя тестировал код из даташита? Как так, Карл?

В общем подход, думаю, понятен. И если подойти к дебрям кода со знаниями третьеклассника, всё станет гораздо проще и дальнейшее приведение формул в человеческий вид не составит большого труда.
Удачи!
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
19.02.2020, 16:51  [ТС] 13
starr1978, Спасибо Вам за вклад, внесённый в данную тему.
Меня тоже эта тема с кодом компенсации очень сначала "сплющила", но я взял тупо код из даташита, тот, который для 32-разрядных вычислений и вот он работает уже 2 года. Если Вам будет интересен файл с секцией вычислений параметров для STM32, то я буду рад опубликовать.
Насколько я понял [с высоты своих скромных навыков программирования], то этот код с безумным количеством сдвигов предназначен для МК типа PIC16xxxx, 8-разрядных.
Досвиданья, удачи!
0
0 / 0 / 0
Регистрация: 24.03.2018
Сообщений: 1
04.03.2020, 02:21 14
starr1978, программисты из Bosch Sensortec не напрасно выдали столь зубодробительный код. Логические операции и битовые сдвиги, в частности, более нативны для контроллера, нежели математические, даже за 3 класс.
Ради интереса, я попробовал "упростить" компенсацию температуры в одном вялотекущем проекте с применением BME280. Так код занял места на 56 байт больше. А еще ведь, давление и влажность с не менее убойным кодом. Этак и контроллер придется менять, на более вместительный.
То есть формула во втором случае выдаёт значения в СТО РАЗ БОЛЬШЕ!!!
Ну да. Это число с фиксированной точкой и разрешением в сотых градуса. Довольно удобно для любителей графиков, как и давление в Паскалях - оно подинамичнее ртутного столбика.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.03.2020, 02:21

Обмен опытом по программированию на С++
А никто не знает сайты, направленные на обмен опытом между программистами, как здесь:...

Framework / Workflow - обмен опытом
Чем больше я работаю, тем лучше я понимаю, что нужно бизнесу, какие задачи можно вынести в...

Обмен опытом: свойство Enabled
Приветствую. Хотел бы обменяться опытом. Так вот. Представьте себе стандартную форму с большим...

Проверка скорости кода. Обмен опытом
Вводные данные: - C++ стандарта 11 - gcc Работаю над ускорением кода для работы со строками....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.