BMP280, датчик давления и температуры
Re: BMP280, датчик давления и температуры
ПростоНуб, про sprintf(), itoa(), utoa() гугл тоже подсказывал, но там непонятное форматирование в аргументах и говорят память отъедают хорошо. Ну и доступного хелпа по ним не удалось отыскать. За упоминание о Double dabble - спасибо! Поищу, что за зверь.
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: BMP280, датчик давления и температуры
[uquote="MOHCTEP",url="/forum/viewtopic.php?p=3584134#p3584134"]За упоминание о Double dabble - спасибо! Поищу, что за зверь.[/uquote]
А чего его искать? В английской вики даже пример есть для него на C: https://en.wikipedia.org/wiki/Double_dabble
А чего его искать? В английской вики даже пример есть для него на C: https://en.wikipedia.org/wiki/Double_dabble
Re: BMP280, датчик давления и температуры
[uquote="MOHCTEP",url="/forum/viewtopic.php?p=3584090#p3584090"]По сути, вся верхняя возня придумана, чтоб не выводить левые нули при любой десятичной разрядности аргумента. Иначе говоря у вас код выведет температуру нормально, а давление в паскалях уже - проблема. По вашему коду есть вопросы.
1). "if (t < 0) { t = -t; uart('-'); }". Как это условие у вас срабатывает, если t - без знаковая(uint16_t)?
2) Покажите, ради хвоста, паяльника и прочих мимоз, как у вас выглядит эта самая "-567" в 16-ричном виде! Очень прошу. И главное куда этот долбаный минус засунулся в 32-битном результате даташитовских манипуляций? У вас все просто "if (n < 0)" = кайф!
У меня, почему-то, эта самая "n" всегда больше нуля.[/uquote]
Знаковая или без знаковая важно при работе в десятичном формате, а в бинарном виде все останется тем же -567 = 0b1111110111001001 = 0xFDC9, а с другим знаком 567 = 0b0000001000110111 = 0x0237;
То есть при температуре -5,67 гр.С переменная _bmp280_temp должна быть равна 0x0xFDC9. Если это же число представить в десятичном беззнаковом виде, получится 64969 вместо нужных -567, несмотря на то что в hex виде данные числа останутся одинаковыми.
А в каком компиляторе вы пишите?
1). "if (t < 0) { t = -t; uart('-'); }". Как это условие у вас срабатывает, если t - без знаковая(uint16_t)?
2) Покажите, ради хвоста, паяльника и прочих мимоз, как у вас выглядит эта самая "-567" в 16-ричном виде! Очень прошу. И главное куда этот долбаный минус засунулся в 32-битном результате даташитовских манипуляций? У вас все просто "if (n < 0)" = кайф!
Знаковая или без знаковая важно при работе в десятичном формате, а в бинарном виде все останется тем же -567 = 0b1111110111001001 = 0xFDC9, а с другим знаком 567 = 0b0000001000110111 = 0x0237;
То есть при температуре -5,67 гр.С переменная _bmp280_temp должна быть равна 0x0xFDC9. Если это же число представить в десятичном беззнаковом виде, получится 64969 вместо нужных -567, несмотря на то что в hex виде данные числа останутся одинаковыми.
А в каком компиляторе вы пишите?
Я, конечно, могу вести себя нормально. Но чёрт возьми - это ведь так скучно.
Re: BMP280, датчик давления и температуры
Так, а если она беззнаковая (всегда положительная), то компилятор ее всегда будет считать больше нуля и, при отрицательной температуре, условие не сработает же...
Спасибо! С битовой разностью + и - вы меня успокоили. Переписал я уже "num2dec" - видит она теперь и отрицательные числа корректно - проверил именно на таком варианте. Причем потестировал именно _bmp280_temp, вот этак вот...
Вопрос остался, почему даташитовская функция компенсации не переворачивает отрицательную температуру в дополнительный код?
Прошу прощения за мое невежество, но - не знаю. Пишу в 7 AtmelStudio, на уровне чайника с боольшим носиком. 
Спасибо! С битовой разностью + и - вы меня успокоили. Переписал я уже "num2dec" - видит она теперь и отрицательные числа корректно - проверил именно на таком варианте. Причем потестировал именно _bmp280_temp, вот этак вот...
Код: Выделить всё
num2dec1(_bmp280_temp,2);
uart_puts("\r");
_bmp280_temp--;
_bmp280_temp^=0xFFFFFFFF;
num2dec1(_bmp280_temp,2);
uart_puts("\r");
// вывод в терминале
23.22
-23.22DESIER писал(а):А в каком компиляторе вы пишите?
Re: BMP280, датчик давления и температуры
[uquote="MOHCTEP",url="/forum/viewtopic.php?p=3583888#p3583888"]Здоровья читателю.
Столкнулся с такой же проблемой с выводом отрицательных или около-нулевых температур
...
не понятно, когда температура становится отрицательной/нулевой?
Братцы, если кому удалось цивилизовано решить эту проблему, поделитесь волшебством пожалуйста.[/uquote]
Я писал о том как я решил эту проблему:
[uquote="passer_by",url="/forum/viewtopic.php?p=3564108#p3564108"][/uquote]
В даташите на BME280 мельком упоминается, что данные в регистрах пишутся в дополнительном коде.
И этот код просто переводит отрицательное значение в дополнительном коде в прямой с установленным знаком (-), понятый для того же sprintf().
К примеру:
+25.0625 | 0000 0001 1001 0001 | 0191h
-25.0625 | 1111 1110 0110 1111 | FE6Fh
Почему это не оговорено в примере из даташита, хрен знает. Может они дали свободу выбора по преобразованию дополнительный/прямой код, можно по разному преобразовывать.
И ни каких танцев с бубном
Столкнулся с такой же проблемой с выводом отрицательных или около-нулевых температур
...
не понятно, когда температура становится отрицательной/нулевой?
Братцы, если кому удалось цивилизовано решить эту проблему, поделитесь волшебством пожалуйста.[/uquote]
Я писал о том как я решил эту проблему:
[uquote="passer_by",url="/forum/viewtopic.php?p=3564108#p3564108"][/uquote]
В даташите на BME280 мельком упоминается, что данные в регистрах пишутся в дополнительном коде.
И этот код просто переводит отрицательное значение в дополнительном коде в прямой с установленным знаком (-), понятый для того же sprintf().
К примеру:
+25.0625 | 0000 0001 1001 0001 | 0191h
-25.0625 | 1111 1110 0110 1111 | FE6Fh
Код: Выделить всё
if (temper_float >100) // если значение температуры перевалило в отрицательные значения
{
temper_float = 409.6-temper_float;
temper_float = -temper_float;
} И ни каких танцев с бубном
Если птичка уже в одном прыжке от тебя, всё-таки побереги свой нос, может она за оконным стеклом???
Re: BMP280, датчик давления и температуры
passer_by, дык она, забака такая, никогда у меня не была в доп.коде. Вот положил на датчик кусок льда и смотрите, что получаю: рав данные тоже там есть
Еще, в кодах на гитхабе от BoschSensortec есть допустимые пределы калибровочных констант. Я их процитирую, для BMP280:
И простой тест нашел ошибки аж в 4!! константах.
Если с "Т3" я соглашусь, то с давлением непонятно, они-то вроде как в диапазон вписываются...
Калибровка у меня читается разово, при подаче питания. Ну забил я Т3 = -2000. Ошибка пропала, но поведение датчика не изменилось. Точно также, при около-нулевой температуре, прыгает в Сахару.
Спойлер
Код: Выделить всё
temperature = 1.32 C
pressure = 97999 Pa, 735.05 mmHg
RAW data
raw_pressure = 0x0004DCE0 := 318688
raw_temperature = 0x0006F840 := 456768
o
temperature = 1.27 C
pressure = 97997 Pa, 735.03 mmHg
RAW data
raw_pressure = 0x0004DCB0 := 318640
raw_temperature = 0x0006F7A0 := 456608
o
temperature = 1.19 C
pressure = 97994 Pa, 735.01 mmHg
RAW data
raw_pressure = 0x0004DC60 := 318560
raw_temperature = 0x0006F6A0 := 456352
o
temperature = 1.02 C
pressure = 98000 Pa, 735.06 mmHg
RAW data
raw_pressure = 0x0004DBA0 := 318368
raw_temperature = 0x0006F490 := 455824
/* И ВНЕЗАПНО!! */
o
temperature = 86 C
pressure = 97993 Pa, 735.00 mmHg
RAW data
raw_pressure = 0x0004DB10 := 318224
raw_temperature = 0x0006F280 := 455296
o
temperature = 85 C
pressure = 97995 Pa, 735.02 mmHg
RAW data
raw_pressure = 0x0004DB00 := 318208
raw_temperature = 0x0006F260 := 455264Спойлер
Код: Выделить всё
# define BMP280_ST_DIG_T1_MIN UINT16_C ( 19000 )
# define BMP280_ST_DIG_T1_MAX UINT16_C ( 35000 )
# define BMP280_ST_DIG_T2_MIN UINT16_C ( 22000 )
# define BMP280_ST_DIG_T2_MAX UINT16_C ( 30000 )
# define BMP280_ST_DIG_T3_MIN INT16_C (- 3000 )
# define BMP280_ST_DIG_T3_MAX INT16_C (- 1000 )
# define BMP280_ST_DIG_P1_MIN UINT16_C ( 30000 )
# define BMP280_ST_DIG_P1_MAX UINT16_C ( 42000 )
# define BMP280_ST_DIG_P2_MIN INT16_C (- 12970 )
# define BMP280_ST_DIG_P2_MAX INT16_C (- 8000 )
# define BMP280_ST_DIG_P3_MIN INT16_C (- 5000 )
# define BMP280_ST_DIG_P3_MAX UINT16_C ( 8000 )
# define BMP280_ST_DIG_P4_MIN INT16_C (- 10000 )
# define BMP280_ST_DIG_P4_MAX UINT16_C ( 18000 )
# define BMP280_ST_DIG_P5_MIN INT16_C (- 500 )
# define BMP280_ST_DIG_P5_MAX UINT16_C ( 1100 )
# define BMP280_ST_DIG_P6_MIN INT16_C (- 1000 )
# define BMP280_ST_DIG_P6_MAX UINT16_C ( 1000 )
# define BMP280_ST_DIG_P7_MIN INT16_C (- 32768 )
# define BMP280_ST_DIG_P7_MAX UINT16_C ( 32767 )
# define BMP280_ST_DIG_P8_MIN INT16_C (- 30000 )
# define BMP280_ST_DIG_P8_MAX UINT16_C ( 10000 )
# define BMP280_ST_DIG_P9_MIN INT16_C (- 10000 )
# define BMP280_ST_DIG_P9_MAX UINT16_C ( 30000 )Спойлер
Код: Выделить всё
Calibration coefficients
T1 28286
T2 26445
T3 50 X
P1 38173
P2 -11029
P3 3024
P4 6663
P5 -33 X
P6 -7 X
P7 15500
P8 -14600 X
P9 6000
WARNING! 4 ERROR[s] in calibration constants found.Калибровка у меня читается разово, при подаче питания. Ну забил я Т3 = -2000. Ошибка пропала, но поведение датчика не изменилось. Точно также, при около-нулевой температуре, прыгает в Сахару.
Re: BMP280, датчик давления и температуры
[uquote="MOHCTEP",url="/forum/viewtopic.php?p=3595668#p3595668"]passer_by, дык она, забака такая, никогда у меня не была в доп.коде. В[/uquote]
А Вы тут ни причем. BME280 сама пишет в регистры в дополнительном коде. Все данные там так пишутся. Математику видишь ли им удобнее в этом формате вычислять
Формат регистра

таблица соответствия
Что косается ошибок в чтении калибровочных данных, скорее всего у Вас ошибки в написании чтения калибровочных регистров BME280.
Я, к примеру вот такую хрень городил для чтения 24 бит
А Вы тут ни причем. BME280 сама пишет в регистры в дополнительном коде. Все данные там так пишутся. Математику видишь ли им удобнее в этом формате вычислять
Формат регистра
таблица соответствия
Ну или как у меня. Иначе ни как.При положительном значении ( S=0 ) код перевести в десятичный и умножить на 0,0625 °C.
При отрицательном значении ( S=1 ) сначала необходимо перевести дополнительный код в прямой. Для этого надо инвертировать каждый разряд двоичного кода и прибавить 1. А затем перевести в десятичный и умножить на 0,0625 °C.
Что косается ошибок в чтении калибровочных данных, скорее всего у Вас ошибки в написании чтения калибровочных регистров BME280.
Я, к примеру вот такую хрень городил для чтения 24 бит
Код: Выделить всё
uint32_t I2C1_ReadDataU24(uint8_t addr, uint8_t Reg)
{
uint8_t data[3];
uint32_t rezult =0;
data[0] = I2C1_MemoryRead(addr, Reg);
data[1] = I2C1_MemoryRead(addr, Reg + 1);
data[2] = I2C1_MemoryRead(addr, Reg + 2);
rezult = data[0];
rezult = rezult<<8;
rezult |= data[1];
rezult = rezult<<8;
rezult |= data[2];
return rezult;
}Если птичка уже в одном прыжке от тебя, всё-таки побереги свой нос, может она за оконным стеклом???
Re: BMP280, датчик давления и температуры
passer_by, спасибо! Попробую так, вдруг чего получится? 
- AlanDrakes
- Прорезались зубы
- Сообщения: 236
- Зарегистрирован: Пн июл 04, 2016 16:51:22
- Откуда: Россия, Омск
Re: BMP280, датчик давления и температуры
Взялся я за этот датчик и... товарищи форумчане, кто-нибудь сталкивался с тем, что датчик зависает при чтении области калибровочных констант?
У меня датчик позволяет считать адреса 0x88~0x9D (Calib_T1~Calib_P8), но при попытке чтения адресов дальше, датчик не возвращает нишу в Z-состояние.
Скриншот из логического анализатора: Видно, что идёт запись регистра 0xF4 = 0x6F, установка указателя на 0x9E и попытка чтения его. И всё. Шина зависает в состоянии нуля.
Пришлось вбить в код костыль, который после чтения именно байта 9E несколько раз дёргает SCK до тех пор, пока SDA не будет отпущен. Кто-нибудь сталкивался с таким поведением?
У меня датчик позволяет считать адреса 0x88~0x9D (Calib_T1~Calib_P8), но при попытке чтения адресов дальше, датчик не возвращает нишу в Z-состояние.
Скриншот из логического анализатора: Видно, что идёт запись регистра 0xF4 = 0x6F, установка указателя на 0x9E и попытка чтения его. И всё. Шина зависает в состоянии нуля.
Пришлось вбить в код костыль, который после чтения именно байта 9E несколько раз дёргает SCK до тех пор, пока SDA не будет отпущен. Кто-нибудь сталкивался с таким поведением?
Re: BMP280, датчик давления и температуры
[uquote="AlanDrakes",url="/forum/viewtopic.php?p=4245790#p4245790"]Взялся я за этот датчик и... товарищи форумчане, кто-нибудь сталкивался с тем, что датчик зависает при чтении области калибровочных констант?
У меня датчик позволяет считать адреса 0x88~0x9D (Calib_T1~Calib_P8), но при попытке чтения адресов дальше, датчик не возвращает нишу в Z-состояние.
Скриншот из логического анализатора:[/uquote]У меня не BMP280, а BME280. Подозреваю, что это одно и то же (I2C-адрес тот же).
Какой-то у Вас странный способ работы....
В-первых: зачем читать по-байтно? Калибровочные данные там лежат 2-мя сплошными блоками: 0x88...0xA1 и 0xE1...0xF0. И соответственно - считываются двумя многобайтными транзакциями: первая = длиной 26 байт, вторая == 7 байт.
Во-вторых: судя по приложенным осциллограммам - переключение на чтение делаете "стоп-стартом", я же для переключения на чтение использую "повторный старт". Хотя возможно, что будет работать и так и так. Но можно проверить.
У меня датчик позволяет считать адреса 0x88~0x9D (Calib_T1~Calib_P8), но при попытке чтения адресов дальше, датчик не возвращает нишу в Z-состояние.
Скриншот из логического анализатора:[/uquote]У меня не BMP280, а BME280. Подозреваю, что это одно и то же (I2C-адрес тот же).
Какой-то у Вас странный способ работы....
Во-вторых: судя по приложенным осциллограммам - переключение на чтение делаете "стоп-стартом", я же для переключения на чтение использую "повторный старт". Хотя возможно, что будет работать и так и так. Но можно проверить.
- AlanDrakes
- Прорезались зубы
- Сообщения: 236
- Зарегистрирован: Пн июл 04, 2016 16:51:22
- Откуда: Россия, Омск
Re: BMP280, датчик давления и температуры
[uquote="jcxz",url="/forum/viewtopic.php?p=4245917#p4245917"]В-первых: зачем читать по-байтно? Калибровочные данные там лежат 2-мя сплошными блоками: 0x88...0xA1 и 0xE1...0xF0.[/uquote]
Оно тупо зависает насмерть и не отпускает шину, из-за этого машина состояний в блоке I2C бесконечно ждёт.
В моём случае - BMP280, только с одним блоком 0x88~0xA1 (хотя 0xA0-0xA1 помечены как `reserved` в даташите). А чтение стабильно запинается на 0x9E. Следующий читает корректно.
Ну и это как раз кусок отладочного кода отрабатывал. Я искал, какой именно байт ломает всё.
[uquote="jcxz",url="/forum/viewtopic.php?p=4245917#p4245917"]Во-вторых: судя по приложенным осциллограммам - переключение на чтение делаете "стоп-стартом", я же для переключения на чтение использую "повторный старт". Хотя возможно, что будет работать и так и так. Но можно проверить.[/uquote] Взял готовые функции из другого проекта на этом же кристалле. Там были другие сигнатуры и проще всего оказалось записать массив из одного элемента, а потом прочитать байт. Сути это не меняет, чип стабильно вешается.
Помог только "ногодрыг". Хорошо виден во втором скриншоте логического анализатора. Вообще не понимаю. Вроди бы и руки не из *опы, а вот такую штуку получил. И ведь стабильно.
Тосовал транзакции, вставлял задержки, убирал, читал массивом - вообще пофигистично. Такое ощущение, что сам датчик битый
В магазине последний взял. Видимо, моя "удача".
Оно тупо зависает насмерть и не отпускает шину, из-за этого машина состояний в блоке I2C бесконечно ждёт.
Ну и это как раз кусок отладочного кода отрабатывал. Я искал, какой именно байт ломает всё.
[uquote="jcxz",url="/forum/viewtopic.php?p=4245917#p4245917"]Во-вторых: судя по приложенным осциллограммам - переключение на чтение делаете "стоп-стартом", я же для переключения на чтение использую "повторный старт". Хотя возможно, что будет работать и так и так. Но можно проверить.[/uquote] Взял готовые функции из другого проекта на этом же кристалле. Там были другие сигнатуры и проще всего оказалось записать массив из одного элемента, а потом прочитать байт. Сути это не меняет, чип стабильно вешается.
Помог только "ногодрыг". Хорошо виден во втором скриншоте логического анализатора. Вообще не понимаю. Вроди бы и руки не из *опы, а вот такую штуку получил. И ведь стабильно.
Тосовал транзакции, вставлял задержки, убирал, читал массивом - вообще пофигистично. Такое ощущение, что сам датчик битый
Re: BMP280, датчик давления и температуры
[uquote="AlanDrakes",url="/forum/viewtopic.php?p=4245981#p4245981"]Тосовал транзакции, вставлял задержки, убирал, читал массивом - вообще пофигистично..[/uquote]Я бы попробовал всё-таки многобайтные транзакции и изменить тип переключения на "повторный старт". Как уже писал выше.
[uquote="AlanDrakes",url="/forum/viewtopic.php?p=4245981#p4245981"]Сути это не меняет, чип стабильно вешается.[/uquote]А с чего вообще решили, что "чип вешается"? По выложенной осциллограмме видно только, что I2C-мастер (МК) почему-то остановил тактирование SCLK на ACK-бите. Даже не дотактировав его. Зависла ваша программа похоже.
[uquote="AlanDrakes",url="/forum/viewtopic.php?p=4245981#p4245981"]Сути это не меняет, чип стабильно вешается.[/uquote]А с чего вообще решили, что "чип вешается"? По выложенной осциллограмме видно только, что I2C-мастер (МК) почему-то остановил тактирование SCLK на ACK-бите. Даже не дотактировав его. Зависла ваша программа похоже.
- AlanDrakes
- Прорезались зубы
- Сообщения: 236
- Зарегистрирован: Пн июл 04, 2016 16:51:22
- Откуда: Россия, Омск
Re: BMP280, датчик давления и температуры
[uquote="jcxz",url="/forum/viewtopic.php?p=4246413#p4246413"]А с чего вообще решили, что "чип вешается"? По выложенной осциллограмме видно только, что I2C-мастер (МК) почему-то остановил тактирование SCLK на ACK-бите. Даже не дотактировав его. Зависла ваша программа похоже.
[/uquote]
К сожалению, не так. Код выглядит так:
Там вбит костыль, который после зависания шины дёргает её до тех пор, пока та не освободится. И именно на байте 0x9E.
Сама функция I2C_Read8 выглядит так:
Самое смешное, что код зависает на следующем обращении к шине. Вызывается i2c_write8 () и код зависает на ожидании TXE, но так как шина в состоянии активности (датчик не отпустил её), то... всё.
На шине сейчас висят два датчика - AHT10 и BMP280. Если отключить последний - работает сутками. Проверено - за три выходных данные читались.
Если отключить первый - вешается на цикле опроса BMP'шки в рандомный момент времени
Вообще не понимаю причину. То есть, код работает, а потом вдруг зависает.
Снял с шины AHT10, оставив подключенным только BMP280. Работает уже пол часа. Чёрт знает что. Но не тайминги же...
К сожалению, не так. Код выглядит так:
Там вбит костыль, который после зависания шины дёргает её до тех пор, пока та не освободится. И именно на байте 0x9E.
Код: Выделить всё
BMPE_Cal.dig_P9 = I2C_Read8(BMPE_Address, 0x9E);
// Костыль. Датчик вешает шину, не позволяя дать NACK.
if ((GPIOF->IDR & GPIO_IDR_IDR_0) == 0) {
GPIOF->BSRR = GPIO_BSRR_BS_1;
GPIOF->MODER &= 0xFFFFFFF3;
GPIOF->MODER |= 0x00000004;
while ((GPIOF->IDR & GPIO_IDR_IDR_0) == 0) {
delay_us(5);
GPIOF->BSRR = GPIO_BSRR_BR_1;
delay_us(5);
GPIOF->BSRR = GPIO_BSRR_BS_1;
};
GPIOF->MODER &= 0xFFFFFFF3;
GPIOF->MODER |= 0x00000008;
};
InitI2C2();
Код: Выделить всё
uint8_t I2C_Read8(uint8_t DevAddr, uint8_t RegAddr) {
uint8_t value;
(void) (I2C2->ISR);
I2C2->TXDR = RegAddr;
I2C2->ICR = I2C_ICR_STOPCF;
I2C2->CR2 = (I2C_CR2_AUTOEND | ((DevAddr << 1) & 0xFE) | (1<<16) | I2C_CR2_START);
while (!(I2C2->ISR & (I2C_ISR_TXE | I2C_ISR_NACKF))) {};
if (I2C2->ISR & I2C_ISR_NACKF) {
I2C2->ICR = I2C_ICR_STOPCF | I2C_ICR_NACKCF;
delay_ms(1);
return -1;
};
I2C2->ICR = 0x3F38; // В очередной раз сбрасываем флаги
// Настраиваем модуль на чтение одного (1) байта, сразу готовимся ответить NACK, и запускаем (START) передачу.
I2C2->CR2 = (I2C_CR2_AUTOEND | I2C_CR2_NACK | ((DevAddr << 1) & 0xFE) | I2C_CR2_RD_WRN | (1<<16) | I2C_CR2_START);
while (!(I2C2->ISR & I2C_ISR_RXNE)) {}; // Успешно читаем результат
value = (I2C2->RXDR); // Возвращаем значение. STOP должен сгенерироваться самостоятельно (AUTOEND).
return value;
}
Код: Выделить всё
void I2C_Write8(uint8_t DevAddr, uint8_t RegAddr, uint8_t RegValue) {
I2C2->TXDR = RegAddr;
I2C2->ICR = 0x3F38;
I2C2->CR2 = (((DevAddr << 1) & 0xFE) | (2<<16) | I2C_CR2_START);
while (!(I2C2->ISR & I2C_ISR_TXE)) {}; // <--------- Вот тут виснем, ибо SCK = 1, SDA = 0. WTF?
I2C2->TXDR = RegValue;
while (!(I2C2->ISR & I2C_ISR_TXE)) {};
I2C2->CR2 = I2C_CR2_STOP;
}Если отключить первый - вешается на цикле опроса BMP'шки в рандомный момент времени
Снял с шины AHT10, оставив подключенным только BMP280. Работает уже пол часа. Чёрт знает что. Но не тайминги же...
Re: BMP280, датчик давления и температуры
[uquote="AlanDrakes",url="/forum/viewtopic.php?p=4246686#p4246686"]К сожалению, не так. Код выглядит так:[/uquote]Что именно "не так"? Вы свою же осциллограмму смотрели?? Похоже что нет.

Видно, что ACK недотактирован. Не завершаете корректно I2C-транзакцию.
И зачем втюхивать какой-то "код", даже не указав к какому МК он относится??
Изучите получше I2C своего МК. Судя по осциллограмме: скорее всего не завершаете корректно I2C-транзакцию и начинаете новую. Без хрустального шара никто не сможет угадать какой МК ковыряете и что именно делаете.
PS: И хорошим тоном является не только:
a) указывать название МК;
b) подписывать - какая осциллограмма к какому действию относится;
c) подписывать названия сигналов на осциллограмме.
Видно, что ACK недотактирован. Не завершаете корректно I2C-транзакцию.
И зачем втюхивать какой-то "код", даже не указав к какому МК он относится??
Изучите получше I2C своего МК. Судя по осциллограмме: скорее всего не завершаете корректно I2C-транзакцию и начинаете новую. Без хрустального шара никто не сможет угадать какой МК ковыряете и что именно делаете.
PS: И хорошим тоном является не только:
a) указывать название МК;
b) подписывать - какая осциллограмма к какому действию относится;
c) подписывать названия сигналов на осциллограмме.
- AlanDrakes
- Прорезались зубы
- Сообщения: 236
- Зарегистрирован: Пн июл 04, 2016 16:51:22
- Откуда: Россия, Омск
Re: BMP280, датчик давления и температуры
[uquote="jcxz",url="/forum/viewtopic.php?p=4246860#p4246860"][uquote="AlanDrakes",url="/forum/viewtopic.php?p=4246686#p4246686"]К сожалению, не так. Код выглядит так:[/uquote]Что именно "не так"? Вы свою же осциллограмму смотрели?? Похоже что нет.

Видно, что ACK недотактирован. Не завершаете корректно I2C-транзакцию.
И зачем втюхивать какой-то "код", даже не указав к какому МК он относится??
Изучите получше I2C своего МК. Судя по осциллограмме: скорее всего не завершаете корректно I2C-транзакцию и начинаете новую. Без хрустального шара никто не сможет угадать какой МК ковыряете и что именно делаете.
PS: И хорошим тоном является не только:
a) указывать название МК;
b) подписывать - какая осциллограмма к какому действию относится;
c) подписывать названия сигналов на осциллограмме.[/uquote]
[Zanuda Mode ON]
1. То есть, вас не смутило, что датчик ЯВНО I2C и висит на этой шине?
2. На "осциллограмме" (хотя это скриншот логического анализатора, но не суть) видно и начало транзакции и такая же транзакция с другим адресом, которая проходит корректно (и даже виден импульс, появляющийся в момент передачи шины slave->master) прямо под всеми ACK кроме адреса 0x9E.
a - STM32F767ZGT6 (аналогично ведёт себя и STM32L152) при наличии двух датчиков на шине.
b - Обе относятся к моменту сбоя ответа. И теперь непонятно, к сбою какого из датчиков - AHT10 / BME280.
c - 0 - SCK, 1 - SDA. Два следующих - болтаются в воздухе. Над ними - встроенный в интерфейс декодер сигналов I2C.
[Zanuda Mode OFF]
------------------------------------------------------------------------------------
По результатам теста стало понятно, что ничего не понятно.
ATH10 (Single) -> OK. Работает без нареканий все выходные (прошлые)
BME280 (Single) -> OK. Работает без нареканий все выходные (текущие)
AHT10 + BME280 -> Stuck. Зависает в случайные моменты времени от 30 секунд (~5 циклов запросов данных) до 10 минут.
Всё питается от 3.6V.
И у меня такое ощущение, что AHT10 в какой-то момент считает, что обращаются к нему. И имеются некоторые подозрения на корректность работы схемы сдвига уровня на его плате:

