реклама на сайте
подробности

 
 
> Проблема с измерением температуры TMP05, Выдает -400 градусов!!!
alux
сообщение Jun 17 2010, 07:15
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Температурный датчик от AD с частотным выходом. Принцип работы прост как двери...
Но почему выдает такой результат, не пойму никак... Пробовал режим работы One Shot Mode и Continuously Converting Mode.

Выкладываю исходники. Может со стороны видно ошибку.
Код
///////////////////////////////////
// tmp05.c
//------------------------------------
unsigned long T_high, T_low;  
double Temperature;
unsigned Timer1OvfCount;

#pragma vector=INT0_vect
__interrupt void INT0_ISR()
{  
    if(!Flags.IsMeasure)
    {
        T_high = TCNT1 + Timer1OvfCount * 65536UL;
        Timer1OvfCount = TCNT1 = 0;   // Reset count
        RISING_EDGE;
        Flags.IsMeasure = true;
    }
    else
    {
        T_low = TCNT1 + Timer1OvfCount * 65536UL;
        Timer1Stop();
        Flags.IsMeasure = false;
        DISABLE_INT0;
        FALLING_EDGE;
    }
}


#pragma vector=TIMER1_OVF_vect
__interrupt void TC1_OVF_ISR()
{
    Timer1OvfCount++;         // Keep a record of timer1 overflows
}


//------------------------------------------------------------------------------
void TMP05_Init()
{
    SETBIT(TMP05_DDR, TMP05_FUNC);  // One Shot Mode (FUNC = 0)
    CLRBIT(TMP05_PORT, TMP05_FUNC);

    FALLING_EDGE;
    SETBIT(TIMSK1, TOIE1);          // Enable timer1 interrupts
}


//------------------------------------------------------------------------------
void TMP05_Measure()
{
    DISABLE_INT0;
    
    // Toggle PA1 (OUT) to give start pulse
    SETBIT(TMP05_DDR, TMP05_OUT);   // Pull PA1 output (OUT = 0)
    CLRBIT(TMP05_DDR, TMP05_OUT);   // Pull PA1 high-Z (OUT -> Z)

    // Start Timer1 to count the high period
    Timer1OvfCount = TCNT1 = 0;   // Reset count
    Timer1Start();

    ENABLE_INT0;     // Pin Change Interrupt0 edge triggered
    
    while(IsTimer1Runing());

    Temperature = 421 - (751 * ((double)T_high / T_low));  
}


//////////////////////
// tmp05.h
//------------------
#define TMP05_DDR     DDRA
#define TMP05_PORT    PORTA
#define TMP05_PIN     PINA

#define TMP05_FUNC    PA0
#define TMP05_OUT     PA1
#define TMP05_START   PA2  

#define ENABLE_INT0 {EIFR = (1 << INTF0); EIMSK = (1 << INT0);} // Clear interrupt status flag, Enable INT0
#define DISABLE_INT0 EIMSK = 0 //&= ~(1 << INT0)          // Disable pin change interrupt INT0

#define FALLING_EDGE    EICRA = (1 << ISC01)
#define RISING_EDGE     EICRA = (1 << ISC01) | (1 << ISC00)

__monitor inline void Timer1Start()
{  
    SETBIT(TIFR1, TOV1);
    TCCR1B = (1 << CS10);  // Normal mode, No prescaler
}

__monitor inline void Timer1Stop()
{
    TCCR1B = 0;
}  

__monitor inline bool IsTimer1Runing()
{
    return TCCR1B != 0;
}  

#define BIT(n)        (1 << (n))
#define SETBIT(p, n)  (p |= BIT(n))
#define CLRBIT(p, n)  (p &= ~BIT(n))
#define TSTBIT(p, n)  (p & BIT(n))



//////////////
// main.c
//------------------------
//==============================================================================
int main()
{  
    TMP05_Init();  
  
    __enable_interrupt();

    for(;;)
    {    
        TMP05_Measure();
        
        LCD_Redraw();  
        delay_ms(500);
    }
}

Управляющий контроллер - ATmega324P. Кварц 20 МГц.
В функции LCD_Redraw() вывожу на ЖКИ значения T_high, T_low, Temperature.
Судя по даташиту TMP05 T_high должно быть меньше T_low и быть неизменным по температуре... В общем, что не так, ребята?!!
Прикрепленные файлы
Прикрепленный файл  TMP05_06.pdf ( 566.65 килобайт ) Кол-во скачиваний: 28
 
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
alux
сообщение Jun 18 2010, 16:00
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



В общем, сделал в режиме непрерывного измерения:
Код
unsigned long T_high, T_low;  
double Temperature;
volatile unsigned Timer1OvfCount;
unsigned long Accum[2];
int Offset;

__eeprom __no_init int ee_Offset;  // Значение смещения (EEPROM)


//==============================================================================
//  INT0 External interrupt handler ISR: Вызывается при каждом перепаде TMP05_OUT
//------------------------------------------------------------------------------
#pragma vector=INT0_vect
__interrupt void INT0_ISR()
{  
    unsigned Tick;

    if(EICRA == 2) // FALLING_EDGE  
    {
        Tick = TCNT1;
        T_high = Tick + ((unsigned long)Timer1OvfCount << 16);
        RISING_EDGE;
    }
    else if(EICRA == 3)   // RISING_EDGE
    {
        Tick = TCNT1;
        T_low = Tick + ((unsigned long)Timer1OvfCount << 16) - T_high;
        Timer1OvfCount = TCNT1 = 0;   // Reset count
        Flags.IsMeasure = true;
        FALLING_EDGE;
    }
}


//==============================================================================
//  Timer/Counter1 Overflow ISR: Вызывается с интервалом 3.27675 мс
//  Инкремент счетчика переполненй
//------------------------------------------------------------------------------
#pragma vector=TIMER1_OVF_vect
__interrupt void TC1_OVF_ISR()
{
    Timer1OvfCount++;         // Keep a record of timer1 overflows
}


//------------------------------------------------------------------------------
void TMP05_Init()
{
    Offset = ee_Offset;
    
    // Initialization TMP05
    CLRBIT(TMP05_DDR, TMP05_FUNC);  // One Shot Mode (FUNC = 0)
    CLRBIT(TMP05_PORT, TMP05_FUNC); // Continuouse Converting Mode (FUNC => Hi-Z)
    
    FALLING_EDGE;
    ENABLE_INT0;
    
    Timer1Start();
    SETBIT(TIMSK1, TOIE1);          // Enable timer1 interrupts
}


//------------------------------------------------------------------------------
void TMP05_Measure()
{
    FALLING_EDGE;
    ENABLE_INT0;
    
    while(!Flags.IsMeasure);    // First cycle is dummy
    
    Flags.IsMeasure = false;

    for(unsigned char i = 0; i < 8; i++)
    {
        while(!Flags.IsMeasure);
        
        Accum[HIGH] += T_high;
        Accum[LOW] += T_low;
        
        Flags.IsMeasure = false;
    }
    
    Temperature = 421 - (751 * ((double)(Accum[HIGH] >> 3) / (Accum[LOW] >> 3))) + Offset;
    Accum[HIGH] = Accum[LOW] = 0;

    DISABLE_INT0;
}

Все теперь работает. Просто я заработался smile.gif...
Но все же вопросы к AD остались.
Первое. Не понятно, почему состояние вывода CONV_IN не влияет на длительности T_high, T_low,- всегда идет номинальная Convertion Rate (25 C гр) 40/76 ms. И когда вывод FUNC = Low, и когда FUNC = High. Значения T_high, T_low для отладки вывожу на ЖКИ, UART. Это же подтверждает и осциллограф.
После установки вывода FUNC = Low или FUNC = High питание датчика пересбрасываю. Для надежности после обесточивания датчика закорачиваю выводы питания датчика отверткой.

Второе. В режиме One Shot Mode всегда идет меандр, а не одиночный цикл, как я предполагал. Судя по даташиту, после стартового импульса (OUT = Low длительностью >20ns, затем OUT = Hi-Z) датчик должен выдать один цикл T_high, T_low и затем вывод остается в OUT = High, пока не будет новый стартовый импульс.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 05:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01374 секунд с 7
ELECTRONIX ©2004-2016