|
Проблема с термопарой, ... или с АЦП ? |
|
|
|
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; } }
|
|
|
|
|
Aug 6 2010, 11:43
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Самое интересное вот здесь: Цитата(alux @ Aug 6 2010, 18:04)  ad7799_InitStatus = ad7799_Status(); В исходниках мне не по глазам физическая инициализация АЦП. А почему не использовали AD7793? И опора встроенная, и делитель внутри...
|
|
|
|
|
Aug 6 2010, 11:51
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
продолжение... Код //------------------------------------------------------------------------------ static unsigned char ad7799_InitStatus;
//------------------------------------------------------------------------------ static void ad7799_Reset() { for(unsigned char i = 0; i < 4; i++) SpiTransferByte(0xff); }
// Helper request function //------------------------------------------------------------------------------ static inline void ad7799_Comm(unsigned char reg, unsigned char read, unsigned char cont) { SpiTransferByte((read ? 0x40 : 0x00) | (reg << 3) | (cont ? 0x04 : 0x00)); }
// Return the contents of the AD7799 register ( OFFSET or FULL-SCALE ) //------------------------------------------------------------------------------ unsigned long ad7799_Read(unsigned char reg) { ad7799_Comm(reg, 1, 0); unsigned long val = 0; if(ad7799_InitStatus & AD7799_STATUS_IS_AD7799) val |= (unsigned long)SpiTransferByte() << 16; val |= (unsigned long)SpiTransferByte() << 8; val |= (unsigned long)SpiTransferByte(); return val; }
//------------------------------------------------------------------------------ unsigned char ad7799_Status() { ad7799_Comm(AD7799_STATUS_REG, 1, 0); return SpiTransferByte(); }
//------------------------------------------------------------------------------ void ad7799_SetMode(unsigned char mode, unsigned char psw, unsigned char rate) { ad7799_Comm(AD7799_MODE_REG, 0, 0); SpiTransferByte(mode << 5 | (psw ? 0x10 : 0x00)); SpiTransferByte(rate); }
//------------------------------------------------------------------------------ void ad7799_WriteConfig(unsigned char burnout, unsigned char unipolar, unsigned char gain, unsigned char ref_det, unsigned char buf, unsigned char chan) { ad7799_Comm(AD7799_CONFIG_REG, 0, 0); SpiTransferByte((burnout ? 0x20 : 0x00) | (unipolar ? 0x10 : 0x00) | gain); SpiTransferByte((ref_det ? 0x20 : 0x00) | (buf ? 0x10 : 0x00) | chan); }
// Write value to the AD7799 register ( OFFSET or FULL-SCALE ) //------------------------------------------------------------------------------ void ad7799_Write(unsigned char reg, signed long value) { ad7799_Comm(reg, 0, 0); if(ad7799_InitStatus & AD7799_STATUS_IS_AD7799) SpiTransferByte(value >> 16);
SpiTransferByte(value >> 8); SpiTransferByte(value); }
// Determine if data is ready to be read, could also be implemented by reading the status register //------------------------------------------------------------------------------ bool ad7799_DataReady() { return !(PIND & (1 << RDY)); //DD_MISO }
// Request a read from the data register //------------------------------------------------------------------------------ void ad7799_RequestData(unsigned char continuous) { ad7799_Comm(AD7799_DATA_REG, 1, continuous); }
// Read from data register, it should be previously requested from ad7799_request_data, the value is signed //------------------------------------------------------------------------------ unsigned long ad7799_ReadData() { unsigned long val = 0;
if(ad7799_InitStatus & AD7799_STATUS_IS_AD7799) { val = SpiTransferByte(); val <<= 8; }
val |= SpiTransferByte(); val <<= 8; val |= SpiTransferByte();
return val; } АЦП использовал то, что было под рукой. Драйвер АЦП отлажен, с этим вопросов быть не должно. Пару лет назад делал под AD7794. Проблем с измерением ТП не возникало...
|
|
|
|
|
Aug 6 2010, 13:37
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Код (AdcValue - STEPS_B) * VREF / 128 / STEPS_B эквивалентно Код (AdcValue - STEPS_B)/(2^(30))* VREF - похоже, просто не хвататет разрядности Т.е. я бы предложил переписать примерно так Код #define STEPS_B 8388608LL long long Vtc(long long AdcValue) { return ((long long)(AdcValue - STEPS_B)*5000000LL>>31LL); } Получится целое значение в микроВольтах. Ошибка должна быть небольшая - где-то в районе 1 мкВ
--------------------
aka Vit
|
|
|
|
|
Aug 6 2010, 13:45
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(sensor_ua @ Aug 6 2010, 16:37)  Код (AdcValue - STEPS_B) * VREF / 128 / STEPS_B эквивалентно Код (AdcValue - STEPS_B)/(2^(30))* VREF - похоже, просто не хвататет разрядности #define STEPS_B 8388608.0 // Full-Scale 2^(24-1) for bipolar operation Обратили внимание, что действия происходят с вещественными числами?
|
|
|
|
|
Aug 6 2010, 14:04
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Обратили внимание Обратил. Но там тоже есть разрядность. И из-за её ограниченности бывают характерные ошибки. http://ltwood.wikidot.com/float Сначала long с реальным значением несколько более 2^23 приводится к float, а не double, потому как STEPS_B имеет тип float, потом это нечто умножается на float 2.5, потом ещё пару действий с float, ну и уж потом выполняется приведение к double. И чтобы double действительно было double, а не float, часто компилеру опции нужно выставлять, но и то это имеет смысл если ещё и в поставке есть соответствующие либы. В данном случае (термопара для чего-то там) собственная ошибка сигнала не стОит оперирования с ним как с вещественным значением.
--------------------
aka Vit
|
|
|
|
|
Aug 6 2010, 14:39
|
Гуру
     
Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883

