В данном эксперименте попробуем исследовать такой замечательный модуль PIC микроконтроллеров как CCP(Capture/Compare/PWM).
Ну в общем приступим…
Исходя из названия модуля можно предположить, что он может:
1. Захватить
2. Сравнить
3. Зашимить 🙂
Продолжение внутри.
Главный здесь регистр ССP1CON:
CCP1X:CCP1Y – биты, про которые будет рассказано слегка попозже
CCP1M<3:0> – выбор режима:
0000 = все вырублено
0100 = захват, каждый ниспадающий импульс0101 = захват, по каждому возрастающему фронту
0110 = захват, по каждому 4 возрастающему фронту
0111 = захват, по каждому 16 возрастающему фронту
1000 = сравнение, перевод выходного пина в 1 при совпадении
1001 = сравнение, очистка выходного пина при совпадении
1010 = сравнение, генерация софтового прерывания
1011 = сравнение, переключение специального события (сам пока толком не понял что это за зверь)
11хх = режим ШИМ
Для начала рассмотрим модуль захвата:
В этом режиме содержимое регистров TMR1H и TMR1L копируется в регистры CCPR1H и CCP1L в следующих ситуациях:
- По каждому спаду на RB3
- По каждому возрастающему импульсу на RB3
- По каждому 4 возрастающему импульсу на RB3
- По каждому 16 возрастающему импульсу на RB3
Для корректной работы модуля нужно соблюсти два условия:
- Пин RB3 должен быть сконфигурирован как вход
- TMR1 должен работать как таймер или как счетчик
По записи может происходить прерывание (флаг ССP1IF). Пример программы приводить не буду, т.к. тут надо еще подумать как извлекать инфу нужную (подключать дисплей и т.д., а это засорит код).
Сравнение: В этом режиме значение регистра CCP1 сравнивается со значением в регистре таймера TMR1. В случае совпадения величин может изменяться состояние порта RB3 или генерироваться прерывание
Для корректной работы режима нужно обеспечить следующие условия:
- Порт RB3 должен быть сконфигурирован как выход
- Таймер TMR1 синхронизируется внутренним тактированием (Focs/4)
Составим небольшую программку для проверки работы компаратора, в данном примере будем генерировать импульсы шириной 1 мс.
#include &lt;htc.h&gt; #define _XTAL_FREQ 4000000 __CONFIG(WDTDIS &amp; UNPROTECT &amp; MCLREN &amp; LVPDIS); void main() { unsigned char x; __delay_ms(100); TRISB = 0x00; PORTB = 0x00; CCPR1H = 0b00000011; CCPR1L = 0b11101000; // 1000 in CCPR1 CCP1M3 = 1; // Сравнение, при совпадении генерим прерывание CCP1M2 = 0; CCP1M1 = 1; CCP1M0 = 0; T1CKPS1 = 0; T1CKPS0 = 0; // Prescaler = 0 T1OSCEN = 0; TMR1CS = 0; // Fosc/4 TMR1ON = 1; T1SYNC = 0; GIE = 1; PEIE = 1; CCP1IE = 1; for (;;) { } } void interrupt isr() { if (CCP1IF) { RB3 = !RB3; TMR1H = 0x00; TMR1L = 0x00; CCP1IF = 0; } }
Результат на осциллограмме из протеуса:
Исходники здесь
О самом интересном применении модуля CCP – ШИМе будет рассказано в следующем эксперименте о PIC микроконтроллерах, дабы не было помеси инфы в голове (в том числе моей)
а как получить секнды из CCPR1L?
Сейчас точно не скажу, но полагаю, что нужно просто завести переменную, присвоить ей значение регистра CCPR1L, а затем произвести преобразование обратное расчету параметров таймера TMR1
ps. Попозже постараюсь дописать этот пункт в статью
DOBROE VREMYA SUTOK . MOJETE PODROBNO OPISAT CCP V REJIMA ZAHVATA DLYA RASCHETA OBOROTOV DVIGATELYA .
Доброго, сейчас времени нету совсем, постараюсь на неделе вспомнить что и как, будет лучше если вы напомните мне об этом 🙂
ZDRASTVUETE , VI SKAZALI NAPOMNIT PRIMER PASCHETA OBOROTA DVIGATELYA V REJIME ZAHVATA CCP . YA SAM PROBOVAL MOJETE POSMOTRET PRAVILNOLI YA SDELAL . PO KAKOY FORMULE PRAVILNO RASCHITAETSA OBOROT V MINUTU .
Доброго дня,
Давайте не будем спешить, начнем с того, что я в принципе никогда с похожими вещами дела не имел, поэтому быстро не сориентируюсь.
Формулы простой тоже я так понимаю не будет, т.к. это зависит от того что там выдает импульсы.
Мой главный вопрос, каким образом мотор подсоединяется к модулю захвата? Что там выдает импульсы и в какой момент?
dlya primera mojem proveryat na proteuse . ya prochital v interrnete chto;
1500 об/мин = 50 Гц
3000 об/мин = 100 Гц
6000 об/мин = 200 Гц
na vhod mojem podat signal ot generatora 3.5-4.5V .pryamougolniy formi
Ого, интересные цифры у вас в интернете:
Чтобы перейти к частоте от оборотов в минуту, нужно сначала перейти к угловой скорости, а потом уже к частоте
http://en.wikipedia.org/wiki/Revolutions_per_minute
Приблизительная формула перехода N_Hz = N_rpm/60, то есть 1500 об/мин = 25 Гц, а не 50, 3000 об/мин = 50 Гц, а не 100, ну и т.д.
Меня не этот вопрос то в общем интересовал, а вопрос – откуда конкретно в реальном моторе будут идти импульсы – энкодер, датчик, что-то еще? В зависимости от этого по идее будут считаться обороты в минуту, так например у разных энкодеров разное количество импульсов соответствует полному обороту вокруг оси.
Дальнейший расчет в принципе элементарен и не составляет никаких сложностей.
DA VI PRAVI YA TOJE HOTEL PODROBNO RAZOBRATSA , A DALNEYWEM UJE MOJNO RASCHITAT . NO YA PO IDEI PRO AVTOMOBILNIY TAHOMETR ,TAM 2 IMPULSA DAET 1POLNIY OBOROT .POETOMU YA PISAL 1500 об/мин = 50 Гц
3000 об/мин = 100 Гц
6000 об/мин = 200 Гц
SIGNAL POSTUPAET OT PRERIVATELYA AVTOMOBILYA CHEREZ TRANZISTORNIY KLUCH ILI REZISTORNIY DELITEL NAPRYAJENIYA .
Вот, уже картинка начинает складываться.
Два импульса один полный оборот, все остальное пока лишнее. Дальше, какой мк вы собрались использовать? Я смотрю на ваш код и вижу что там до фига портов, а у меня статья по pic16f628a, соответственно не могу пока дать точный совет.
В целом вроде код выглядит правильным, за исключением того что:
1. Формула перехода от Гц к rpm у вас забита как N = F*60, а нужно (если два импульса = 1 оборот) N = F*30
2. Значения регистров таймера TMR1H, TMR1L реинициализируются только по срабатыванию модуля захвата, то есть ваш N_overflows по идее будет всегда либо 0 либо 1.
В остальном надо пробовать, в том же протеусе, вроде все ок выглядит и я не понимаю зачем вам нужна помощь 🙂
u menya mk pic 16f887 , mogu perevesti na 628 , mne ne ponyatno to ya izmeryuy ;1 .pereud signala . 2. kak etot period pravilno perevesti na chastoti
N = N_end – N_start ;esli N pereud F=1/N i oboroti N1=F*30 tak budet pravilno . i echo kak pravilno prisvoit znachenie ccp. N_end = 256*CCPR1H+CCPR1L; ,N_end = (CCPR1L & 0x00ff); .N_end = CCPR1L+(CCPR1H << 8);
1. По захвату каждого возрастающего фронта вы измеряете период сигнала
2. F = 1/T
Но ваш T может состоять из нескольких прогонов таймера, и я бы делал скорее всего не так, а как то вот так:
1. Рассчитываю период сигнала – T = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)) * 128 us (кварц 8 МГц, предделитель 256)
2. Рассчитываю частоту сигнала F = 1/T
3. Рассчитываю обороты в минуту N = F*30
По правильному присвоению подойдут оба варианта и можно еще кучу новых напридумывать, например:
N_end = 0;
N_end = CCPR1L | (CCPR1H<<8);
mojete obyasnit eto ; 1. Рассчитываю период сигнала – T = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)) * 128 us (кварц 8 МГц, предделитель 256) // * 128 us (кварц 8 МГц, предделитель 256) TMR1 ;
биты 5-4: T1CKPS1:T1CKPS0: Выбор коэффициента деления предделителя TMR1
11 = 1:8
10 = 1:4
01 = 1:2
00 = 1:1
Прошу прощения, перепутал TMR1 c TMR0, вы правы максимальный предделитель здесь 8
T = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)) * 4 us (кварц 8 МГц, предделитель 8)
SPASIBO POPROBUYU PROVERIT I SOOBSHU VAM
YA SEYCHAS PROVERIL ,SIGNAL PODAYU DO 30 HZ CHASTOTA PRAVILNO POKAZIVAET PRI OTLADKE V PROTEUSE S VISHE 30HZ NACHINAET SBIVATSAY CHASTOTI ; PRI CHASTOTE 34HZ f=10HZ,50HZ f=11 , PRI 101HZ f=13HZ .
N = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)); (кварц 8 МГц, предделитель 2)
f=1000000/N;
t=f*30 ;// kolichestva oborotov v minutu
Сбросьте весь проект архивом с настроенным файлом под протеус.
Все как то очень странно, я вообще не смог обработать пока ни одного прерывания по захвату, они попросту не происходят, завтра еще поковыряю.
KAK MOJNO PREKREPIT ZIP FAYL?
Выложите на файлообменник или на сервисы типа дропбокса, яндекс диска и т.д.
К моему сайту прикреплять нельзя.
ya skachal yandex disk . ya postavil fayl tuda . chto ya doljen vam otpravit chtobi vi mogli posmotret fayl
Ссылку на файл.
Выделили папку/файл и выбрали “Поделиться ссылкой”, все после этого можно скидывать ссылку.
sdelal; yandex disk;skopirovat publichnuyu ssilku
Круто, так ссылку эту отдадите мне? 🙂
samoe interesnoe ne mogu nayti adress ssilki .
Блин, пришлите мне просто ваш архив на sargein@gmail.com
Мне не нужен ваш пароль и логин, я уже могу скачать вашу папку, она доступна и мне.
Так что я потру ваш предыдущий пост, ждите в общем, я пока поеду домой и поздним вечером постараюсь повтыкать в ваш проект.
ZDRASTVUETE , KOGDA CHASTOTA S 18-30 HZ PROISHODIT ZAHVAT PRAVILNO POKAZIVAET f ,POSLE 30HZ OSHIBKI , NE IZ ZA ETOGO (256*CCPR1H+CCPR1L))???
Ни один из ваших светодиодов в протеусе не срабатывает при частоте 25 Гц.
Нет, не изза этого, я даже светодиод пока зажечь не смог по прерыванию модуля захвата
кстати
CCP1CON=0b000000101;
В этой строчке вы ноль лишний добавили.
Блин есть большое подозрение что протеус не справляется с данной задачей, не работает даже такой простой код:
Вы можете проверить на реальном девайсе работоспособность кода? А то мне сдается, что я ща ковыряюсь впустую.
DOBRIY DEN . PROTEUSE RABOTAET ,POPROBUYTE DOBAVIT V PRERIVANII OT CCP ; RB3 = !RB3; V KAJDOM PEREPOLNENIE CCP IZMENYAETSA SOSTOYANIYA PORTA RB3.
А почему же не работает RD0 = !RD0?
A U VAS TAK NAPISANO;
if (CCP1IF)
{
RD0 = 0;
TMR1H = 0x00; TMR1L = 0x00;
CCP1IF = 0;
}
да, а до этого в инициализации RD0 = 1;
ну и можете попробовать RD0 = !RD0; у меня изначально так было и он молчал.
RABOTAET I NA ; RD0 = !RD0;
Проверил еще раз. Глухо. Какая версия протеуса у вас и дайте мне хекс файл, скомпиленный вами.
RABOTAET I NA ; RD0 = !RD0; I NA RB3=!RB3 I NA DRUGIH PORTAH
Proteus.pro.7.6.sp4-patch_v1
:060000000A128A110E280D
:10000800FE00030E83120313B4000A08B5000A1297
:100018008A1123280A128A111128A001A101A2011C
:10002800A301A401A501A601A701A801A901AA018C
:10003800AB01AC01AD0183010A128A110A2A0C1C1A
:1000480029280C10A80A0319A90A0C1D5B292808DD
:10005800013EAE0029080318013EAF002E08B0008B
:100068002F08B100B201B301B3003008B200B101EA
:10007800B0013308AD003208AC003108AB003008DD
:10008800AA001508AE001608AF000030AF1BFF30FD
:10009800B000B1002E08AA072F0803110318013E6B
:1000A800031DAB07300803110318013E031DAC07FD
:1000B800310803110318013E031DAD072D08F30095
:1000C8002C08F2002B08F1002A08F0000F30F70185
:1000D800F6004230F5004030F40062210A128A111D
:1000E8007308A3007208A2007108A1007008A0009C
:1000F8002308F3002208F2002108F1002008F0008C
:100108001E30F400F501F601F701D7210A128A1111
:100118007308A7007208A6007108A5007008A4005B
:1001280000302702031DA22800302602031DA22842
:1001380001302502031DA228F5302402031CA6283D
:100148000514A728051000302702031DB528003024
:100158002602031DB52803302502031DB528E93002
:100168002402031CB9288514BA28851000302702F8
:10017800031DC82800302602031DC82805302502A3
:10018800031DC828DD302402031CCC280515CD2802
:10019800051100302702031DDB2800302602031D4D
:1001A800DB2807302502031DDB28D1302402031C7D
:1001B800DF288515E028851100302702031DEE2869
:1001C80000302602031DEE2809302502031DEE2803
:1001D800C5302402031CF2280516F3280512003046
:1001E8002702031D012900302602031D01290B30B7
:1001F8002502031D0129B9302402031C052985168F
:100208000629851200302702031D14290030260212
:10021800031D14290D302502031D1429AD302402B5
:10022800031C182905171929051300302702031D77
:10023800272900302602031D27290F302502031D18
:100248002729A1302402031C2B2985172C29851363
:1002580000302702031D3A2900302602031D3A29DF
:1002680011302502031D3A2995302402031C3E292A
:1002780006143F29061000302702031D4D290030BF
:100288002602031D4D2913302502031D4D298930EF
:100298002402031C5129861452298610013088062D
:1002A800083086068F018E010C11A801A9013508B6
:1002B8008A00340E8300FE0E7E0E0900F901F31F3A
:1002C8007229F009F109F209F309F00A0319F10A90
:1002D8000319F20A0319F30AF901F90AF71F812928
:1002E800F409F509F609F709F40A0319F50A0319D7
:1002F800F60A0319F70A0130F906FA01FB01FC01B5
:10030800FD0173087204710470040319C029F8010F
:10031800F80AF31B95290310F00DF10DF20DF30DFA
:100328008C290310FA0DFB0DFC0DFD0D73087702E7
:10033800031DA82972087602031DA82971087502F1
:10034800031DA82970087402031CBA297008F40256
:100358007108031C710FF5027208031C720FF60274
:100368007308031C730FF7027A140310F30CF20CD2
:10037800F10CF00CF80B952979080319CE29FA0924
:10038800FB09FC09FD09FA0A0319FB0A0319FC0A0F
:100398000319FD0A7D08F3007C08F2007B08F100D0
:1003A8007A08F0000800F801F901FA01FB01701C55
:1003B800F1297408F807750803110318013E031D95
:1003C800F907760803110318013E031DFA07770899
:1003D80003110318013E031DFB070310F40DF50D6F
:1003E800F60DF70D0310F30CF20CF10CF00C73087A
:1003F800720471047004031DDB297B08F3007A087A
:10040800F2007908F1007808F000080085018601FB
:10041800870188018901063083169F0083129F0196
:1004280083168501860104308700880189018B01C4
:100438000730810003178801890183128713881305
:100448000530031397001130900083160C150C1417
:0C0458008B170B1783120C110C10312AAB
:04400E0094ECFFFF30
:00000001FF
Ваш хекс вообще ничего не дергает у меня, даже RD0 в 1 не ставит.
Позже постараюсь вернуться к вашему вопросу, и установить протеус посвежее может в этом глюк, сейчас пора бежать.
TOCHNO PEREUSTANOVITE PROTEUS DOLJNO SRABOTAT .U MENYA TOJE INOGDA TAK BIVAET
Да, поставил сейчас 8 протеус и все начало работать. Теперь можно и поковыряться.
Вопрос – какую максимальную частоту вы хотите ловить?
Если это тахометр так по идее вам же не нужно особо больше 200 Гц, правильно?
izmenil formulu ; N = ((N_overflows+0)*65536 + (256*CCPR1H+CCPR1L))*2;
N=N/16;
CCP1CON=0b00000111;//0111 = захват по каждому 16-му переднему фронту сигнала
T1CON=0b00100001;
//10 = 1:4 частота таймера 500kГц и 1 тик таймера будет равен 1/500000 Гц = 2 мкс.,
vse zarabotalo ,no odna problema mejdu chastotami 130-230 Hz ne opredelyaet chastotu . 0-120 i ot 240 do 400 vse normalno
shkala do 8000 oborotov v minutu 8000/30=266,6 Hz ,stranno pochemu v predelah 130-230 hz N privishaet 65000 i f=0 ;
Как вы проверяете точное значение частоты? Пользуетесь режимом отладки?
da polzuyus otladkoy , v rejime zahvat po 16 frontu bole tochnee vichislaet chastotu
Тестирую код, пока считаю только период:
Работаю как и прежде по каждому фронту, таймер настроен на 1 мкс.
Вот результат:
https://www.dropbox.com/s/s8xsjd5b91vik4w/Taho_piuc.JPG?dl=0
К 270 Гц ошибка расчетной частоты уже составляет 3%, не знаю приемлемо это для вас или нет, но в целом я не наблюдаю пока никаких прострелов в расчете периода.
Добавил частоту
Просвипал по быстрому по частотам все есть, провалов не видно, НО:
Ошибка расчетов частоты в коде составляет уже приличные 20 процентов на 250 Гц, причина добавление математических вычислений в обработчик прерываний – чем больше мы сюда грузим, тем больше ошибка
Я бы кстати вообще частоту не считал, если вы собираетесь светодиодами рулить, можно на основе временных промежутков выбирать сколько светодиодов зажигать.
Ну или повышать частоту тактирования вашего мк.
dly naglyadnosti perevel programmu na 16f628 . chastotomer , pabotaet na vseh chasstotah pri zahvate po kajdomu frontu . pri perevode ccp na zahvat po kajdomu 4 ili 16 frontu rabotaet no ne na fseh chastotah , v kakoyto pereud chastot v eredine ne rabotaet , proekt postavil na yandex disk , mojet proverite kogda vremya budet
Вы мой код пробовали?
Считает по всем частотам на pic16f877a, читайте в общем мои два сообщения сверху.
kompilyator vidaet oshibku na etu stroku;proverte mojet chtoto ne pravilno v etoy stroke
Ttemp = (CCPR1H<<8) | CCPR1L;
if (CCP1IF)
{
Ttemp = 0;
Ttemp = (CCPR1H<<8) | CCPR1L;
T = N_overflows*65536 + Ttemp;
test++;
N_overflows = 0;
TMR1H = 0x00; TMR1L = 0x00;
CCP1IF = 0;
}
Покажите ошибку, все тут правильно и ошибки быть не должно.
Я вам не вручную набирал а скопировал код, который откомпилился и работает.
//// Ttemp = (CCPR1H<<8) | CCPR1L;
А это что значит вообще?
da zdes net oshibki . na vashem soobshenii pochemuta etu stroku pokazivaet tak; Ttemp=(CCPR1H&;lt;8)|CCPR1L;
POSMOTRITE NA VERHU VASHU SOOBSHENII ,ILI U MENYA V KOMPUTERE TAK POKAZIVAET
это глюк отображалки кода, но вы же правильно написали << и |, вместо этих хтмл служебных символов.
YA TOLKO OSVOBODILSYA I HOCHU PROVERIT , SEYCHAS PROVERYU I NAPISHU
PROGRAMMA RABOTAET OTLICHNA ,SDELAL ZAHVAT PO KAJDOMU 16 FRONTU ,TOCHNOST NAMNOGO LUCHSHE ,V CHEM BILA PROBLEMA ? I KAKOY ROL IGRAYUT SDES ETI DVE PEREMENNIE ?
timerFlag = 1;
test++;
Эти переменные для меня, забыл почистить, тестил отладку на протеусе.
SPASIBO CHTO VIDELILI VREMYA I POMOGLI RAZOBRATSA ,BUDU ESHE EKSPEREMENTIROVAT . ESLI POYAVITSA VOPROSI BUDU OBRASHATSYA
Обращайтесь 🙂