Some years ago I bought some 20MHZ xtals from DigiKey. They came in, I installed them and all my timing was a bit off. After spending a whole bunc= h of time looking at my code and the hardware I finally took a closer look at the xtals and found they were marked 19.. Apparently DigiKey mispicked them, and I didn't perform an appropriate incoming inspection. -- Bob Ammerman ----- Original Message ----- From: "KPL" To: "PICLIST" Sent: Monday, February 20, 2012 12:33 PM Subject: Re: [PIC] pulse counter, pulses lost > Oh, well. > > I will never ever buy cheap crystals again. > I will never ever buy cheap crystals again. > I will never ever buy cheap crystals again. > I swear. > Seems like my 20MHz crystal was not 20MHz at all. With a different > crystal it counts correctly. > > > On Sun, Feb 19, 2012 at 21:43, KPL wrote: >> Hi, >> >> Since this is more about pic itself than about jal, I wll ask here. >> >> While playing (educating myself) with timers, I tried to build a >> frequency counter. The one where time period of counting pulses would >> change depending on pulse rate, that is, frequency. >> At first I used tmr0 and tmr1, then rebuilt using tmr1 and tmr2, but >> still can not get exactly what I was looking for. I have spent many >> late evenings trying, probably somebody from a side can spot my error. >> >> Basically, TIMER2 is used to make a time frame when pulses must be >> counted, but TIMER1 is the one that counts pulses. Both have >> interrupts enabled, and interrupt routine just adds 1 to a variable, >> which is then dealt with in main code. >> No prescalers or postscalers are used. >> In main code, when a time frame counter or a pulse counter exceeds >> pre-defined values, both timers are stopped, their values added to >> respective variables, and both variables just sent via serial link to >> my PC. >> The problem is: >> When TIMER1 (pulse counter) is fed from internal clock, I get correct >> values: >> >> Finish TMR: 5000307 >> Finish CNT: 5000306 >> >> 20MHz crystal is used, so 5MHz instruction clock, and one tick of a >> timer is 0.2us, so this gives frequency : F=3D(CNT * 5000000) / TMR =3D >> 4999999.0 Hz. That error of 1 pulse can be eliminated by changing >> timer start/stop order. >> >> These are about the same, which is correct, since both timers advance >> at the same speed. That made me think that program works correctly. >> >> The only pulse source with predictable frequency I have, is an quartz >> oscillator, marked as 1.8432MHz. Another frequency counter shows it's >> frequency as 1843150Hz. >> When I change T1CON_TMR1CS to 1, and feed pulses from the oscillator, >> I get results like this : >> >> Finish TMR: 5000304 >> Finish CNT: 1843100 >> >> which gives F=3D1842987.94 Hz - which shows I am missing several hundred >> pulses, or my time frame was several hundred pulses too long. >> 5000000 TMR pulses is one second, so it is more-than-enough time >> period to count this frequency. >> >> So, I tried to move all the stuff around, changed start and stop >> sequences, checked datasheets, got a bit different results, but did >> not get better precision. >> Enabling or disabling T1SYNC did not change anything, since the >> frequency I'm trying to measure is quite low. >> It's not like this circuit is mission-critical or something, I just >> want to understand what I'm doing wrong. And I want a good frequency >> counter. >> Where are my pulses?! :) >> How can it be, it's working perfectly with internal clock, but runs >> wrong with external one. >> Code is in Jal2, with jallibs, and it looks like this: >> >> >> include 16f886 -- target PICmicro >> pragma target clock 20_000_000 -- oscillator frequency >> pragma target OSC HS -- HS crystal or resonator >> pragma target WDT disabled -- no watchdog >> pragma target LVP disabled -- no Low Voltage Programming >> pragma target MCLR internal -- reset externally >> -- >> enable_digital_io() >> ------------------------------------------------------------------------= ------------------------ >> >> include delay >> include print >> >> -- UART >> const serial_hw_baudrate =3D 115200 >> include serial_hardware >> serial_hw_init() >> alias serial_write is serial_hw_write >> alias serial_read is serial_hw_read >> alias serial_data is serial_hw_data >> alias serial_data_available is serial_hw_data_available >> >> -- print start >> print_crlf(serial_hw_data) >> print_crlf(serial_hw_data) >> const byte starttmrmsg[] =3D "Startup" >> print_string(serial_hw_data, starttmrmsg) >> print_crlf(serial_hw_data) >> >> -- time frame is made using timer2 >> var byte tmrupd >> var dword tmrcnt >> var byte running >> const dword tmrmax =3D 5000000 >> >> T2CON =3D 0 >> T2CON_T2CKPS =3D 0 -- prescaler=3D1:1 >> T2CON_TOUTPS =3D 0 -- postscaler=3D1:1 >> T2CON_TMR2ON =3D 0 -- tmr2 off >> TMR2 =3D 0 -- tmr2, pre, post scalers clear >> PIR1_TMR2IF =3D 0 -- int flag clear >> PIE1_TMR2IE =3D 0 -- int off >> >> -- pulse counter is done using timer1 >> var byte cntupd >> var dword cntcnt >> const dword cntmax =3D 5000000 >> >> T1CON =3D 0 >> T1CON_TMR1CS =3D 1 -- use input from T1CKI >> ;T1CON_TMR1CS =3D 0 -- use input from internal clock >> ;T1CON_T1GINV =3D 0 -- gate active=3Dlow >> T1CON_TMR1GE =3D 0 -- tmr0 gate not used >> ;T1CON_T1OSCEN =3D 0 -- tmr1 osc not used >> T1CON_NT1SYNC =3D 1 -- do not synchronize sgnal to clock (inverted logic= ) >> T1CON_T1CKPS =3D 0 -- set prscaler (0:1, 1:2, 2:4, 3:8) >> T1CON_TMR1ON =3D 0 -- tmr1 off >> TMR1 =3D 0 -- clear timer >> PIR1_TMR1IF =3D 0 -- clear int flag >> PIE1_TMR1IE =3D 0 -- int off >> >> const byte tmrmsg0[] =3D "Start TMR: " >> const byte tmrmsg1[] =3D "Update TMR: " >> const byte tmrmsg2[] =3D "Finish TMR: " >> const byte cntmsg0[] =3D "Start CNT: " >> const byte cntmsg1[] =3D "Update CNT: " >> const byte cntmsg2[] =3D "Finish CNT: " >> const byte freqmsg0[] =3D "Freq: " >> >> INTCON_GIE =3D 1 -- enables all unmasked interrupts >> INTCON_PEIE =3D 1 -- enables all unmasked peripheral interrupts >> >> portA_direction =3D all_output >> portB_direction =3D all_output >> portC_direction =3D all_output >> >> alias led is pin_C3 >> pin_C3_direction =3D output >> >> pin_C0_direction =3D input >> >> var dword freq >> >> ------------------------------------------------------------------------= ------------------------ >> forever loop >> running =3D 0 >> cntcnt=3D0 >> cntupd=3D0 >> tmrcnt=3D0 >> tmrupd=3D0 >> ;print_string(serial_hw_data, tmrmsg0) >> ;print_dword_dec(serial_hw_data, tmrcnt) >> ;print_crlf(serial_hw_data) >> ;print_string(serial_hw_data, cntmsg0) >> ;print_dword_dec(serial_hw_data, cntcnt) >> ;print_crlf(serial_hw_data) >> TMR1 =3D 0 >> TMR2 =3D 0 >> ;while (pin_C0) loop end loop >> ;while (! pin_C0) loop end loop >> T1CON_TMR1ON =3D 1 -- tmr2 on >> T2CON_TMR2ON =3D 1 -- tmr2 on >> >> PIR1_TMR2IF =3D 0 -- int flag clear >> PIE1_TMR2IE =3D 1 -- int on >> PIR1_TMR1IF =3D 0 -- int flag clear >> PIE1_TMR1IE =3D 1 -- int on >> >> running =3D 1 >> >> led =3D on >> while (running =3D=3D 1) loop >> if (cntupd > 0) then >> cntcnt =3D cntcnt + 65536 >> cntupd =3D cntupd - 1 >> ; print_string(serial_hw_data, cntmsg1) >> ; print_dword_dec(serial_hw_data, cntcnt) >> ; print_crlf(serial_hw_data) >> end if >> if (tmrupd > 0) then >> tmrcnt =3D tmrcnt + 256 >> tmrupd =3D tmrupd - 1 >> ; print_string(serial_hw_data, tmrmsg1) >> ; print_dword_dec(serial_hw_data, tmrcnt) >> ; print_crlf(serial_hw_data) >> end if >> >> if (tmrcnt > tmrmax) then >> T1CON_TMR1ON =3D 0 -- tmr1 off >> T2CON_TMR2ON =3D 0 -- tmr2 off >> running =3D 0 >> elsif (cntcnt > cntmax) then >> T1CON_TMR1ON =3D 0 -- tmr1 off >> T2CON_TMR2ON =3D 0 -- tmr2 off >> running =3D 0 >> end if >> end loop >> led =3D off >> >> cntcnt =3D cntcnt + TMR1 >> tmrcnt =3D tmrcnt + TMR2 >> >> print_string(serial_hw_data, tmrmsg2) >> print_dword_dec(serial_hw_data, tmrcnt) >> print_crlf(serial_hw_data) >> print_string(serial_hw_data, cntmsg2) >> print_dword_dec(serial_hw_data, cntcnt) >> print_crlf(serial_hw_data) >> >> delay_1s(3) -- some delay >> print_crlf(serial_hw_data) >> >> end loop >> >> ------------------------------------------------------------------------= ------------------------ >> >> procedure ISR() is >> ; pragma interrupt fast >> pragma interrupt >> if PIR1_TMR2IF =3D=3D true then -- timeframe timer overflowed >> tmrupd =3D tmrupd+1 >> PIR1_TMR2IF =3D 0 >> end if >> if PIR1_TMR1IF =3D=3D true then -- pulse counter overflowed >> cntupd =3D cntupd+1 >> PIR1_TMR1IF =3D 0 >> end if >> end procedure >> >> >> >> >> >> -- >> KPL > > > > -- > KPL > > -- > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .