d18b20 и мерцание

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
pierro
Открыл глаза
Сообщения: 66
Зарегистрирован: Вс фев 14, 2010 14:48:19
Откуда: Львов

d18b20 и мерцание

Сообщение pierro »

Доброго времени суток все "котам"

Прошу помочи у старожилом и профессионалов. Это моя 3-я разработка на микроконтроллере. Делаю термостат на attiny2313 с возможностью регулирования температур (также будет использоваться для инкубатора). Все сделал, программу написал, все работает. Только одна проблема осталась. Мерцание индикатора при считывание температуры с d18b20. Вроде проблема старая, как свет, много форумом перечитал, все перепробовал, но проблема осталась.
Били решения но
1. они били на atmega8
2. либо использовалса кварц

У меня
1. attiny2313
2. кварца нету
3. Переписана функция считывания температура, так как та что шла с CodeVision уж больно много места занимала (не хватало памяти для остальной программами)
4. Пробовал не отключать прерывания в функции my_ds18b20_temperature - но температура недосчитываться (как би и не должна)

Существующий ли решения этой проблемы (жк индикатор не подходит)?

Код программами
term.zip
Программа
(2.72 КБ) 159 скачиваний
Вот схема
Изображение

Это фото уже почти готового устройства
Изображение
Изображение

Спасибо всем!
Реклама
Мастер Ломастер
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город
Контактная информация:

Re: d18b20 и мерцание

Сообщение Мастер Ломастер »

перечитайте форум еще раз - решение всегда одно, независимо от типа МК, кварца, схемы и т.п.: нельзя запрещать прерывания на время всей работы с датчиком температуры, достаточно запрещать их только на время чтения/записи одно бита - это гарантирует исключение мерцания при динамической индикации (при условии, что сама динамическая индикация сделана без ошибок).
битва с дураками проиграна, победители торжествуют. слава победителям!
Реклама
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: d18b20 и мерцание

Сообщение ploop »

Заводится счетчик на интервал 1-2 секунды. В прерывании его сначала считываем температуру с датчика, потом даём команду на преобразование. Это выполняется довольно быстро, мерцания не будет заметно, а при следующем входе в прерывание считается готовая температура. Слишком часто опрос тоже делать не стоит.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: d18b20 и мерцание

Сообщение Аlex »

ploop, не советуйте ерунды. Работать с датчиком в прерывании глупо. Так-же как и глупо вешать обработчик любыми другими способами. Вы ещё посоветуйте индикацию вынести в основной цикл с использованием всяких там delay_ms.
pierro, придерживайтесь совету Ломастера. Он дал совет по единственно правильному решению подобной проблемы. Если уж не терпится ждать весь тайм слот с запрещёнными прерываниями, можно их запретить только на основную часть тайм-слота (в самом начале), но это при условии того, что прерывание, которое может вызваться во время остальной части, не затянется на большое время.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: d18b20 и мерцание

Сообщение ploop »

Работать с датчиком в прерывании глупо.
Обоснуйте?
Зависит от задачи. Во время обмена данными всё равно прерывания запрещены, а я предложил делать внутри перрывания только обмен (не ожидание). При том не чаще раза в секунду.

Второй вариант - флаговый автомат, когда в прерывании выставляем флаг, обмен делаем в основном цикле. Но опять же, как говорил, на время обмена прерывания запрещены, так что ничего не выигрываем и не теряем.
Разве что обсчет CRC обычным (не табличным) методом лучше не делать в прерывании.
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: d18b20 и мерцание

Сообщение Аlex »

Обоснуйте?
Что кнокретно ? Что вешать прерывание - глупо ? Дак тут и обоснований не нужно. На то он и обработчик прерываний, что-бы обработать быстренько событие и бегом оттуда, сломя голову...
Зависит от задачи.
Естественно. И в конкретной задаче, как раз, вешать его глупо. Т.к. , пологаю, дин. индикация происходит в прерывании по таймеру. По этому и нельзя запрещать прерывания на длительное время. И премещать работу с датчиком в ОП, обосновывая это тем, что прерывания и так запрещены - не выход. Это тоже-самое, только "вид сбоку"... Необходимо давать возможность обработаться событию вовремя, по этому единственный выход - запрет прерываний на то время, которое критично к изменению. Это время и есть 1 тайм-слот. Между тайм-слотами время неограничено.
Реклама
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: d18b20 и мерцание

Сообщение ploop »

Это время и есть 1 тайм-слот
Всё верно.
Длительность полного обмена (8 байт + 1 CRC) всегда будет меньше 10мс, если это время критично для дин. индикации - тогда да, я не прав.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: d18b20 и мерцание

Сообщение Аlex »

10 мс это наверное многовато будет. Предположим 3 индикатора, 30 мс полупериод на один индикатор. Получается период 60 мс = 16.6 Гц на индикатор. :roll:
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: d18b20 и мерцание

Сообщение Леонид Иванович »

Аlex писал(а):Работать с датчиком в прерывании глупо.
Как раз "interrupt-driven 1-wire master" - самая правильная реализация. Все задержки отсчитываются таймером, все действия с шиной производятся в прерываниях. Тратится минимальное количество вычислительных ресурсов. Но такая реализация сложнее. Ну и прерывание должно быть высокоприоритетным, ведь формируются малые интервалы времени.

Но даже реализация без прерываний тратит не так много ресурсов. Вот такой код позволяет даже вынести динамическую индикацию из прерывания и вставить в основной цикл. Мерцания незаметны. Ну, почти :)

Код: Выделить всё

//----------------------------------------------------------------------------

//DSS-90
//Модуль обслуживания термометра DS18B20

//Цифровой датчик температуры DS18B20 подключен по 1-проводному
//интерфейсу, который реализован программно.
//Для подключения датчика используется порт OWP.
//Порт должен быть  настроен на ввод,
//внутренний подтягивающий резистор должен быть отключен,
//используется внешний подтягивающий резистор 4.7 кОм.
//Во время измерения обеспечивается сильноточная
//подтяжка линии данных (порт переключается на вывод ВЫСОКОГО уровня),
//поэтому возможно использование термометра с паразитным питанием.
//Должны быть определены следующие макросы:
//#define OWP (1 << Pxn)
//#define Port_OWP_OUT (DDRx |= OWP)
//#define Port_OWP_IN (DDRx &= ~OWP)
//#define Pin_OWP   (PINx & OWP)
//Датчик DS18B20 должен быть запрограммирован в 12-разрядный режим
//(биты R0, R1 в регистре конфигурации равны единице,
//это заводская установка).

//Дискретность измерения температуры составляет 0.1°C.
//Из датчика считываются только 2 байта, CRC не проверяется.

//Для инициализации модуля один раз в начале программы должна
//вызываться функция DS18B20_Init(). Функция DS18B20_Exe() должна
//вызываться в основном цикле, она осуществляет запуск преобразования,
//формирует в фоновом режиме временную задержку и производит считывание
//температуры во внутреннюю переменную Temp.

//Поскольку обмен по однопроводной шине довольно медленный (чтение или
//запись одного байта занимает порядка 0.5 мс), целиком выполнять
//чтение температуры и запуск преобразования за один вызов DS18B20_Exe()
//нельзя. Это может нарушить выполнение других задач. Поэтому процесс
//обмена с термометром разбит на элементарные операции, каждая из
//которых включает в себя обмен не более чем одним байтом.

//Значение температуры в любой момент может быть считано с помощью функции
//DS18B20_GetT(). Значение представлено в виде 16-разрядного целого числа
//со знаком и представляет собой температуру в десятых долях градуса.
//До того, как закончится первое преобразование температуры, возвращается
//значение T_NORDY. В случае отсутствия ответа термометра возвращается
//код ошибки T_ERROR.

//----------------------------------------------------------------------------

#include "Main.h"
#include "DS18B20.h"

//------------------------------ Константы: ----------------------------------

#define TCONV 800      //время преобразования температуры, мс

//----------------------------- Переменные: ----------------------------------

static int Temp;       //текущая температура
static char TState;    //состояние процесса измерения

//-------------------------- Прототипы функций: ------------------------------

bool TReset(void);     //формирование импульса сброса
char TByte(char dat);  //запись/чтение байта
bool TBit(bool b);     //запись/чтение бита

//--------------------- Инициализация термометра: ----------------------------

void DS18B20_Init(void)
{
  Temp = T_NORDY;      //результат измерения не готов
  TState = 0;          //начало процесса
}

//----------------------- Измерение температуры: -----------------------------

void DS18B20_Exe(bool t)
{
  static int TTimer = 0;              //таймер термометра
  static int T;                       //код температуры
  if(t)
  {
    if(TTimer)                        //если интервал таймера не истек,
    {
      TTimer--;                       //ожидание (и декремент таймера)
    }
    else                              //иначе выполнение шага
    {
      switch(TState)
      {
      case 0: if(TReset())            //команда RESET
                TState++;             //если выполнена успешно, следующий шаг
                  else TState = 0xFF; //если ошибка, переход на задержку
              break;
      case 1: TByte(0xCC);            //команда SKIP ROM
              TState++;               //следующий шаг
              break;               
      case 2: TByte(0x44);            //команда START CONVERSION
              TTimer = ms2sys(TCONV); //загрузка задержки преобразования
              TState++;               //следующий шаг
              break;
      case 3: if(TReset())            //команда RESET
                TState++;             //если выполнена успешно, следующий шаг
                  else TState = 0xFF; //если ошибка, переход на задержку
              break;
      case 4: TByte(0xCC);            //команда SKIP ROM
              TState++;               //следующий шаг
              break;
      case 5: TByte(0xBE);            //команда READ SCRATCHPAD
              TState++;               //следующий шаг
              break;
      case 6: T = TByte(0xFF);        //чтение TL
              TState++;               //следующий шаг
              break;
      case 7: T |= TByte(0xFF) << 8;  //чтение TH
              TState++;               //следующий шаг
              break;
      case 8: Temp = 10 * T / 16;     //вычисление температуры
              TState = 0;             //переход на первый шаг
              break;
      default: TTimer = ms2sys(TCONV); //загрузка задержки
              Temp = T_ERROR;         //код ошибки
              TState = 0;             //переход на первый шаг
      }
    }
  }
}

//--------------------- Генерация импульса сброса: ---------------------------

bool TReset(void)
{
  char si;
  Port_OWP_0;
  Port_OWP_OUT;                //OWP <- 0
  Delay_us(500);               //delay 500 uS
  si = __save_interrupt();
  __disable_interrupt();       //запрещение прерываний
  Port_OWP_IN;                 //OWP <- 1
  Delay_us(14);                //delay 14 uS
  if(Pin_OWP)                  //если OWP = 0, то ошибка
  {
    Delay_us(52);              //delay 52 uS
    if(!Pin_OWP)               //если OWP = 1, то ошибка
    {
      __restore_interrupt(si); //восстанавление прерываний
      Delay_us(250);           //delay 250 uS
      if(Pin_OWP)              //если OWP = 0, то ошибка
      {
        return(1);             //если ошибок нет, термометр присутствует
      }
    }
  }
  __restore_interrupt(si);     //восстанавление прерываний в случае ошибки
  return(0);
}

//-------------- Запись/чтение байта по однопроводной шине: ------------------

char TByte(char dat)
{
  char res;
  for(char i = 0; i < 8; i++)
  {
    res = res >> 1;
    if(TBit(dat & 1)) res |= 0x80;
     else res &= ~0x80;
    dat = dat >> 1;
  }
  return(res);
}

//--------------- Запись/чтение бита по однопроводной шине: ------------------

bool TBit(bool b)
{
  char si;
  si = __save_interrupt();
  __disable_interrupt();       //запрещение прерываний
  Port_OWP_0;
  Port_OWP_OUT;                //OWP <- 0
  Delay_us(2);                 //delay 2 uS
  if(b) Port_OWP_IN;           //bit = 1, OWP <- 1
  Delay_us(13);                //delay 13 uS
  bool owp = Pin_OWP;          //чтение порта
  Delay_us(45);                //delay 45 uS
  Port_OWP_1;                  //force pullup
  Port_OWP_OUT;
  __restore_interrupt(si);     //восстанавление прерываний
  Delay_us(2);                 //delay 2 uS
  return(owp);
}

//------------------------- Чтение температуры: ------------------------------

int DS18B20_GetT(void)
{
  return(Temp);
}

//----------------------------------------------------------------------------
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: d18b20 и мерцание

Сообщение Satyr »

Как то вы усложняете.
Вижу незапользованный UART.
Можно на нем и таймере 1-wire интерфейс практически нахаляву в смысле вычислительных ресурсов сделать и некритичный к обработке прочих прерываний.
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: d18b20 и мерцание

Сообщение ploop »

Кстати да, что-то мы про UART забыли.
Если что - вот докУмент :)
Вложения
1w.doc.zip
(277.43 КБ) 175 скачиваний
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: d18b20 и мерцание

Сообщение Леонид Иванович »

UART хорош, если только 1 порт 1-Wire нужен. А чаще датчиков несколько.
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: d18b20 и мерцание

Сообщение ploop »

Аlex писал(а):10 мс это наверное многовато будет. Предположим 3 индикатора, 30 мс полупериод на один индикатор. Получается период 60 мс = 16.6 Гц на индикатор. :roll:
Зачем? Затык на 10мс будет раз в 1-2 секунды, в остальном, пока датчики считают, всё будет крутиться как положено. И я сомневаюсь, если этот затык будет виден.
Просто данный вариант проще в реализации.
Последний раз редактировалось ploop Пн окт 24, 2011 11:41:17, всего редактировалось 1 раз.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: d18b20 и мерцание

Сообщение Аlex »

Да, кстати, с датчиком можно по усарту работать. Я пробовал, работает :))
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: d18b20 и мерцание

Сообщение ploop »

Ничегонеработает писал(а):UART хорош, если только 1 порт 1-Wire нужен. А чаще датчиков несколько.
А какая разница? Передаём адрес нужного и работаем с ним.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: d18b20 и мерцание

Сообщение Аlex »

И я сомневаюсь, если этот затык будет виден.
Очень хорошо будет виден, даже не сомневайтесь.
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: d18b20 и мерцание

Сообщение Леонид Иванович »

ploop писал(а):Зачем? Затык на 10мс будет раз в 1-2 секунды...И я сомневаюсь, если этот затык будет виден.
Хорошо виден. Раз в секунду будет подмигивать.
Аlex писал(а):Да, кстати, с датчиком можно по усарту работать. Я пробовал, работает :))
И я пробовал. На PC. Исходник на Delphi тут: http://digit-el.com/files/open/ds18x20/ds18x20.html
ploop писал(а):А какая разница? Передаём адрес нужного и работаем с ним.
Еще чего. Связываться с адресацией - это такие проблемы на свою голову. Их же как-то прописывать при инсталляции системы нужно. А датчик заменил - и всё. Другое дело, если для каждого датчика - свой порт.
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: d18b20 и мерцание

Сообщение Satyr »

Ничегонеработает писал(а):UART хорош, если только 1 порт 1-Wire нужен. А чаще датчиков несколько.
Какая разница то ?
Пакеты все одинакового формата
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: d18b20 и мерцание

Сообщение Аlex »

Другое дело, если для каждого датчика - свой порт.
А поиск ROM Вам не знаком ? :)
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: d18b20 и мерцание

Сообщение Satyr »

Аlex писал(а):Да, кстати, с датчиком можно по усарту работать. Я пробовал, работает :))
Не то что работает, а и коду кроха, и на софтовые тайминги не заложено.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»