Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Чт ноя 29, 2018 09:01:33
А для эксперимента пока нет возможности вынести датчик на улицу.
А что морозильника нет? Или просто куска льда в пакете чтобы приложить к датчику? )
Чт ноя 29, 2018 09:37:05
Получается, что ни кто не пробовал датчик BME280 при отрицательных температурах? Печалька
Чт ноя 29, 2018 09:43:03
А что морозильника нет? Или просто куска льда в пакете чтобы приложить к датчику? )
Морозильника нет. Я дома электроникой не занимаюсь, у меня мастерская отдельная для этого, либо на работе, к тому же датчик уже стоит в устройстве и закрыт в корпусе.
Пт ноя 30, 2018 11:27:22
Ну вроде победил проблему
Поменял формат переменной BME280_S32_t t_fine с 32 на 64 и все поехало. Получается на положительные значения int32 хватало, а при отрицательных уходил в нирвану. В общем прихлебывая валерьянку, курим даташит.
Сб дек 15, 2018 22:32:36
Не очень понятно. t_fine вроде бы используется в конце вычислений:
t_fine = var1 + var2;
T = (t_fine * 5 +128) >> 8;
return T;
var1, var2 и T имеют тип BME_280_S32_t и они не переполняются, так как Вы их не меняли.
Неужели var1 и var2 близки к максимуму и их сумма переполняется? Или может быть засада в том, что переполнение происходит во время умножения на 5 и возможно достаточно написать по-другому последнее выражение:
T = (int32_t)((((int64_t)t_fine) * 5) >> 8 ) ;
Ну или что-то в этом роде... Впрочем, похоже что это тоже самое, что сделали Вы, только другим способом. Жаль, что я сейчас не могу вытащить датчик на мороз, надо бы погонять в отладчике пошагово и понаблюдать за вычислениями.
Вс янв 20, 2019 16:21:01
Самое интересное, что с ошибкой отрицательных температур библиотеки bosh судя по поиску в инете мало кто столкнулся, люди похоже в основном используют в помещениях. Я блин аж второй датчик на Али купил и упёрся в те же грабли. Как уходит Т в минус, то на входе 400 и выше градусов.
passer_by не могли бы вы выложить свой кусок кода, где приведение к 64 битам делаете.
Чт янв 31, 2019 22:02:49
Не очень понятно. t_fine вроде бы используется в конце вычислений:
достаточно написать по-другому последнее выражение:
T = (int32_t)((((int64_t)t_fine) * 5) >> 8 ) ;
Ну или что-то в этом роде... Впрочем, похоже что это тоже самое, что сделали Вы, только другим способом. Жаль, что я сейчас не могу вытащить датчик на мороз, надо бы погонять в отладчике пошагово и понаблюдать за вычислениями.
Попробовал. Не взлетело.. Всё также при минусах температура за 400 выходит.
Где-то на гитхабе попадалась библиотека для этого датчика полностью на 64 бита заточенная
Пн фев 04, 2019 19:39:23
Наконец то я нашел время и проверил работу при отрицательных температурах. У меня все нормально работает. Проблем не было.
Вот прилагаю вырезку из своего кода. В функции PreesAndTemp я просто проверяю температуру больше она или меньше ноля и убираю или добавляю соответственно знак минуса и пихаю все это на дисплей.
Расчет температуры и давления взят из datasheet, данные библиотеки не изменялись, они оригинальные.
Вт фев 05, 2019 14:57:35
passer_by не могли бы вы выложить свой кусок кода, где приведение к 64 битам делаете.
Вот код:
- Код:
int64_t temper_int; //глобальная переменная
...........................
.............................
float BME280_ReadTemperature(void)
{
float temper_float = 0.0f;
uint32_t temper_raw;
int32_t val1, val2;
BME280_ReadReg_BE_U24(BME280_REGISTER_TEMPDATA,&temper_raw);
temper_raw >>= 4;
val1 = ((((temper_raw>>3) - ((int32_t)CalibData.dig_T1 <<1))) *
((int32_t)CalibData.dig_T2)) >> 11;
val2 = (((((temper_raw>>4) - ((int32_t)CalibData.dig_T1)) *
((temper_raw>>4) - ((int32_t)CalibData.dig_T1))) >> 12) *
((int32_t)CalibData.dig_T3)) >> 14;
temper_int = val1 + val2;
temper_int = ((temper_int * 5 + 128) >> 8);
temper_float = temper_int/100;
if (temper_float >100) // если значение температуры перевалило в отрицательные значения
{
temper_float = 409.6-temper_float;
temper_float = -temper_float;
}
return temper_float;
}
Обратите внимание. Переменная
int64_t temper_int это
BME280_S32_t t_fine по даташиту, используется и в расчете давления и влажности.
to
DESIERРаз работает код как у DS18B20 это говорит о том что формат значения температуры на выходе у датчиков одинаков.
К стате, как я понял Ваш код, Вы делаете ровно то же самое, только вместо двух строчек кода довольно громоздкая структура.
Пт фев 08, 2019 20:20:27
- Код:
int64_t temper_int; //глобальная переменная
...........................
.............................
float BME280_ReadTemperature(void)
{
float temper_float = 0.0f;
uint32_t temper_raw;
int32_t val1, val2;
BME280_ReadReg_BE_U24(BME280_REGISTER_TEMPDATA,&temper_raw);
temper_raw >>= 4;
val1 = ((((temper_raw>>3) - ((int32_t)CalibData.dig_T1 <<1))) *
((int32_t)CalibData.dig_T2)) >> 11;
val2 = (((((temper_raw>>4) - ((int32_t)CalibData.dig_T1)) *
((temper_raw>>4) - ((int32_t)CalibData.dig_T1))) >> 12) *
((int32_t)CalibData.dig_T3)) >> 14;
temper_int = val1 + val2;
temper_int = ((temper_int * 5 + 128) >> 8);
temper_float = temper_int/100;
if (temper_float >100) // если значение температуры перевалило в отрицательные значения
{
temper_float = 409.6-temper_float;
temper_float = -temper_float;
}
return temper_float;
}
to
DESIERРаз работает код как у DS18B20 это говорит о том что формат значения температуры на выходе у датчиков одинаков.
К стате, как я понял Ваш код, Вы делаете ровно то же самое, только вместо двух строчек кода довольно громоздкая структура.
Да у меня абсолютно тоже самое. В datasheet на датчик есть 2 варианта кода, код для расчетов с применением переменных с плавающей запятой и вариант для расчетов с целочисленными переменными.
Для 8-bit микроконтроллера расчеты с плавающей запятой занимают больше процессорного времени. Поэтому ваш вариант мне не подходит так как у меня простой 8-bit микроконтроллер. А вот если бы я использовал какой нибудь ARM, конечно же я использовал бы вариант как у вас.
Вот мой код для расчета температуры (из datasheet), я не вижу тут огромной структуры, наоборот, у меня даже меньше получается:
- Код:
int32_t bmp280_compensate_T(int32_t adc_T)
{
int32_t var1;
int32_t var2;
int32_t temperature = 0;
var1 = ((((adc_T >> 3) - ((int32_t) dig_T1 << 1))) * ((int32_t) dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((int32_t) dig_T1)) * ((adc_T >> 4) - ((int32_t) dig_T1))) >> 12) * ((int32_t) dig_T3)) >> 14;
t_fine = var1 + var2;
temperature = (t_fine * 5 + 128) >> 8;
return temperature;
}
Ср мар 06, 2019 12:38:55
Здоровья читателю.
Столкнулся с такой же проблемой с выводом отрицательных или около-нулевых температур. Вот лог:
- Код:
temperature = 1.32 C
raw_temperature = 0x0006F840 := 456768
temperature = 1.27 C
raw_temperature = 0x0006F7A0 := 456608
temperature = 1.19 C
raw_temperature = 0x0006F6A0 := 456352
temperature = 1.02 C
raw_temperature = 0x0006F490 := 455824
temperature = 86 C
raw_temperature = 0x0006F280 := 455296
temperature = 85 C
raw_temperature = 0x0006F260 := 455264
temperature = 91 C
raw_temperature = 0x0006F320 := 455456
temperature = 88 C
raw_temperature = 0x0006F2D0 := 455376
temperature = 63 C
raw_temperature = 0x0006EFA0 := 454560
temperature = 58 C
raw_temperature = 0x0006EF20 := 454432
temperature = 65 C
raw_temperature = 0x0006EFE0 := 454624
temperature = 68 C
raw_temperature = 0x0006F040 := 454720
temperature = 3.64 C
raw_temperature = 0x00071500 := 464128
Датчик ВМР280 под снегом в пакете.
Код с даташита, проверял 100500 раз, сверял с выкладками в этой теме, пробовал шаман-бубен здешний с удваиванием типа t_fine - ничего не помогает...
Вот по "raw_temperature" в логе (это 20-битный компот значений соответствующих регистров ВМР280), не понятно, когда температура становится отрицательной/нулевой?
Братцы, если кому удалось цивилизовано решить эту проблему, поделитесь волшебством пожалуйста.
Ср мар 06, 2019 12:45:33
Братцы, если кому удалось цивилизовано решить эту проблему, поделитесь волшебством пожалуйста.
Покажите ваш код, тогда подумаем. А так можно гадать долго. Я думаю что проблема в типах данных, возможно вы где то вместо int используете unsigned int в коде расчета.
Ср мар 06, 2019 13:19:30
DESIER, возможно "глаз замылился" и я просто не вижу ошибку.
Ср мар 06, 2019 14:17:32
DESIER, возможно "глаз замылился" и я просто не вижу ошибку.
А вот что вот это за функция? num2dec(_bmp280_temp, 2);
Она выводит переменную _bmp280_temp в знаковом типе?
Что то мне кажется дело в ней. Если осуществлять вывод информации в беззнаковом типе, будет вот такая байда.
Ср мар 06, 2019 14:44:27
DESIER писал(а):Что то мне кажется дело в ней.
Вот - да. Я на нее тоже грешу. Она самописная, а так как я не умею толком преобразовывать, вполне вероятна проблема в ней.
- Код:
void num2dec(long arg, int fractionDigits){
unsigned long dec = 1;
int i = 0, index = 0,max = 0;
char arr[16];
memset(arr, 0, 16);
while(dec < arg){
dec *= 10;
max ++;
}
if(max) dec /= 10;
if(fractionDigits && max > fractionDigits) max -= fractionDigits;
while(dec){
i = 0;
if(index == max && fractionDigits) arr[index ++ ] = 0x2E; // Symbol - "."
while(dec <= arg){
arg -= dec;
i++;
}
arr[index++] = i + 48;
dec /= 10;
}
uart_puts(arr);
}
Ср мар 06, 2019 14:57:57
MOHCTEP, я так понял это ардуино?! А в нем разве нельзя просто взять и отправить число в uart без вот таких танцев с бубнами?
Я с ардуино не работал и отладку я делаю через JTAG. Не могу понять для чего эта функция? Опишите в кратце что она делает.
Ср мар 06, 2019 15:27:06
DESIER Не-не, чур меня.
Ни разу ардуино не доводилось видеть. Это Мега 8 + ВМР280 + USB-UART для отладки, а и + макетка.
DESIER писал(а):Не могу понять для чего эта функция? Опишите в кратце что она делает.
Задумывалась для преобразования любого числа (до 32 бит) в читабельный вид, с фиксированной точкой и отправки его в UART. Если есть какие-то стандартные вещи в си, для этого, не сильно отжирающие ресурсы и память, подскажите пожалуйста.
Ср мар 06, 2019 15:51:07
Ну вот например если отправлять побайтно.
допустим переменная t несет значение температуры в виде -567 на пример, это будет температура -5,67 гр.С
и какая либо функция uart(char) принимающая в качестве аргумента байт, записывая его на шину.
- Код:
uint16_t t = temperatureBMP280;
if (t < 0) { t = -t; uart('-'); }
if (t >= 1000) uart(((t/1000)%10)+48);
uart(((t/100)%10)+48);
uart('.');
uart(((t/10)%10)+48);
uart((t%10)+48);
uart('°');
uart('C');
Может я что то и нагородил, но я вывожу на LCD дисплей по шине I2C именно таким методом. У меня вместо uart другая рисующая символ на дисплее функция выводит изображение в соответствии с кодировкой ASCII.
Или вот так:
- Код:
void DesSend(int32_t n)
{
uint16_t temp = 0;
if (n < 0) { temp = -n; UDR = 45; }
else temp = n;
if (t >= 1000) UDR = ((temp/1000)%10)+48;
UDR = ((temp/100)%10)+48;
UDR = 46;
UDR = ((temp/10)%10)+48;
UDR = (temp%10)+48;
UDR = 176;
ADR = 67;
}
Ср мар 06, 2019 16:45:08
Я чуть откомментировал
По сути, вся верхняя возня придумана, чтоб не выводить левые нули при любой десятичной разрядности аргумента. Иначе говоря у вас код выведет температуру нормально, а давление в паскалях уже - проблема. По вашему коду есть вопросы.
1). "if (t < 0) { t = -t; uart('-'); }". Как это условие у вас срабатывает, если t - без знаковая(uint16_t)?
2) Покажите, ради хвоста, паяльника и прочих мимоз, как у вас выглядит эта самая "-567" в 16-ричном виде! Очень прошу. И главное куда этот долбаный минус засунулся в 32-битном результате даташитовских манипуляций? У вас все просто "if (n < 0)" = кайф!
У меня, почему-то, эта самая "n" всегда больше нуля.
Ср мар 06, 2019 17:23:04
Не проще ли было воспользоваться если не sprintf(), то хотя бы itoa() или utoa()?
А если уж очень захотелось конвертировать из двоичку в десятичку самостоятельно, то лучше воспользоваться более быстрым алгоритмом, без деления. Например, тем же Double dabble.
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.