Noticable flickering on multiple 7 segment displays because of PULSIN?
Here is what i am attempting....
I am wanting to have a set of 7 segment displays to show my current RPM on my car. I am using an RPM function that i found on here and now I am trying to get it to show the RPM on the displays. Everything works except there is a VERY noticeable flicker on the displays. Can anyone help me on how to remove this flicker?
I am wanting to have a set of 7 segment displays to show my current RPM on my car. I am using an RPM function that i found on here and now I am trying to get it to show the RPM on the displays. Everything works except there is a VERY noticeable flicker on the displays. Can anyone help me on how to remove this flicker?
RPM_signal PIN RC.0 TRIS_disp VAR TRIS_B rpm VAR WORD pWidth0 VAR WORD pWidth1 VAR WORD dividendMSW VAR WORD dividendLSW VAR WORD overflow VAR BIT doneBit VAR BIT display VAR RB digit VAR WORD digit1 VAR WORD b1 VAR WORD PROGRAM Start PUT_DIGIT SUB 2 getrpm FUNC 3, 0 Start: TRIS_disp = %00000000 Main: rpm = getrpm display = PUT_DIGIT rpm GOTO Main PUT_DIGIT: b1 = __WPARAM12 LOW RA.1 digit1 = b1 / 10 digit = __REMAINDER READ SegMap + digit, display pause 5 HIGH RA.1 LOW RA.2 digit1 = digit1 / 10 digit = __REMAINDER READ SegMap + digit, display pause 5 HIGH RA.2 LOW RA.3 digit1 = digit1 / 10 digit = __REMAINDER READ SegMap + digit, display pause 5 HIGH RA.3 RETURN getrpm: PULSIN RPM_signal, 0, pWidth0 PULSIN RPM_signal, 1, pWidth1 pWidth0 = pWidth0 + pWidth1 dividendMSW = $005B dividendLSW = $8D80 rpm = 1 overflow = 0 DO doneBit = rpm.15 rpm = rpm << 1 IF overflow = 1 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ELSE IF dividendMSW >= pWidth0 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ENDIF ENDIF overflow = dividendMSW.15 dividendMSW = dividendMSW << 1 dividendMSW.0 = dividendLSW.15 dividendLSW = dividendLSW << 1 LOOP UNTIL doneBit = 1 rpm = rpm << 1 rpm.0 = overflow IF dividendMSW >= pWidth0 THEN rpm.0 = 1 ENDIF RETURN rpm ENDFUNC
Comments
Using the original program you posted (without interrupts) this code will update the RPM value about once a second:
Main:
· rpm = getrpm
· FOR cnt = 1 TO 60
··· PUT_DIGIT rpm
· NEXT
· display = 0 ' Blank display while getting new RPM value
· GOTO Main
You will still get a flicker, but it will only be once a second. You could change the "60" value in the FOR line to adjust the update/flicker rate.
P.S. You should NOT be assigning PUT_DIGIT to the variable display as you are in the line "display = PUT_DIGIT rpm". Just use "PUT_DIGIT rpm".
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"A government big enough to give you everything you want, is big enough to take away everything you·have."·· Thomas Jefferson
"It is our choices, Harry, that show what we truly are, far more than our abilities."·Dumbledore from Harry Potter
www.iElectronicDesigns.com
·
The example in the help file for COUNT provides a good understanding of how to use the command.
COUNT RPM_signal, 1000, revolutions
I am using 'revolutions' in the statement as a variable.
The 1000 in the COUNT command represents 1 second (1000 milliseconds) of timing to give you the revolutions in one second. This is something I am sure you know, but I wanted to state it none-the-less. This value can be changed to 500 (milliseconds), thus the revolutions measured is for one-half second. Or use a count value of 250 for one-fourth second. A multiplier would then be needed to get the desired value for true rpm. For example, RPM = REVOLUTIONS * 60
I hope this provides some help. Or maybe I am way off of what you are after in using the COUNT command.
Gary
[noparse][[/noparse]post edited for clarity for conversion to revolutions per minute]
Post Edited (Sens-a-Dat) : 7/8/2008 1:22:18 PM GMT
[noparse][[/noparse]Edit] I've attached a program that shows you how to simulate PULSIN with custom functions that use the ISR timing. Put your display multiplexing code in the ISR -- everything else goes OUTSIDE (you want the ISR to run as swiftly as possible).
Post Edited (JonnyMac) : 7/8/2008 5:16:31 AM GMT
JonnyMac is right. It will definitely take some time to learn how to do this no matter what approach you use. However, it is a worthwhile goal.
Bean's suggestion is easier to implement but you have stated that even occasional flicker is unacceptable.
Sens-a-Dat might be on to an alternative concept, though I expect that the COUNT command will take too much time to complete (although fixed) thus creating noticeable flicker as well.
I will offer you another alternative concept but will not actually solve the particulars for you in this post. Consider running just the display update routine for a moment. It sounds like you will then have a nice, flicker-free display running if you do this. That should work but you need to read data and perform some calculations. If only you did not have to "interrupt" this routine to obtain and process new input data you would have a sweet RPM display for your car that you built yourself. Well, maybe you can still achieve that goal!
I noticed that in your original display update code you have three sections where you pause for 5ms. What is the SX doing during that time? It is doing nothing useful except counting down the time!
If you can figure out a way check your input pin state and perform some calculations based on that state in less than the 5ms wait period you can do both without disrupting your display. Do you think you can do that?
The big drawback to what I have just proposed is in the lack of timing accuracy. As written you will not have a very accurate sense of how much time it takes to execute the primary loop each time. It is possible the difference will be small enough to disregard.
If the timing errors from this approach are too significant you will have two corrective options. One way to correct for this is to write the code for the loop so that each possible path variation takes the exact same amount of time to complete. This is not trivial but for your tasks should not be extremely difficult. The other way to correct for time invariance is to use interrupts. (There is that interrupt option again!) However, if you can accomplish the above then calling a display update routine once every 5ms while cycling between the three digits of the display will not seem too difficult.
Really, there are many options. You will learn a lot by trying out more than one. The reality is that trying to have the two time dependent tasks you want to have working together is going to require some careful thought and planning. It can most certainly be done but it is going to require a bit of effort.
Let us know how you choose to proceed.
- Sparks
Basically you would setup RTCC to count from external input using "OPTION = %1111_1000"
Then clear the counter by using "RTCC = 0"
Then update the display for 1 second (you might have to adjust the PAUSE value to get this as close as possible).
Then do "rpm = RTCC" and "rpm = rpm * 60"
That is how I would do it...
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"A government big enough to give you everything you want, is big enough to take away everything you·have."·· Thomas Jefferson
"It is our choices, Harry, that show what we truly are, far more than our abilities."·Dumbledore from Harry Potter
www.iElectronicDesigns.com
·
Then of course there is the assembler approach using multi tasking scheduler approach. No external hardware required, all the multiplexing speed you want -ie no observable flicker- and as precise as you need.
However, it is adifferent approach, and much more work..... and tons of fun learning.
Cheers,
Peter (pjv)
I'd love to see more examples of your scheduler approach. While it intuitively makes sense to me, I have yet to wrap me head around it enough to be able to use that technique in my own programs.
I've attached a program that does what you want; it uses your math and my original suggestion to use the interrupt for timing and display multiplexing. I've added some traps for low (< 91) and high (> 9999) rpm values. I have this running on a PDB, you may need to adapt for your needs.
As a result of the theft of my laptop with all my SX assembler projects on it, I've been forced to rewite my current project because my backup was several months out of date. Lesson learned.
So I'm rewriting it in SX/B, and I'm having a blast! Normally I would not have entertained such an approach as gnerally I have a serious need for muti-tasking, and that is something SX/B is terrible at. That said, this particular project manages to get by pretty well with a single thread, soI thought to have a go. As I'm learnng SX/B, I'm finding my efficiency in recreating the code to be very high compared to the assembler approach.... somewhere in the 2 to 4 to one range.... realizing of course I'm re-using the algorithms and structure developed previously.
What I would love to see, is a modified SX/B that can be truly multi-tasking....getting rid of those ugly PAUSEUS and delay statements that cause indeterminism and timing interactions between code segments. And as I learn SX/B I'm seeing the sheer convenience, power and elegance of it...I'm truly marveled by it's simplicity.
A job well done Bean!
So, after I expect to finish my rewrite over the next several months, I suggest a few of us meet at some convenient place and time to see if it's possible to make the modifications to SX/B for achieving that end. I'd be happy to fly to Parallax if they would be willing to offer their facility.
Anybody game??
Cheers,
Peter (pjv)
Post Edited (pjv) : 7/9/2008 3:56:11 AM GMT
I can assure you that the program works. It uses four, common-cathode 7-segment displays. The segment mapping is laid out in the digit tables section. If you get the connections right and the program properly downloaded you should see something on the displays.
VAL_TO_ARRAY rpm, @digits(0)
... the 2.0 compiler doesn't need the zero index. I've reloaded the 1.51.03 compiler and it works fine with this change.
Since you're serious about SX development get yourself a hand full of resonators from Parallax, and an SX-Key (not the Blitz).
Post Edited (JonnyMac) : 7/9/2008 5:39:54 AM GMT
Since you're building a custom circuit and asking for help, you should draw your schematic -- that will help forum members help you. If you don't have it, download ExpressPCB and use their schematic editor; it takes about 5 minutes to learn and produces nice, clean output.
[noparse][[/noparse]Edit] I just downloaded your program, and after filling in the information you didn't provide, find that it runs on my hardware. The only difference is that your ones digit is offset by one in my display as you're using RA.1. My program uses four digits with RA.0 controlling the ones. Still, unless you've changed my code, you should see my program running on your hardware. I do sincerely hope you're able to sort it all out.
Post Edited (JonnyMac) : 7/9/2008 5:08:04 PM GMT