roboforum.ru

Технический форум по робототехнике.

Счётчик импульсов

Раздел создан специально для людей которым интересна робототехника, но в силу разных причин они не знают с чего начать.
Задавайте ваши вопросы, какими бы простыми они не казались, постоянные посетители форума постараются ответить на них по мере своих сил.
Робот своими руками. Самодельный робот.

Re: Счётчик импульсов

Сообщение legion » 05 май 2014, 15:07

Через ICP нужно, да. Там и антидребезг есть подключаемый встроенный, если не путаю.
legion
 
Сообщения: 736
Зарегистрирован: 24 апр 2010, 14:47
Откуда: Уфа
прог. языки: avr asm

Re: Счётчик импульсов

Сообщение Maxiik » 07 май 2014, 14:44

Радость моя была не долгой (((
Выводится по сути какая-то белеберда....
Я так понимаю, что таймер переполняется и поэтому выводятся не правильные цифры...
Посмотрите пожалуйста !
Я уже и пороги поставил, а всёравно не помогает....
***
int s; // переменная для хранения выводимого значения
int i; // промежуточная переменная для хранения времени между импульсами в миллисекундах
int a; // переменная для хранения натиканого значения таймера

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
#asm ("cli") // глобально запрещаем прерывания на время обработки
a = TCNT0; // Присваиваем переменной а число натиканое таймером
TCNT0 = 0; // обнуляем таймер
#asm ("sei") // разрешаем глобальные прерывания
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x00;
}
***

while (1)
{
if (a<=100)a=100;
if (a>=255)a=255;
i = a * 0.128;
s = 1000 / i;


lcd_gotoxy(0,0);
lcd_putchar(s/10+0x30);
lcd_putchar(s%10+0x30);


};

Добавлено спустя 1 час 5 минут 45 секунд:
В общем , как я понял, основная проблема,- это переполнение таймера...
Подскажите как можно решить проблему переполнения таймера ?)
Аватара пользователя
Maxiik
 
Сообщения: 262
Зарегистрирован: 28 сен 2009, 21:54
Откуда: Петербург
прог. языки: С++
ФИО: Бирюк Максим Викторович

Re: Счётчик импульсов

Сообщение dccharacter » 07 май 2014, 18:00

Ха ха ха, собрал ВСЕ грабли, по которым я прошелся, решая задачу. Я даже записал для себя (простите, что ссылка не на народе.ру и на чуркистанском): http://dccharacter.blogspot.com/2012/08 ... f-eye.html
Метода по измерениям мне очень помогла. Вообще методичек сейчас куча опубликована в инете - офигенный источник информации.

У тебя есть прерывание по переполнению таймера/счетчика. Заведи еще одну переменную и инкрементируй ее в прерывании. Так ты будешь знать сколько раз счетчик переполнился за нужный тебе промежуток времени.
Мой волшебник это я сам. Всю архитектуру программы придумал лично, а ребята помогли воплотить её. Я бы и сам мог написать, но лень учить язык и его конструкции.
Аватара пользователя
dccharacter
 
Сообщения: 4995
Зарегистрирован: 10 дек 2010, 13:16
Откуда: Красногорск МО
прог. языки: C, Python, wiring/processing
ФИО: Андрей

Re: Счётчик импульсов

Сообщение Dmitry__ » 07 май 2014, 18:25

ыыыыыыыыы, dccharacter, а можно пожлобить? :)
Вот вы пишите:
Код: Выделить всёРазвернуть
        else
        {
            cntval = (CCPR1H << 8) + CCPR1L;
            TMR1L -= CCPR1L;
            TMR1H -= CCPR1H;
        }

И тут:
Код: Выделить всёРазвернуть
        {           
            TMR1L = 0;
            TMR1H = 0;
            cntval = 0;
        }

Тут совсем плохо:
Код: Выделить всёРазвернуть
        {
            cntval = (CCPR1H << 8) + CCPR1L;
            TMR1L -= CCPR1L;
            TMR1H -= CCPR1H;
        }


А тут правильно :)
Код: Выделить всёРазвернуть
    TMR1H = 0;
    TMR1L = 0;


А все дело в:
11.5 Чтение и запись таймера в 16-разрядном режиме
TMR1 может быть настроен для работы в режиме 16-разрядного чтения/записи (смотрите рисунок 11-2). Когда бит
RD16(T1CON<7>) установлен в ‘1’, обращение по адресу TMR1H вызовет действие с буферным регистром. При чтении
TMR1L значение старшего байта TMR1 будет загружено в буфер. Это позволяет читать 16-разрядное значение
полностью без необходимости проверки возможного переполнения младшего байта.
Запись старшего байта TMR1 должна выполняться через буферный регистр TMR1H. В старший байт TMR1
переписывается значение из TMR1H при записи в регистр TMR1L. Это позволяет сразу записывать 16-разрядное
значение.
В этом режиме старший байт TMR1 не доступен для непосредственного чтения или записи. Любая запись или
чтение должно выполняться через буферный регистр TMR1. Запись в TMR1H не сбрасывает предделитель.
Предделитель сбрасывается только при записи в TMR1L.

Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Счётчик импульсов

Сообщение dccharacter » 07 май 2014, 18:45

А ты мне не выкай!
Пойду почитаю че ты там написал. Жлобить можно, у меня от этого навыки правильного эмбеддинга вырабатываются.

Добавлено спустя 2 минуты 52 секунды:
я нихрена не понял :-) Ни что написал сам, ни что процитировал ты. Т.е. погодь, можно в TMR1H писать uint16_t а из TMR1L читать uint16_t?
Мой волшебник это я сам. Всю архитектуру программы придумал лично, а ребята помогли воплотить её. Я бы и сам мог написать, но лень учить язык и его конструкции.
Аватара пользователя
dccharacter
 
Сообщения: 4995
Зарегистрирован: 10 дек 2010, 13:16
Откуда: Красногорск МО
прог. языки: C, Python, wiring/processing
ФИО: Андрей

Re: Счётчик импульсов

Сообщение Dmitry__ » 07 май 2014, 18:48

Я выкал шутя, жлобил ведь :)
Вот картинка этого буфера, при записи младшего байта, скидывается старший байт из tmp
Изображение

Добавлено спустя 1 минуту 50 секунд:
т.е. записывать первым TMR1H, а считывать первым TMR1L
Последний раз редактировалось Dmitry__ 07 май 2014, 18:49, всего редактировалось 1 раз.
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Счётчик импульсов

Сообщение dccharacter » 07 май 2014, 18:52

А это ты для какого МК цитируешь? В pic16f1827, к примеру, нет такой фигни.

Добавлено спустя 2 минуты 13 секунд:
Вот смотрю хедеры, кстати, можно прям фигачить в TMR1 без L и H похоже

Добавлено спустя 1 минуту 6 секунд:
Writes to TMR1H or TMR1L directly update the
counter

Добавлено спустя 56 секунд:
READING AND WRITING TIMER1 IN
ASYNCHRONOUS COUNTER
MODE
Reading TMR1H or TMR1L while the timer is running
from an external asynchronous clock will ensure a valid
read (taken care of in hardware). However, the user
should keep in mind that reading the 16-bit timer in two
8-bit values itself, poses certain problems, since the
timer may overflow between the reads.
For writes, it is recommended that the user simply stop
the timer and write the desired values. A write
contention may occur by writing to the timer registers,
while the register is incrementing. This may produce an
unpredictable value in the TMR1H:TMR1L register pair.
Мой волшебник это я сам. Всю архитектуру программы придумал лично, а ребята помогли воплотить её. Я бы и сам мог написать, но лень учить язык и его конструкции.
Аватара пользователя
dccharacter
 
Сообщения: 4995
Зарегистрирован: 10 дек 2010, 13:16
Откуда: Красногорск МО
прог. языки: C, Python, wiring/processing
ФИО: Андрей

Re: Счётчик импульсов

Сообщение Dmitry__ » 07 май 2014, 18:54

хм, да, нету, во бред. Но тогда таймер надо обязательно останавливать при чтении. Или делать проверку что при чтении TMR1L не изменился TMR1H. Прикинь, считываешь 0x20ff, считал TMR1L = 0xff, а в этот момент таймер инкрементировался, и TMR1H стал 0x21.
Последний раз редактировалось Dmitry__ 07 май 2014, 18:57, всего редактировалось 1 раз.
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Счётчик импульсов

Сообщение dccharacter » 07 май 2014, 18:57

TMR1L = 0;
TMR1H = 0;

А писал я так, потому, что если делать наоборот, то возможна ситуация, когда TMR1L == 0xFF. В этот момент ты пишешь 0 в TMR1H. В следующем такте TMR1L пробрасывает единицу в TMR1H, и ты обнуляешь TMR1L. В итоге вместо нуля в счетчике у тебя получается 0x0100

Добавлено спустя 2 минуты 3 секунды:
А вот при чтении, похоже, ты прав
я-то думал, что вот тут я в безопасности: TMR1L -= CCPR1L;
Но, наверное, если посмотреть асм-листинг, там чудеса какие-нить будут. Да даже без листинга если TMR1L == 0xff, а CCPR1L == 0x00, то косяк
Мой волшебник это я сам. Всю архитектуру программы придумал лично, а ребята помогли воплотить её. Я бы и сам мог написать, но лень учить язык и его конструкции.
Аватара пользователя
dccharacter
 
Сообщения: 4995
Зарегистрирован: 10 дек 2010, 13:16
Откуда: Красногорск МО
прог. языки: C, Python, wiring/processing
ФИО: Андрей

Re: Счётчик импульсов

Сообщение Dmitry__ » 07 май 2014, 19:20

dccharacter писал(а):TMR1L = 0;
TMR1H = 0;

А писал я так, потому, что если делать наоборот, то возможна ситуация, когда TMR1L == 0xFF.


Да, тут сбрасывал правильно, так и надо делать в убогих 16-ти битных таймерах. Я думал у тебя таймер с буфером...

В пдф:
dccharacter писал(а):А это ты для какого МК цитируешь? В pic16f1827, к примеру, нет такой фигни.


В пдф есть предупреждение, для сброса таймера катит твой способ, а если надо записывать произвольное число, то:

For writes, it is recommended that the user simply stop
the timer and write the desired values. A write
contention may occur by writing to the timer registers,
while the register is incrementing. This may produce an
unpredictable value in the TMR1H:TMR1L register pair.


Добавлено спустя 15 минут 51 секунду:
Читать так можно:
Код: Выделить всёРазвернуть
tmpL = TMR0L;
tmpH = TMR0H;
if (tmpH != TMR0H)
  {
    tmpL = TMR0L;
    tmpH += 1;
  }

Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Счётчик импульсов

Сообщение Radist » 07 май 2014, 22:03

Максиму: очень сложно вас консультировать. Вы даете куски кода, работающие не так, как вы хотите, но из них не сложить всю картину. Имеем кучу вопросов: когда включается таймер? До скольки таймер может досчитать (какой предделитель)? Есть ли его предустановка? Правильная разработка начинается с ТЗ, где все расписано: что надо измерить, все параметры (от стольки до стольки, с таким допуском). Затем нужно четко понимать как математически решается задача (именно тут до скольки должен считать таймер, погрешность счета и тд). Когда все это сложилось в голове - полдела сделано. Уже всем нам будет понятно (если вы все это напишете), что надо сделать, как вы это делаете и где грабли.

ЗЫ. Зачем вы в прерывании запрещаете/разрешаете прерывания? Вот опять вопрос: вы на каком МК делаете? На AVR это делается само.
Аватара пользователя
Radist
 
Сообщения: 2241
Зарегистрирован: 01 июл 2009, 08:59
Откуда: Екатеринбург
прог. языки: асемблер AVR

Re: Счётчик импульсов

Сообщение Maxiik » 12 май 2014, 13:20

Radist, прерывания запрещаю, чтобы на всякий случай *)
Я в теории не особо силён, сейчас тоже стараюсь изучать параллельно )
Конечная задача состоит в том, чтобы измерять обороты двигателя на автомобиле.
На данный момент задача состоит в том чтобы понять как считать импульсы в целом. Для этого я собрал маленький генератор импульсов на 555-ом таймере. Измерял на осциллографе- он выдаёт от 15 до 100 герц примерно, можно регулировать подстроечным резистором.
***
Я использую микроконтроллер АТмега8
частота кварца 8 МГц
Таймер использую - 0 (на сколько мне известно, он 8-и разрядный)
Предделитель - 1024 (Если я правильно понял,в моём случае получается 7812,5 Гц)
Прерывания (импульсы) подключил к выводу INT1
***
Таймер у меня считает постоянно до переполнения, после чего обнуляется и начинает считать сначала.
При возникновении прерывания на INT1 читается значение натиканое таймером и переводится в число импульсов в секунду.
После чтения из таймера он обнуляется принудительно.
На сколько я правильно понимаю, таймер считает от 0 до 256.
***
Тактовая частота микроконтроллера Fcpu = 8000000 Гц
Период тактового сигнала микроконтроллера Tcpu = 1/Fcpu
Период тактового сигнала таймера Т0 равен Tt0 = (1/Fcpu)/k = k/Fcpu

При k = 1024 период тактовой частоты таймера Т0 будет равен Tt0 = 1024/8000000 = 0.128 мс
***
Таким образом получаем время одного тика 0.128 мс.
Умножив число тиков на время одного тика я получаю период импульсов (время длительности одного импульса)
поделив одну секунду на получаю число импульсов в секунду.
Например между прерываниями было 150 тиков таймера, то получаем 1000 / ( 150 * 0.128 ) = 52 Гц (импульсов в секунду)
***
Вот у меня такая логика в программе.
На всякий случай прикреплю полный проект. Я работаю в CVavr.
Спасибо большое за помощь и советы !!!

