Страница 1 из 1
SHT10 и ATmega8
Добавлено: Вт апр 18, 2017 23:09:32
melandr
Доброй ночи, уважаемые коты! Подскажите с такой проблемой, а то уже мозг сломал себе. Делаю на МК ATmega8 и SHT10 датчик влажности. Нашел на просторах интернета готовый проект работы с датчиком SHT15. Но в библиотеке есть одна трабла. Запуск измерения , ожидание и само чтение данных из датчика SHT10 сделано одной функцией. А так как я использую динамическую индикацию, то задержка в 350 мс совсем не вариант. При разделении функции измерения на две функции, датчик начинает передавать ерунду. Первая - запуск преобразования, потом задержка и вторая функция - чтение данных из SHT10.
Вот исходная функция:
Спойлер
Код: Выделить всё
int ShtMeasure(unsigned char mode)
{
unsigned int temp = 0xFFFF;
unsigned char checksum;
unsigned char c;
// Signal start of communications
transstart();
// Request measurement
write_byte(mode);
// Sensor lowers the data line when measurement
// is complete. Wait up to 2 seconds for this.
for (c=0; c<20; c++)
{
if (! bit_is_set(SHT_PIN, SHT_DATA))
break;
DELAY(1000000/10);
}
// Read the measurement
if (! bit_is_set(SHT_PIN, SHT_DATA))
{
temp = read_byte();
temp = temp << 8;
temp += read_byte();
checksum = read_byte();
}
return temp;
}
а вот я разбил ее на две:
void ShtMeasure(unsigned char mode)
{
unsigned char c;
// Signal start of communications
transstart();
// Request measurement
write_byte(mode);
DELAY(350000);
}
int ShtReadData(void)
{
unsigned int temp = 0xFFFF;
unsigned char checksum;
temp = read_byte();
temp = temp << 8;
temp += read_byte();
checksum = read_byte();
return temp;
}
Заранее благодарен за помощь.
Re: SHT10 и ATmega8
Добавлено: Ср апр 19, 2017 05:05:47
afz
А сделать индикацию в прерываниях, по таймеру? Программа пусть выкладывает считанные из датчика и обработанные результаты куда-то в отдельную область памяти, а в прерывании по таймеру эти данные обновляются на индикаторе.
Как вариант, залезть в программу DELAY(), разобраться, как она работает и вписать регенерацию в нее... Добавить проверку на истечение времени между циклами регенерации (и учесть эту проверку при подсчете общего времени задержки), как это время истечет, выполнить регенерацию и учесть ее время в общем времени задержки. Да, перед регенерацией проверить, не истечет ли общее время задержки за время регенерации, и, если истечет, пропустить .ту регенерацию. Ну, взморгнет чуток... Или сделеть с запасом, чтобы пропуск одного цикла регенерации не был заметен...
Re: SHT10 и ATmega8
Добавлено: Ср апр 19, 2017 09:10:48
uk8amk
И как вы узнаете что датчик уже готов к общению?
На мой взгляд желательно переписать ShtReadData(void) так, чтобы она возвращала 2 поля: статус датчика(ready, busy, error) и результат.
Когда готов - читаем значение, если занят - занимаемся какими-то иными делами, через некоторое время повторяем вызов ShtReadData. А вот если ошибка - можно начать со сброса датчика.
Плюсом будет то, что никаких лишних delay не требуется.
Re: SHT10 и ATmega8
Добавлено: Ср апр 19, 2017 10:42:42
pyzhman
Влажность не такой параметр, который требует работы в реальном режиме времени. Считывайте данные раз в десять минут.
Re: SHT10 и ATmega8
Добавлено: Ср апр 19, 2017 21:56:42
melandr
Блин проблема в том, что когда я в одной функции даю команду считать температуру, потом задержку 350 мс и потом читаю два байта данных и один байт контрольной суммы, то данные получаю правильные. А когда я эту функцию разделяю на две. Одна дает команду на измерение температуры, а во второй делаю задержку на 350 мс и потом опрос датчика, такой же как и в первой функции. Данные уже получаю неправильные. Вот и пытаюсь понять, в чем может быть проблема.
Добавлено after 3 hours 15 minutes 6 seconds:
afz писал(а):А сделать индикацию в прерываниях, по таймеру? Программа пусть выкладывает считанные из датчика и обработанные результаты куда-то в отдельную область памяти, а в прерывании по таймеру эти данные обновляются на индикаторе.
Индикация и так сделана в прерываниях. Проблема состоит в том, что я хочу убрать задержку в 350 мс из функции, разбив ее на две функции и вызываю по таймеру
Re: SHT10 и ATmega8
Добавлено: Ср апр 19, 2017 23:29:08
Аlex
В первом случае, Вы проверяете бит SHT_DATA и по нему выходите из цикла. Во втором случае, этого нет, а просто стоит задержка.
В остальном, разницы нет между двумя вариантами.
Re: SHT10 и ATmega8
Добавлено: Чт апр 20, 2017 12:47:37
DimAlt
melandr я использовал этот датчик с динамической индикацией, в этом
проекте, есть исходник. Я там опрос разбивал по состояниям
Спойлер
Код: Выделить всё
switch(StateSHT10){
case (0):
//if (--Time1ms==0) StateSHT10=1;
StateSHT10++;
break;
case (21):
sht_sart();
error=sht_wr_byte(MEASURE_TEMP);
Time1ms=0;
StateSHT10=22;
break;
case (22):
if ( (ACTIVE(SDA))==0 ) StateSHT10=23;
if (++Time1ms==1000) error=0xFF;
break;
case (23):
TempSht.Byte[1]=sht_rx_byte(1);
TempSht.Byte[0]=sht_rx_byte(0);//stop connect (no ask)
StateSHT10=24;
break;
case (24):
sht_sart();
error=sht_wr_byte(MEASURE_HUMI);
Time1ms=0;
StateSHT10=25;
break;
и так далее..
Только вот с контрольной суммой не получилось.. В протеусе работало, в железе crc не совпадает, так и не разобрался.
Re: SHT10 и ATmega8
Добавлено: Чт апр 20, 2017 23:06:44
melandr
Спасибо, это похожее, что я искал. Правда пока перебил под свой код саму функция измерения, что-то не пошло. Попробую использовать полностью Вашу библиотеку.
Re: SHT10 и ATmega8
Добавлено: Пт апр 21, 2017 07:25:48
DimAlt
Вот в виде библиотеки из другого проекта.
Re: SHT10 и ATmega8
Добавлено: Вт май 02, 2017 16:49:03
melandr
Что-то не могу понять. У Вас есть переменная extern uint8_t StateSHT10; Вначале ее значение равно 0xFF. При заходе в switch попадаем в секцию default, обнуляем эту переменную. При следующем вызове measure_sht10() заходим в секцию case(0) увеличиваем StateSHT10 на 1. При следующем вызове measure_sht10() опять попадаем в секцию default и обнуляем значение StateSHT10. А в остальные секции switch мы не попадаем. И где-то в функции измерения температуры Вы принудительно присваиваете StateSHT10 = 21, чтобы начать измерение влажности. Непонятно, для чего это присвоение засовывать в какую-то функцию, не относящуюся к измерению влажности. И не подскажете, как правильно и когда нужно сделать присвоение StateSHT10, чтобы запустить измерение?
Для чего тогда
case (0):
//if (--Time1ms==0) StateSHT10=1;
StateSHT10++;
break;
Не подскажете. Для чего мы присваиваем StateSHT10 значение 0xFF. Если потом мы его обнуляем, и присваиваем 1, а дальше опять завтык пока не присвоим значение 21?
Прогнал в протеусе код, функция uint8_t sht_wr_byte(uint8_t Byte) возвращает 1. Вкладываю архив с проектом AVRStudio и проектом Протеуса, может подскажете почему не работает. DimAlt рабочий проект дал и библиотеку. Еще вопрос, почему функция void sht10_init(void) за комментирована? Инициализация не требуется?
ЗЫ: Вот я СТепан, в хидере не изменил порт и пины, на котором сидит датчик

ЗЫ2Ж Тут по ходу пьесы возникло пару вопросов. Первый, то что вычисление температуры и влажности происходят с плавающей. По температуре погрешность меньше запятой, насколько это критично для загрузки микроконтроллера. И второй вопрос, в протеусе выставляю влажность 40% , а получаю от датчика преобразованную влажность 41,45% По температуре погрешность меньше устанавливаю на датчике10.0 град.Ц , а с датчика получаю 10,32 град.Ц. Ну и походу при изменении температуры изменяется влажность
Re: SHT10 и ATmega8
Добавлено: Пт май 05, 2017 07:42:56
DimAlt
Спойлер
Код: Выделить всё
enum ST_SHT10 {SHT10_START_DELAY,
SHT10_MEAS_T, SHT10_WAIT_T, SHT10_READ_T,
SHT10_MEAS_H, SHT10_WAIT_H, SHT10_READ_H,
SHT10_DATA_1, SHT10_DATA_2, SHT10_END_CONV};
#define SHT10_START_CONV SHT10_MEAS_T
Код: Выделить всё
//--------------------------------------------------------------
void measure_sht10(void){
static uint16_t Time1ms;
uint8_t error=0;
switch(StateSHT10){
case (SHT10_START_DELAY):
if (++Time1ms==TIME_WAIT_ERROR_SHT10*2)
StateSHT10=SHT10_MEAS_T;//StateSHT10=SHT10_CMD_STATUS_R;//
DRIVER(SCK,OUT);//инициализация на выход, что бы все ножки настраивались внутри модуля без выноса в основную прогу
break;
case (SHT10_MEAS_T):
error=sht_sart();
error=sht_wr_byte(MEASURE_TEMP);
Time1ms=0;
StateSHT10=SHT10_WAIT_T;
break;
case (SHT10_WAIT_T):
if ( (ACTIVE(SDA))==0 ) StateSHT10=SHT10_READ_T;
if (++Time1ms==TIME_WAIT_ERROR_SHT10) error=0xFF;
break;
case (SHT10_READ_T):
TempSht.Byte[1]=sht_rx_byte(1);//msb
TempSht.Byte[0]=sht_rx_byte(0);//lsb 0 stop connect (no ask)
StateSHT10=SHT10_MEAS_H;
break;
case (SHT10_MEAS_H):
error=sht_sart();
error=sht_wr_byte(MEASURE_HUMI);
Time1ms=0;
StateSHT10=SHT10_WAIT_H;
break;
case (SHT10_WAIT_H):
if ( (ACTIVE(SDA))==0 ) StateSHT10=SHT10_READ_H;
if (++Time1ms==TIME_WAIT_ERROR_SHT10) error=0xFF;
break;
case (SHT10_READ_H):
HumiSht.Byte[1]=sht_rx_byte(1);//msb
HumiSht.Byte[0]=sht_rx_byte(0);//lsb 0 stop connect (no ask)
StateSHT10=SHT10_DATA_1;
break;
case (SHT10_DATA_1):
TempSht.f=(float)TempSht.i;
HumiSht.f=(float)HumiSht.i;
StateSHT10=SHT10_DATA_2;
break;
case (SHT10_DATA_2):
calc_sth11(&HumiSht.f,&TempSht.f);
XhtHumi=(int)(HumiSht.f);
XhtTemper=(int)((TempSht.f)*10);
if ( (XhtHumi!=0) || (XhtTemper!=0) )
Flag_Xht=XHT_OK;
else
error=1;
StateSHT10=SHT10_END_CONV;
break;
case (SHT10_END_CONV):
//StateSHT10=1;
//return 1;
break;
default :
s_softreset();
StateSHT10=SHT10_START_DELAY;
Time1ms=0;
break;
}
if (error){
StateSHT10=0xFF;
Flag_Xht=XHT_ERROR;
//return 0xFF;
}
//return 0;
}
Сначала попадаем в состояние SHT10_START_DELAY, делал для того чтобы после ошибки датчика не сразу его опрашивать, а через какое то время. У меня функция measure_sht10 вызывается раз в 1мС. Старт после ошибки через время (++Time1ms==TIME_WAIT_ERROR_SHT10*2).
Как работает у меня.
В коде есть это:
#define SHT10_START_CONV SHT10_MEAS_T
Старт преобразования выполняется в основном коде программы
StateSHT10=SHT10_START_CONV
Затем можно ждать окончание преобразования StateSHT10==SHT10_END_CONV (можно не дождаться, нужно мониторить XHT_ERROR).
У меня, в рабочем проекте, это состояние опрашивается через 1сек после StateSHT10=SHT10_START_CONV, поэтому я не смотрю это условие, а проверяю if (Flag_Xht==XHT_OK){действия}
Затем запускаем по новому. Что бы крутилось автоматом, то можно сделать так:
Код: Выделить всё
case (SHT10_END_CONV):
StateSHT10=SHT10_START_CONV;
break;
Непонятно, для чего это присвоение засовывать в какую-то функцию, не относящуюся к измерению влажности.
У меня, для синхронизации задач в главном цикле программы. Старт измерения влажности во время простоя при опросе других датчиков.
Тут по ходу пьесы возникло пару вопросов. Первый, то что вычисление температуры и влажности происходят с плавающей. По температуре погрешность меньше запятой, насколько это критично для загрузки микроконтроллера.
Вычисления вынесены в отдельное состояние, занимают относительно мало времени.
И второй вопрос, в протеусе выставляю влажность 40% , а получаю от датчика преобразованную влажность 41,45% По температуре погрешность меньше устанавливаю на датчике10.0 град.Ц , а с датчика получаю 10,32 град.Ц. Ну и походу при изменении температуры изменяется влажность
У меня было также, не знаю почему. Код функции вычисления данных от производителя.
Re: SHT10 и ATmega8
Добавлено: Вт май 23, 2017 10:56:52
melandr
DimAlt спасибо. Запустил датчик влажности, все нормально работает.