Ошибка в программе или особенность Протеус?
- Войдите на сайт для отправки комментариев
Пытаюсь сделать датчик уровня воды в емкости. Принцип действия основан на измерении емкости конденсатора, который представляет собой медную трубу диам. 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%. Результат удовлетворительный применительно к моей задаче.