Убрал с платы стабилизатор и обошёл парой перемычек "схему сдвига уровней". Наблюдаем-с...
Обошёл схему сдвига уровней на AHT10. Не помогло.
Поменял адрес оного с 0x38 на 0x39. Не помогло.
Уменьшил агрессивность таймингов шины I2C:
I2C2->TIMINGR = 0x40541010; (SDA_DELAY)
Теперь SDA меняется на четыре такта позже, чем SCK, а не на один, как работало с любыми другими чипами, к которым у меня был доступ. Вроди бы заработало.
Самое странное, что работает с одним датчиком на шине без сбоев!.
UPD 2:
Не помогло. Но на этот раз видно, что дело где-то на стороне одного из ведомых - это видно по фазе сигнала. STM32 делает переход уровня на SDA со сдвигом на указанное выше количество тактов (4) (хотя для наглядности выставил
, общая длительность одного бита - 0x10 + 0x10 = 32 условных такта.
В то время как ведомый тянет линию вниз по спаду уровня на SCK.
У меня создаётся подозрение, что AHT10 наблюдает за линией и "находит" START там, где его нет, а за ним из байта 0x72 читает "свой" адрес и отвечает не в попад, потому как стабильно передача обрывается, когда BMP280 выдает ответ: 0x6F 0x82 0xC0 0x7E 0x72 0xC0.
:/
Теперь виню второй датчик. Снял новый дамп обмена на шине. Дополнительно подключил канал (2) непосредственно рядом с самим AHT10 ("SDA-AHT" на скниншотах). Но ничего понятнее не стало.
Момент запуска: (Прошу обратить внимание на время на шкале ~0.9с - время от момента начала захвата). Собственно, чтение области калибровочных констант (на скниншоте не очень хорошо видно, но всё читается), затем - проверка статуса AHT10. Удачная. (39-E1-08-00). До момента T+137c всё идёт корректно, посылки идут пачкой:
AHT10->Trigger()
+0.1c
AHT10->GetData() -> Status? -> Not ready
+0.1c
AHT10->GetData() -> Status? -> Not ready
+0.1c
AHT10->GetData() -> Status? -> Conversion Done
BMP280->Read (0xF7..0xFC)
Скриншот не прикладываю - тут всё похоже на вертикальные полоски и паузу в пару секунд.
И по какой-то причине когда датчик давления выдаёт 0x72 в предпоследнем байте - всё виснет.
Проверил по битам, да, там можно угадать х111001 - 0x39
Общий вид транзакции: И сами биты: И разница между фазами сигналов, когда шину ведёт STM32 и BMP280.
Первый оставляет задержку в 2.9мкс между переходом SCK 1->0 и изменением уровня SDA, второй - 0,2мкс (плюс-минус, потому что захват происходил на 10MSa/s, ибо шина изначально медленная). Вот и вопрос: И как это победить? У меня пока банальный вариант - разнести датчики на физически разные шины. Но это же костыль!
Видно, что ACK недотактирован. Не завершаете корректно I2C-транзакцию.
И зачем втюхивать какой-то "код", даже не указав к какому МК он относится??
Изучите получше I2C своего МК. Судя по осциллограмме: скорее всего не завершаете корректно I2C-транзакцию и начинаете новую. Без хрустального шара никто не сможет угадать какой МК ковыряете и что именно делаете.
PS: И хорошим тоном является не только:
a) указывать название МК;
b) подписывать - какая осциллограмма к какому действию относится;
c) подписывать названия сигналов на осциллограмме.[/uquote]
[Zanuda Mode ON]
1. То есть, вас не смутило, что датчик ЯВНО I2C и висит на этой шине?
2. На "осциллограмме" (хотя это скриншот логического анализатора, но не суть) видно и начало транзакции и такая же транзакция с другим адресом, которая проходит корректно (и даже виден импульс, появляющийся в момент передачи шины slave->master) прямо под всеми ACK кроме адреса 0x9E.
a - STM32F767ZGT6 (аналогично ведёт себя и STM32L152) при наличии двух датчиков на шине.
b - Обе относятся к моменту сбоя ответа. И теперь непонятно, к сбою какого из датчиков - AHT10 / BME280.
c - 0 - SCK, 1 - SDA. Два следующих - болтаются в воздухе. Над ними - встроенный в интерфейс декодер сигналов I2C.
[Zanuda Mode OFF]
------------------------------------------------------------------------------------
По результатам теста стало понятно, что ничего не понятно.
ATH10 (Single) -> OK. Работает без нареканий все выходные (прошлые)
BME280 (Single) -> OK. Работает без нареканий все выходные (текущие)
AHT10 + BME280 -> Stuck. Зависает в случайные моменты времени от 30 секунд (~5 циклов запросов данных) до 10 минут.
Всё питается от 3.6V.
И у меня такое ощущение, что AHT10 в какой-то момент считает, что обращаются к нему. И имеются некоторые подозрения на корректность работы схемы сдвига уровня на его плате:

