Доброй ночи, уважаемые коты! Подскажите с такой проблемой, а то уже мозг сломал себе. Делаю на МК 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); }
Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42 Сообщений: 744 Откуда: Караганда, Казахстан
Рейтинг сообщения:0
А сделать индикацию в прерываниях, по таймеру? Программа пусть выкладывает считанные из датчика и обработанные результаты куда-то в отдельную область памяти, а в прерывании по таймеру эти данные обновляются на индикаторе.
Как вариант, залезть в программу DELAY(), разобраться, как она работает и вписать регенерацию в нее... Добавить проверку на истечение времени между циклами регенерации (и учесть эту проверку при подсчете общего времени задержки), как это время истечет, выполнить регенерацию и учесть ее время в общем времени задержки. Да, перед регенерацией проверить, не истечет ли общее время задержки за время регенерации, и, если истечет, пропустить .ту регенерацию. Ну, взморгнет чуток... Или сделеть с запасом, чтобы пропуск одного цикла регенерации не был заметен...
_________________ Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
На мой взгляд желательно переписать ShtReadData(void) так, чтобы она возвращала 2 поля: статус датчика(ready, busy, error) и результат. Когда готов - читаем значение, если занят - занимаемся какими-то иными делами, через некоторое время повторяем вызов ShtReadData. А вот если ошибка - можно начать со сброса датчика. Плюсом будет то, что никаких лишних delay не требуется.
Блин проблема в том, что когда я в одной функции даю команду считать температуру, потом задержку 350 мс и потом читаю два байта данных и один байт контрольной суммы, то данные получаю правильные. А когда я эту функцию разделяю на две. Одна дает команду на измерение температуры, а во второй делаю задержку на 350 мс и потом опрос датчика, такой же как и в первой функции. Данные уже получаю неправильные. Вот и пытаюсь понять, в чем может быть проблема.
Добавлено after 3 hours 15 minutes 6 seconds:
afz писал(а):
А сделать индикацию в прерываниях, по таймеру? Программа пусть выкладывает считанные из датчика и обработанные результаты куда-то в отдельную область памяти, а в прерывании по таймеру эти данные обновляются на индикаторе.
Индикация и так сделана в прерываниях. Проблема состоит в том, что я хочу убрать задержку в 350 мс из функции, разбив ее на две функции и вызываю по таймеру
Карма: 90
Рейтинг сообщений: 1435
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4603 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
В первом случае, Вы проверяете бит SHT_DATA и по нему выходите из цикла. Во втором случае, этого нет, а просто стоит задержка. В остальном, разницы нет между двумя вариантами.
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 не совпадает, так и не разобрался.
Спасибо, это похожее, что я искал. Правда пока перебил под свой код саму функция измерения, что-то не пошло. Попробую использовать полностью Вашу библиотеку.
Что-то не могу понять. У Вас есть переменная 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 град.Ц. Ну и походу при изменении температуры изменяется влажность
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;
Сначала попадаем в состояние 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 град.Ц. Ну и походу при изменении температуры изменяется влажность
У меня было также, не знаю почему. Код функции вычисления данных от производителя.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 30
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения