Dmitry Kiryashov [zews at AHA.RU] says
Brief explanation. You are to run 10 tasks "simultaneously". 4 of them are counting pulses (or reading some buses if you would like to ;) while 6 others are some timing, converting information, sending and receiving RS232 stuff. Each slice of code has some execution time t1,t2,t3,... You can run everything in straight way in one loop when one follows by another but you will got total loop execution time exactly equal to t1+t2+t3+...+t9+t10 which is enormously huge ;) Forgot to mention that those pulses of course are longer than 10 sampling periods.
But you can reduce it significantly if will run each task separately in different time slots. Timer constantly generates required slots. Two different types of processes: constant rate happened and floating. Sampling ports and doing RS232 for instance are constant rate processes. Those should be sampled by every pass but finding edges can be scheduled for later. To reduce total time you also need to do finding edges in parallel for all 4 port pins. So you are just collecting information for analyzing it in later time. Total execution time in this case of every loop is no more than tC+tMAX where tC is time for driving/reading constant rate part of all process and tMAX is maximal execution time of longest process. Average execution time is reduced anyway. So applying this trick with accumulating first and executing later you can either do it faster or move this part of code into timer driven interrupt and forget about it (it becomes to be transparent and you don't care about low level programming anymore just playing with flags, buffers and semaphores on "high" level of art ;))
XORing the new value with the previous value yields a mask for all the changed bits. ANDing the result of that with the old value yields 1s for all the falling edges, and ANDing with the new value yields 1s for all the rising edges. These falling and rising edge masks can be accumulated by ORing them with previous versions if that's what you want to do.
Anding that mask with inverted current bit also produces falling flag. It's very easy to check. So you need to store only one variable (last one) and being exchanging it with a new one will have flags the same time.
I've been asked to design some trick to reduce code execution time for rise and fall edge events on some port pins. For instance we have two samples, previous byte x0 and current byte x1. Each holds inside value like aAbBcCdD. As a result of playing with vetical math I realized that:a) (x0^x1)&x1 = X0&x1 , which is "1" in case of rise event only b) (X0^X1)&X1 = x0&X1 , which is "1" in case of fall event only
where X0=!x0, Y0=!y0
Example:;... ;W holds 00ab00cd movwf temp ;save it for iorlw 0x55 ;future usage addwf temp,W ;get aAbBcCdD xorwf prev,W ;put x1 byte to prev xorwf prev,F ;get x0^x1 byte into W andwf prev,W ;get edges a) and b) iorwf edges,F ;detected edges ;...
We will get "rises detected" flags in 188.8.131.52. (case a) and "falls detected" flags in 184.108.40.206 (case b)
For instance edge can have a place somewhere within 10 samples period, so instead of reading and analizing it each time you can just accumulate it 10 times in edges cell and then analize it only ones. (don't forget to reset edges flags after that ;) Some clock saving anyway ;)
Probably someone can see another useful features of applying aAbBcCdD view of 4 bits variable.
How to convert 00ab00cd into aAbBcCdD? Bob Ammerman [RAMMERMAN at PRODIGY.NET] from RAm Systems says:
How about this:00ab00cd +00100010 --------------- 0aAb0cCd &01010101 ---------------- 0a0b0c0d +01010101 ---------------- aAbBcCdD
so, in code:ADDLW B'00100010' ANDLW B'01010101' ADDLW B'01010101'
Dmitry Kiryashov [zews at AHA.RU] says
I got the same in two variations for pure W usage (without additional temp cell) and another one with temp cell usage.
2nd variation is:addlw 0x66 ;00ab00cd -> aAAbcCCd andlw 0xDD ;-> aA0bcC0d addlw 0x11 ;-> aAbBcCdD
And with temp cell:movwf temp ;00ab00cd iorlw 0x55 ;01a101c1 addwf temp,W ;aAbBcCdD
Last one is useful for storing original W for futher usage.
I am involved in using PIC 18F458 on a buggy. Attached to the rear wheel are optical encoders used to measure the speed.
I would please like to find out whether there are any resources on using the CCP (Capture/Compare/PWM) module to capture every rising edge from the encoder and also have 1 second time intervals to determine the speed (RPM).
Is this the most efficient way to determine the speed of the buggy at any particular instance in time or is there a more efficient way?
Thanks in advance
Christo Pelster of Pelster Says:
The Edge Detection decribed in the example above works fine. It may ben oted that the initial state in prev needs to contain the actual initial state. If one for example want to detect edges on a port with a pushbutton to ground (low-true), then the initial state needs to be set up to "1" (true). If this is not done, the code will result in a incorrect rising edge detection when it executes the first time. This is quite likely, as one ussually clears all varaibles used upon program startup and before executing the edge detection routine.+
|file: /Techref/microchip/edgedetect.htm, 6KB, , updated: 2009/12/26 22:24, local time: 2020/2/18 06:36,
|©2020 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?|
<A HREF="http://techref.massmind.org/techref/microchip/edgedetect.htm"> Detecting riseing and falling edge events</A>
|Did you find what you needed?|
Welcome to massmind.org!
Welcome to techref.massmind.org!