|
Проблема с термопарой, ... или с АЦП ? |
|
|
|
Aug 5 2010, 15:23
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Делаю терморегулятор для печи. Термопару для отладки взял от китайского тестера (в фторопластовой изоляции с разъемом на конце). Индикация - четыре 7-сегментных знакоместа. Вывожу значение напряжения с первого канала, куда подключена термопара. Отрицательный вывод термопары соединен с опорным напряжением +2,5В, которое является опорным для АЦП (AD7799). Режим измерения - биполярный. Проблема в том, что при правильном подключении термопары ("-" к AIN1-, "+" к AIN1+) значение напряжения неизменное от температуры (прикладываю конец ТП к включенной настольной лампе). Если же подключить ТП наоборот к АЦП, то, значение меняется по температуре, но, естественно, в обратную сторону. В чем может быть дело?
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 5 2010, 20:32
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(alux @ Aug 5 2010, 19:23)  Отрицательный вывод термопары соединен с опорным напряжением +2,5В, которое является опорным для АЦП (AD7799). Режим измерения - биполярный. Поясните, пожалуйста, сию глубокую мысль... Что-то мне кажется, что не должно АЦП мерить напряжение выше опоры. Может, лучше подцепить опорное напряжение к плюсовому входу АЦП и плюсовому проводу ТП соответственно? И всё равно непонятно... Я обычно делаю приподнятую слегка землю и цепляю к ней датчик (неважно какой) и общий вход АЦП. Никаких проблем и можно пользоваться усилителем.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Aug 6 2010, 05:57
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(MrYuran @ Aug 5 2010, 23:32)  Поясните, пожалуйста, сию глубокую мысль... Что именно? Что такое биполярный режим? Это измерение напряжения на положительном входе относительно отрицательного входа АЦП. Покажите, пожалуйста, в даташите, где сказано о том, что напряжение на входе не должно превышать опорное? Есть только требования по значению напряжения относительно общего провода (земли). Tanya, какая разница, чем греть, лампочкой или утюгом?
|
|
|
|
|
Aug 6 2010, 06:05
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(alux @ Aug 6 2010, 09:57)  Покажите, пожалуйста, в даташите, где сказано о том, что напряжение на входе не должно превышать опорное? Ну, судя по тому, что вниз изменяется, а вверх не хочет, похоже на то
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Aug 6 2010, 07:54
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Блин, ерунда какая-то... Подключил отрицательный вывод ТП через делитель 20М + 10М на +2.5В. Т.е. на отрицательном выводе ТП должно быть 2.5 * 10/(10+20) = +0.83 В. Но проблема осталась - все равно напряжение с ростом температуры практически не меняется. А при обратном включении меняется, как положено, в обратную сторону В чем дело? PS. Готов выложить исходники... Дело горит!
|
|
|
|
|
Aug 6 2010, 08:18
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(MrYuran @ Aug 6 2010, 11:04)  А на самом деле сколько? Тестером померял +0.5В Цитата(Tanya @ Aug 6 2010, 11:09)  Вы можете прочитать установки? Проблема еще в том, что нет возможности для отладки: плата уже разведена, выводы UART заняты. В принципе, можно подключить по I2C ЖКИ для отладки. Нужно подсуетиться...
|
|
|
|
|
Aug 6 2010, 11:04
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Выкладываю сырцы. Код // HEADER //----------------------
// AD7799 macro definitions #define AD7799_CS_ACTIVE PORTC &= ~(1 << CS) #define AD7799_CS_INACTIVE PORTC |= (1 << CS)
#define NMAX 3
#define AVCC 5.0 // AVCC = +5.0 V #define VREF 2.5 // VREF = +2.5 V #define TMP_SEN 0.01 // Temperature sensor sensitivity tmp36, V/C #define OFFSET_VOLTAGE 0.5 // Offset voltage of TMP36 (0.5 V)
#define STEPS_U 16777216.0 // Full-Scale 2^24 for unipolar operation #define STEPS_B 8388608.0 // Full-Scale 2^(24-1) for bipolar operation
#define TC 0 #define CJ 1
typedef struct { unsigned char Channel; // каналы //double TemperatureCJ; // температура TMP36 double TemperatureTC; // температура термопары long Data[2]; // Значения АЦП для двух каналов }RESULT;
extern RESULT Result;
typedef struct { int Index; // номер диапазона температур int Threshold; // температурный порог int Hysteresis; // гистерезис int Average; // усреднение double Offset[6]; // значения смещений для разных диапазонов температур double Reference[6]; // реперные точки }VALUE;
extern VALUE Value;
typedef struct { unsigned char volatile One; // Первое (младшее) знакоместо unsigned char volatile Ten; // Второе знакоместо unsigned char volatile Hundred; // Третье знакоместо unsigned char volatile Thousand;// Четвертое (старшее) знакоместо }DIGIT;
//////////////////////////////////////// // SOURCE //-----------------------------------
// AD7799 Initialization //------------------------------------------------------------------------------ void ad7799_Init() { ad7799_Reset(); delay_ms(500); ad7799_InitStatus = ad7799_Status(); }
// Запуск непрерывного преобразования на AIN1 //------------------------------------------------------------------------------ void ad7799_StartMeasure() { AD7799_CS_ACTIVE; ad7799_WriteConfig(1, 0, AD7799_128_GAIN, 1, 1, AD7799_AIN1_CHAN); // burnout, bipolar, gain, ref_det, buf, chan ad7799_SetMode(AD7799_CONTINUOUS_CONVERSION_MODE, 0, AD7799_16_7_1_HZ); // mode, psw=0(OFF), rate }
//------------------------------------------------------------------------------ void ad7799_Measure() { Result.Data[Result.Channel] = 0; while(!ad7799_DataReady()); // Ждать окончания преобразования АЦП (RDY => 0) ad7799_RequestData(CONTINUOUS_READ); // 1 -> Continuous Read PORTD &= ~(1 << DIN); // Held Low in Continuous-Read mode for(unsigned char i = 0; i < Value.Average; i++) // (1 << NMAX) { while(!ad7799_DataReady()); // Ждать окончания преобразования АЦП (RDY => 0) Result.Data[Result.Channel] += ad7799_ReadData(); // Накапливаем результат } Result.Data[Result.Channel] /= Value.Average; // >>= NMAX; // Усреднение результата while(!ad7799_DataReady()); // Ждать окончания преобразования АЦП (RDY => 0) ad7799_RequestData(NOT_CONTINUOUS_READ); // 0 -> Not Continuous Read // Maintain multiplexing of input channels //if(++Result.Channel > 2) // Result.Channel = 0; switch(Result.Channel) { case AD7799_AIN1_CHAN: ad7799_WriteConfig(1, 0, AD7799_128_GAIN, 1, 1, AD7799_AIN1_CHAN + Result.Channel); // burnout, bipolar, gain, ref_det, buf, chan break; case AD7799_AIN2_CHAN: ad7799_WriteConfig(1, 0, AD7799_2_GAIN, 1, 1, AD7799_AIN1_CHAN + Result.Channel); // burnout, bipolar, gain, ref_det, buf, chan break; } }
void Initialise() { ..... Result.Channel = 0; ad7799_Init(); ad7799_StartMeasure(); }
void main() { Initialise(); // set up I/O registers, flags & variables
__enable_interrupt(); // allow all enabled interrupts for(;;) { ad7799_Measure();
Result.TemperatureTC = Vtc(Result.Data[TC]) * 1000;
__sleep(); //Idle. Спать до следующего прерывания } }
// Вычисление напряжения термопары, В //------------------------------------------------------------------------------ double Vtc(long AdcValue) { return (AdcValue - STEPS_B) * VREF / 128 / STEPS_B; }
// Timer/Counter0 Overflow ISR: Вызывается с интервалом 4 мс // Вывод значения на индикатор и обработка нажатия кнопок. //------------------------------------------------------------------------------ #pragma vector=TIMER0_OVF_vect __interrupt void TIMER0_OVF_ISR() { // Динамическая индикация четырехразрядного индикатора switch(znak) { case 0: { int temp = (pValue == &Result.TemperatureTC) ? (int)(Result.TemperatureTC * 10) : *(int*)pValue; // Преобразовать значение *pValue в BCD число: bin2bcd(ABS(temp)); if(temp < 0) { if(temp > -10) { Digit.Ten = MINUS; Digit.Hundred = EMPTY; Digit.Thousand = EMPTY; } else if(temp > -100) { Digit.Hundred = MINUS; Digit.Thousand = EMPTY; } else if(temp > -1000) Digit.Thousand = MINUS; } else { if(temp < 10) Digit.Ten = EMPTY; if(temp < 100) Digit.Hundred = EMPTY; if(temp < 1000) Digit.Thousand = EMPTY; } } digit(znak++); // Включить первый (младший) разряд индикатора // Преобразовать значение единиц индикатора в 7-сегментный код и вывести в порт display(Digit.One); break; case 1: digit(znak++); // Включить второй разряд индикатора // Преобразовать значение десятков индикатора в 7-сегментный код и вывести в порт display(Digit.Ten); if((pValue == &Result.TemperatureTC) && (Result.TemperatureTC < 1000)) { PORTB |= (1 << POINT); } else { PORTB &= ~(1 << POINT); } break; case 2: digit(znak++); // Включить третий разряд индикатора // Преобразовать значение сотен индикатора в 7-сегментный код и вывести в порт display(Digit.Hundred); break; case 3: digit(znak); // Включить четвертый (старший) разряд индикатора // Преобразовать значение тысяч индикатора в 7-сегментный код и вывести в порт display(Digit.Thousand); znak = 0; break; } }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|