Убрал с платы стабилизатор и обошёл парой перемычек "схему сдвига уровней". Наблюдаем-с...
Обошёл схему сдвига уровней на AHT10. Не помогло.
Поменял адрес оного с 0x38 на 0x39. Не помогло.
Уменьшил агрессивность таймингов шины I2C:
I2C2->TIMINGR = 0x40541010; (SDA_DELAY)
Теперь SDA меняется на четыре такта позже, чем SCK, а не на один, как работало с любыми другими чипами, к которым у меня был доступ. Вроди бы заработало.
Самое странное, что работает с одним датчиком на шине без сбоев!.
UPD 2:
Не помогло. Но на этот раз видно, что дело где-то на стороне одного из ведомых - это видно по фазе сигнала. STM32 делает переход уровня на SDA со сдвигом на указанное выше количество тактов (4) (хотя для наглядности выставил
Код: Выделить всё
SCK ````|____|````|____|````|____|````|____|````|____
SDA ``|__(s)___(0)__|````(1)```|___(0)__|``````````|_
У меня создаётся подозрение, что AHT10 наблюдает за линией и "находит" START там, где его нет, а за ним из байта 0x72 читает "свой" адрес и отвечает не в попад, потому как стабильно передача обрывается, когда BMP280 выдает ответ: 0x6F 0x82 0xC0 0x7E 0x72 0xC0.
:/
Теперь виню второй датчик. Снял новый дамп обмена на шине. Дополнительно подключил канал (2) непосредственно рядом с самим AHT10 ("SDA-AHT" на скниншотах). Но ничего понятнее не стало.
Момент запуска: (Прошу обратить внимание на время на шкале ~0.9с - время от момента начала захвата). Собственно, чтение области калибровочных констант (на скниншоте не очень хорошо видно, но всё читается), затем - проверка статуса AHT10. Удачная. (39-E1-08-00). До момента T+137c всё идёт корректно, посылки идут пачкой:
AHT10->Trigger()
+0.1c
AHT10->GetData() -> Status? -> Not ready
+0.1c
AHT10->GetData() -> Status? -> Not ready
+0.1c
AHT10->GetData() -> Status? -> Conversion Done
BMP280->Read (0xF7..0xFC)
Скриншот не прикладываю - тут всё похоже на вертикальные полоски и паузу в пару секунд.
И по какой-то причине когда датчик давления выдаёт 0x72 в предпоследнем байте - всё виснет.
Проверил по битам, да, там можно угадать х111001 - 0x39
Общий вид транзакции: И сами биты: И разница между фазами сигналов, когда шину ведёт STM32 и BMP280.
Первый оставляет задержку в 2.9мкс между переходом SCK 1->0 и изменением уровня SDA, второй - 0,2мкс (плюс-минус, потому что захват происходил на 10MSa/s, ибо шина изначально медленная). Вот и вопрос: И как это победить? У меня пока банальный вариант - разнести датчики на физически разные шины. Но это же костыль!
Re: BMP280, датчик давления и температуры
[uquote="AlanDrakes",url="/forum/viewtopic.php?p=4248180#p4248180"]Вот и вопрос: И как это победить?[/uquote]Для танкистов ещё раз:
Разобраться почему недотактирован ACK на осциллограмме:

Найти баг в своём коде - почему недоктактируется ACK?
Гуглить на тему "что такое I2C и как оно работает?"
В инете целая куча диаграмм. Например сравните своё с: https://developer.electricimp.com/resources/i2cerrors
Разобраться почему недотактирован ACK на осциллограмме:

Найти баг в своём коде - почему недоктактируется ACK?
Гуглить на тему "что такое I2C и как оно работает?"
В инете целая куча диаграмм. Например сравните своё с: https://developer.electricimp.com/resources/i2cerrors
- AlanDrakes
- Прорезались зубы
- Сообщения: 236
- Зарегистрирован: Пн июл 04, 2016 16:51:22
- Откуда: Россия, Омск
Re: BMP280, датчик давления и температуры
ACK дотактирован. А причину я уже описал чуть выше. Всего-то слишком агрессивная работа с шиной со стороны датчика BMP280 и слишком медленная работа с шиной у датчика AHT10. В итоге - конфликт, когда первый вроди бы ведёт шину, но отпускает её, чтобы мастер мог вернуть NACK, а второй считает, что обратились к нему и продавливает 9-й бит в ноль, таким образом мастер отвечает датчику NACK, соседний датчик на шине отвечает ACK (чёрт его знает, почему он решил, что обращение идёт к нему), и в итоге на шине ACK, но периферийный блок STM32 в гробу видал читать лишние данные (его об этом никто не просил в коде), потому шина зависает в некорректном состоянии.
Всё. Финита ля комедия. Проблема именно во взаимодействии двух датчиков, а не в коде.
Предлагаю посмотреть скриншоты в предыдущем сообщении Особенно "Scr_4" и его метку времени.
Всё. Финита ля комедия. Проблема именно во взаимодействии двух датчиков, а не в коде.
Предлагаю посмотреть скриншоты в предыдущем сообщении Особенно "Scr_4" и его метку времени.
Re: BMP280, датчик давления и температуры
В описании BMP280 есть фрагмент программы расчета с поправками. Хочу узнать- это формула или алгоритм? Если формула, то какая? Я не программист, поэтому заинтересован лишь этим вопросом, и только. Буду благодарен за понятный ответ или совет.
- Вложения
-
- Формула.jpg
- (84.54 КБ) 96 скачиваний
Re: BMP280, датчик давления и температуры
Это формула пересчета измеренных "сырых" данных температуры во вменяемое значение. Ну и алгоритм в ней "зашит", естественно. 
t_fine используется в дальнейших "формулах" пересчета давления и влажности, для температурной коррекции.
t_fine используется в дальнейших "формулах" пересчета давления и влажности, для температурной коррекции.
Re: BMP280, датчик давления и температуры
Спасибо за пояснение. Прошу прощения за кривую терминологию. А t_fine в дальнейшем используется для сглаживания, в фильтре Калмана (IIR filter)? Это, ведь, считает сам BMP?