Ошибка в программе или особенность Протеус?
- Войдите на сайт для отправки комментариев
Пытаюсь сделать датчик уровня воды в емкости. Принцип действия основан на измерении емкости конденсатора, который представляет собой медную трубу диам. 15мм (1-я обкладка) и изолированного провода, размещенного внутри этой трубки (2-я обкладка) и погруженного в воду. Емкость датчика меняется от 20pF (пустая) до 1700pF (полная).
Схема
Работает (по моей задумке) так: изначально РВ0, РВ1, РВ2 - выходы с низким уровнем, датчик С1 разряжен. Перед началом измерения РВ2 переключаем на высокий уровень, а РВ1 и РВ2 на входы компаратора. Через R3 начинается заряд конденсатора. Запускаем таймер Т2 , по прерыванию от компаратора останавливаем. Время пропорционально емкости. R1,R2 - делитель, подает на инвертирующий вход компаратора Uпит/2.
Код ( компилировал в Атмел Студио 8.0)
#define F_CPU 8000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <string.h> #include <avr/power.h> #include <util/atomic.h> uint8_t temp, count, start; volatile uint8_t c; #define BAUD_C 101 #define TxD PB4 #define T_START TCCR0B = (1 << CS01) // F_CPU/8 #define T_STOP TCCR0B = 0 //#define T_RESET TCNT0 = 0 ISR(TIM0_COMPA_vect){ OCR0A += BAUD_C; c = 1; //T_RESET; } void send(uint8_t data) { if (count >= 8) { PORTB |= (1<<TxD); start = 0; temp = 0; c = 0; count = 0; T_STOP; OCR0A = 0; return; } if(c == 1) { if (start == 0) { temp = 0x80; start = 1; count--; } else { temp = data; temp = temp >> count; temp = temp << 7; } switch(temp) { case 0x80 : PORTB &= ~(1 << TxD); break; case 0 : PORTB |= (1 << TxD); break; } count++; c = 0; } } void send_ch(uint8_t data){ uint8_t f; data = ~data; T_START; for(f = 0; f < 10; f++){ while(c == 0); send(data); } } void send_str(char *text){ while(*text) { send_ch(*text++); } } void itoa(uint16_t n, char s[]) { uint8_t i = 0; do { s[i++] = n % 10 + '0'; } while ((n /= 10) > 0); s[i] = '\0'; // Reversing uint8_t j; char c; for (i = 0, j = strlen(s)-1; i<j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } } void send_num(char *text, uint16_t n){ char s[6]; itoa((uint16_t)n, s); send_str(text); send_str(s); } volatile uint16_t capt; volatile uint8_t ovf_cnt, measured_flag, ovf_flag; uint16_t Measure() { DDRB &= ~(1<<PB0); //включаем входы компаратора DDRB &= ~(1<<PB1); _delay_ms(5); //даем устаканиться переходным процессам TCNT1 = 0; //сбрасываем таймер1 measured_flag = 0; ovf_flag = 0; ovf_cnt = 0; capt = 0; //TCCR1 |= (1 << CS12); // старт таймера1 F_CPU/8 TCCR1 |= (1 << CS10); // старт таймера1 F_CPU PORTB |= 1<<PB2; // начинаем заряд конденс ACSR |= (1<<ACIE); //разрешаем прерывание компаратора) while (!measured_flag) // ждем поднятия флага от обработчика компаратора { capt = ((uint16_t)ovf_cnt) << 8; //умножаем количество переполнений таймера1 на 256 capt |= TCNT1; //прибавляем то, что на счетчике таймера1 } ACSR &= ~(1<<ACIE); //запрет прерывание компаратора) DDRB |= 1<<PB0; //входы компаратора ставим выходами DDRB |= 1<<PB1; PORTB &= ~(1<<PB2); // сброс низкий return capt; } ISR(TIM1_OVF_vect) //обработчик таймера1 : инкрементир. переменную при переполнении { ovf_cnt++; if (ovf_cnt == UINT8_MAX) { ovf_flag = 1; //если переполнение - поднимаем флаг ovf_cnt = UINT8_MAX - 1; } } ISR(ANA_COMP_vect) //обработчик компаратора { TCCR1 = 0; // останов таймер1 measured_flag = 1; } int main(void){ DDRB |= (1 << TxD); TIMSK |= (1 << OCIE0A); // разрешение прерывания таймера0 по совпадению А sei(); DDRB |= 1<<PB0; //выход низкий DDRB |= 1<<PB1; DDRB |= 1<<PB2; TIMSK |= (1 <<TOIE1 ); //разрешаем прерывание по переполнению таймера1 DIDR0 |= (1<<AIN1D)|(1<<AIN0D); //откл. цифровых буферов на входах компаратора ACSR |= (1<<ACIS0)|(1<<ACIS1); //преривание компаратора при смене с 0 на 1 while(1){ _delay_ms(1000); uint16_t a = Measure(); if(!ovf_flag) {send_num("Norm:",a);} //выводим верные показания else {send_num("Over:",a);} //Было переполнение ovf_cnt, показания неверные //send_num(" A :",(uint16_t)ovf_cnt); //send_num(" b :",(uint16_t)TCNT1); } }
Пояснения по коду: строки 10-90 - программный ЮАРТ, честно сколипизжен тут. Остальное мое. Пока жду ATtiny решил смоделировать в Протеусе. И все вроде работает, но есть одно НО! В сериал иногда выводятся различные значения, для этого примера в основном выводится
Norm:46802
Но иногда (примерно каждое 10 - 15 значение) выводится другое , например
Norm:47194 или Norm:46907
Иногда разница показаний доходит до 500. Я так понимаю, модели Протеус не могут допускать таких отклонений и ошибку надо искать в пограмме? Или в Протеусе могут наблюдаться подобные странности? Собственно это и есть вопрос.
Ну о попутно просьба к знающим - может кого не обременит глянуть код и указать на ошибки. Буду очень признателен:))
Вы ведь это не arduino IDE компилируете? Чем? Или ею?
Я выше писал - компилировал в Атмел Студио 8.0
Один раз целый день потратил на поиск ошибки в программе при моделирование в Протеус. В железе проверил - всё норм.
kolyn ошибок особо не видно
так размышления
а РВ1 и РВ2 на входы компаратора - надо читать как а РВ0 и РВ1 на входы компаратора
111-114 зачем то попали внутрь цикла ожидания
Пытаюсь сделать датчик уровня воды в емкости. Принцип действия основан на измерении емкости конденсатора, который представляет собой медную трубу диам. 15мм (1-я обкладка) и изолированного провода, размещенного внутри этой трубки (2-я обкладка) и погруженного в воду. Емкость датчика меняется от 20pF (пустая) до 1700pF
Но иногда (примерно каждое 10 - 15 значение) выводится другое , например
Иногда разница показаний доходит до 500.
Ну о попутно просьба к знающим - может кого не обременит глянуть код и указать на ошибки. Буду очень признателен:))
отклонение 500 попугаев от номинала 50тыс - это 1%
Очень приличный результат для простейшего измерителя емкости.
111-114 зачем то попали внутрь цикла ожидания
Я их вначале в прерываннии делал, а потом решил перенести в основной цикл. И не те скобки убрал...
Komandir, огромное спасибо!
отклонение 500 попугаев от номинала 50тыс - это 1%
Очень приличный результат для простейшего измерителя емкости.
Протеус создает цифровую модель. А от модели я ожидал 100% повторяемости - если в нее специально не внесен элемент случайности.
отклонение 500 попугаев от номинала 50тыс - это 1%
Очень приличный результат для простейшего измерителя емкости.
Протеус создает цифровую модель. А от модели я ожидал 100% повторяемости - если в нее специально не внесен элемент случайности.
Пришли ATtiny85, испытал в железе. Разброс показаний не превышает 1,3%. Результат удовлетворительный применительно к моей задаче.