|
Цитата(sensor_ua @ Aug 6 2010, 18:04)  В данном случае (термопара для чего-то там) собственная ошибка сигнала не стОит оперирования с ним как с вещественным значением. Добавлю? Можно даже и так. Чтобы перевести кванты АЦП в микровольты можно подобрать рациональное число, обеспечивающее нужную точность и... микровольты (или миллиградусы или сотые градуса) = кванты (без смещения)* числитель / знаменатель. Как подобрать - http://ru.wikipedia.org/wiki/%D0%9D%D0%B5%...%BE%D0%B1%D1%8CЧтобы правильно переводить в градусы нужно еще вычесть Эдс температуры холодных спаев в квантах. Но это все равно придется делать.
|
|
|
|
|
Aug 7 2010, 06:19
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
чтобы выводить 8-значные числа кодов АЦП. PS. Очень похоже на нехватку памяти при делении вещественных чисел. В какой-то момент при неизменном коде все вдруг стало работать. Значение напряжения на ТП стало расти с температурой. Включал, выключал прибор несколько раз. Все стало пучком... Затем все стало, как было. Цитата(sensor_ua @ Aug 6 2010, 16:37)  Т.е. я бы предложил переписать примерно так Код #define STEPS_B 8388608LL long long Vtc(long long AdcValue) { return ((long long)(AdcValue - STEPS_B)*5000000LL>>31LL); } Получится целое значение в микроВольтах. Ошибка должна быть небольшая - где-то в районе 1 мкВ PS. Код enum { AD7799_1_GAIN, AD7799_2_GAIN, AD7799_4_GAIN, AD7799_8_GAIN, AD7799_16_GAIN, AD7799_32_GAIN, AD7799_64_GAIN, AD7799_128_GAIN };
#define BITS 24
int Vtc(long AdcValue) { return (AdcValue - STEPS_B) * VREF >> (AD7799_128_GAIN + BITS - 1); //30; } Та же фигня! При правильном подключении ТП - напряжение не меняется (по крайней мере то, что вывожу на индикатор), а при обратном включении все работает, только наоборот
|
|
|
|
|
Aug 7 2010, 07:12
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Burnout выключите. Какой проц используете? JTAG или что-то подобное на борту есть?
|
|
|
|
|
Aug 7 2010, 08:02
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
А сколько сегментов на индикаторе?
Для меня сомнительно использование float-арифметики на таком дохлом проце. Попробуйте удвоить стек, если компиллятор IAR.
|
|
|
|
|
Aug 7 2010, 12:11
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(sensor_ua @ Aug 7 2010, 14:44)  Так сколько показывает? И какое напряжение сигнала термопары? Насчёт целочисленной арифметики - как минимум не понял насчёт VREF - оно осталось вещественным или как? Забыл написать Код #define VREF 2500000LL // VREF = +2.5 V Цитата(Tanya @ Aug 7 2010, 14:11)  Вот на него и выводите регистры АЦП. Объясните, пожалуйста, каким образом вывести значение 24-битного регистра в 4-разрядный индикатор? Лучше уж подкличить UART, тогда все станет понятно. Я сейчас этим и занимаюсь.
|
|
|
|
|
Aug 7 2010, 13:15
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Самое простое, если у Вас 8-и-сегментные индикаторы(8 и точка) - выводить по биту целого на сегмент - да не цифры, а козявки, но инфы достаточно Посмотрел ещё раз на Ваш вариант целого - думаю, что без long long переполнение обеспечено. При сигнале 3 мВ код АЦП в идеале должен быть 9677098 (0x93A92A) (AdcValue - STEPS_B)*VREF = 3.221225E+12 (0x 2EDFFF8CC40) 0хFFF8CC40>>30 = 0x03 Но Вы написали Цитата Код #define VREF 2500000LL // VREF = +2.5 V Может, препроцессор лажанулся и пересчитал и подставил VREF >> (AD7799_128_GAIN + BITS - 1) ? Тогда будет ноль. Скобками можно это проверить
--------------------
aka Vit
|
|
|
|
|
Aug 7 2010, 14:42
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(sensor_ua @ Aug 7 2010, 16:15)  Посмотрел ещё раз на Ваш вариант целого - думаю, что без long long переполнение обеспечено. Может, препроцессор лажанулся и пересчитал и подставил VREF >> (AD7799_128_GAIN + BITS - 1) ? Я очень сомневаюсь, что компилер будет игнорировать порядок выполнения арифметических операция и правила приведения типов, которые описаны в любом учебнике по С/С++. Согласно общепринятым правилам, выполняются вначале выражения в скобках, затем слева направо учитывая приоритет операций. Когда результат вычитания (ADC_Value - STEP_B), который имеет тип long , умножается на VREF, имеющий тип long long, то первый операнд приводится к типу long long. Операция >> имеет меньший приоритет, чем *. Это даже не стоит проверять.
|
|
|
|
|
Aug 7 2010, 15:53
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Насчёт long long Вы написали всё правильно и я на это обратил внимание (правда не сразу, потому и редактировал пост добавлением). Цитата Я очень сомневаюсь, что компилер будет игнорировать порядок выполнения арифметических операция и правила приведения типов, которые описаны в любом учебнике по С/С++. Я ясно написал, что возможно проблема у препроцессора, но если бы Вы всё-таки чётко выдали нагора то неправильное число, то и гаданий было бы меньше. А приоритет операций кроме арифметических  , представьте себе, никогда не запоминал и не собираюсь, ибо не на одном Си свет клином сошёлся. Потому если мне надо, то смотрю не учебник, а справочник. И не стесняюсь. В данном случае выдал предположение насчёт возможного нарушения обработки из-за наличия не переменных или констант в последовательной записи , а только литералов. Вам помочь пытаюсь, а Вы одно число выдать боитесь  Ещё у Вас есть усреднение. Интересно было бы узнать значение Value.Average // (1 << NMAX) на предмет опять же переполнения Result.Data[Result.Channel].
--------------------
aka Vit
|
|
|
|
|
Aug 8 2010, 05:13
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Подключил UART. Отдельная плата с MAX232, соединяется через 4 проводка: общий, +5В, RXD, TXD. В программу добавил драйвер UART, которым всегда пользуюсь. Но почему-то всегда передает 0x00, чтобы я не посылал. Какое-то проклятие!!! Сейчас вывожу на 7-сегм индикатор значение напряжения в микровольтах, значение int. При правильном включении ТП показывает значение -1.5 ... -1.7 мВ. ТП прикладываю к горячему. Показания не меняются. Но если подключить неправильно ТП ("-" ТП на AIN1+ ) , то значения меняются по температуре, но в отрицательную область! Я уже все больше склоняюсь к мысли, может просто убрать этот минус и пусть работает так? Но все же этому должно быть какое-то простое объяснение. PS. Значение Value.Average = 4, и это нее приведет к переполнению. PS2. Это ж надо так было облажаться!!! Код // Read from data register, it should be previously requested from ad7799_request_data, the value is signed //------------------------------------------------------------------------------ unsigned long ad7799_ReadData() { unsigned long val = 0;
.................. Нужно возвращать значение типа long !. Главное, что в шапке функции я об этом специально написал  Все теперь работает. Спасибо.
|
|
|
|
|
Aug 10 2010, 07:38
|

Гуру
     
Группа: Свой
Сообщений: 2 002
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271

|
Цитата(MrYuran @ Aug 6 2010, 03:32)  Что-то мне кажется, что не должно АЦП мерить напряжение выше опоры. Полностью поддерживаю! Это следует из принципа работы АЦП, где опора на делителе делится на много-много ответвлений, а потом происходит сравнение. Цитата(alux @ Aug 6 2010, 12:57)  Покажите, пожалуйста, в даташите, где сказано о том, что напряжение на входе не должно превышать опорное? Тогда разность напряжений не должна превышать опору. А вообще, насколько я разбирался с АЦП в Attiny (это конечно не одно и то же), то биполярный режим - это всего лишь способ представления данных: со знаком минус или без знака. А Цитата измерение напряжения на положительном входе относительно отрицательного входа АЦП - это дифференциальный режим измерений, с биполярным не связанный. Другими словами, дифференциальность производится аналогово (вычитанием на входном ОУ), а биполярность делается в цифре - смещением нуля по шкале. И это совершенно независимые параметры.
--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
|
|
|
|
|
Aug 10 2010, 14:45
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Полностью поддерживаю! Это следует из принципа работы АЦП АЦП бывают разных видов. Как и их входные каскады. В данном случае Вы и MrYuran ошибаетесь Вот выдержка из DS AD7799: The AD7798/AD7799 can be programmed to have a gain of 1, 2, 4, 8, 16, 32, 64, or 128 using Bit G2 to Bit G0 in the configuration register. Therefore, with a 2.5 V reference, the unipolar ranges are from (0 mV to 19.53 mV) to (0 V to 2.5 V), and the bipolar ranges are from ±19.53 mV to ±2.5 V. When the in-amp is active (gain ≥ 4), the common-mode voltage (AIN(+) + AIN(−))/2 must be greater than or equal to 0.5 V. If the AD7798/AD7799 operate with a reference that has a value equal to AVDD, the analog input signal must be limited to 90% of VREF/gain when the in-amp is active for correct operation. BIPOLAR/UNIPOLAR CONFIGURATIONThe analog input to the AD7798/AD7799 can accept either unipolar or bipolar input voltage ranges. A bipolar input range does not imply that the parts can tolerate negative voltages with respect to system GND. Unipolar and bipolar signals on the AIN(+) input are referenced to the voltage on the AIN(–) input. For example, if AIN(−) is 2.5 V and the ADC is configured for unipolar mode and a gain of 1, the input voltage range on the AIN(+) pin is 2.5 V to 5 V. If the ADC is configured for bipolar mode, the analog input range on the AIN(+) input is 0 V to 5 V. The bipolar/unipolar option is chosen by programming the U/B bit in the configuration register.
--------------------
aka Vit
|
|
|
|
|
Aug 11 2010, 04:15
|

Гуру
     
Группа: Свой
Сообщений: 2 002
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271

|
Цитата(sensor_ua @ Aug 10 2010, 21:45)  АЦП бывают разных видов. Как и их входные каскады. В данном случае Вы и MrYuran ошибаетесь Вот выдержка из DS AD7799: The AD7798/AD7799 can be programmed to have a gain of 1, 2, 4, 8, 16, 32, 64, or 128 Cогласен, я забыл о наличии усиления перед непосредственно аналого-цифровым преобразованием. Таким образом, все мои утверждения справедливы для сигнала непосредственно перед АЦП, уже после усиления. В любом случае, автору необходимо не забывать про такую цитату: Цитата A bipolar input range does not imply that the parts can tolerate negative voltages with respect to system GND.
--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|