Добавлено спустя 4 минуты 57 секунд:
dccharacter, по поводу...
У тебя есть прерывание по переполнению таймера/счетчика. Заведи еще одну переменную и инкрементируй ее в прерывании. Так ты будешь знать сколько раз счетчик переполнился за нужный тебе промежуток времени.

... попробую !
Спасибо большое за совет !
Отпишусь попозже *)
Вложения
sss.hex
(3.55 КиБ) Скачиваний: 218
sss.c
(3.82 КиБ) Скачиваний: 225
Аватара пользователя
Maxiik
 
Сообщения: 262
Зарегистрирован: 28 сен 2009, 21:54
Откуда: Петербург
прог. языки: С++
ФИО: Бирюк Максим Викторович

Re: Счётчик импульсов

Сообщение dccharacter » 12 май 2014, 18:07

Мой волшебник это я сам. Всю архитектуру программы придумал лично, а ребята помогли воплотить её. Я бы и сам мог написать, но лень учить язык и его конструкции.
Аватара пользователя
dccharacter
 
Сообщения: 4995
Зарегистрирован: 10 дек 2010, 13:16
Откуда: Красногорск МО
прог. языки: C, Python, wiring/processing
ФИО: Андрей

Re: Счётчик импульсов

Сообщение Maxiik » 13 май 2014, 01:01

Спасибо за советы, курю статью *)
По одному из советов добавил переменную, немножко посидел над программой и получилось !
Никозисто и скорее всего не грамотно с точки зрения программиста, но всё-же работает !!!) Ура !
Добавил переменную для подсчёта количества переполнения таймера *) Как советовал dccharacter.
Ниже выложу код, подскажите как можно сделать более грамотно !
Да и вывод на дисплей у меня хромает...( Как правильно выводить на ЖК дисплей длинное число ?)
***
КОД
***

Chip type : ATmega8L
Program type : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/

#include <mega8.h>
#include <delay.h>
#include <stdio.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>

int s; // переменная для хранения выводимого значения
int i; // переменная счётчик прерываний - импульсов
int a; // переменная для хранения текущего значения таймера
int b; // переменная для хранения результата общего натиканого таймером
int e=0; // переменная для хранения числа сколько раз переполнился таймер

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{


a = TCNT0; // Присваиваем переменной а число натиканое таймером
b = (e * 256)+a; // Расчитываем общее число тиков, умножив число переполнения таймера на 256 и сложив с текущим значением таймера
e=0; // обнуляем число переполнений таймера для новых подсчётов
TCNT0 = 0; // обнуляем таймер

}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0x00;

e++;

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7.813 kHz
TCCR0=0x05;
TCNT0=0x06;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Rising Edge
GICR|=0x80;
MCUCR=0x0C;
GIFR=0x80;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm("sei")

while (1)
{
i = b * 0.128;
s = 1000 / i;

lcd_gotoxy(0,0);
if (s<=99)
{
lcd_putchar(0+0x30);
lcd_putchar(s/10+0x30);
lcd_putchar(s%10+0x30);
}

if (s>=100)
{
lcd_putchar((s/10)/10+0x30);
lcd_putchar(((s/10)/10)%10+0x30);
lcd_putchar(s%10+0x30);
}

};
}
Аватара пользователя
Maxiik
 
Сообщения: 262
Зарегистрирован: 28 сен 2009, 21:54
Откуда: Петербург
прог. языки: С++
ФИО: Бирюк Максим Викторович

Re: Счётчик импульсов

Сообщение Maxiik » 14 май 2014, 01:29

Доброго времени суток !
Выкладываю видео первых полевых испытаний тахометра (счётчика импульсов).
Сигнал брал с датчика холла *)
Теперь нужно работать над точностью показаний и грамотностью кода...
Очень жду советов по более граматному коду, как лучше реализовать...
Зарание спасибо !
***
Код той версии что на видео тоже прикладываю *)

Добавлено спустя 1 минуту 35 секунд:
http://www.youtube.com/watch?v=5rNqvlfN3e0&feature=youtu.be
Вложения
sss.hex
(4.38 КиБ) Скачиваний: 221
Аватара пользователя
Maxiik
 
Сообщения: 262
Зарегистрирован: 28 сен 2009, 21:54
Откуда: Петербург
прог. языки: С++
ФИО: Бирюк Максим Викторович

Пред.След.

Вернуться в Новичкам или основы основ роботостроения.

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

cron