RTCC with SX/B help request on magneto/throttle project
![Ken Gracey](https://forums.parallax.com/uploads/userpics/937/nHX7GKXF8OR2S.jpg)
Hey SXers:
This is my first time attempting to use the SX's RTCC ISR. This portion of the·project consists of a Honda engine magneto connected to an SX, with a servo for throttle control. The goal is to control the throttle using a known RPM. The bigger project is that I've got an alternator connected to the engine for a high-powered robot power plant for over-the-snow travel. But·this is where I'm stuck.·The signals I'm dealing with look like this (servo on top, magneto on bottom):
![attachment.php?attachmentid=43493](http://forums.parallax.com/attachment.php?attachmentid=43493)
Every 20-50 ms I generate·the servo pulse, and meanwhile I'd like to be counting magneto pulses for 1 second. The scope capture above shows the engine in an idle state, so the pulse frequency increases with RPM. I'm able to control the servo and count pulses accurately, but putting these two tasks together is where I need some help. You can ignore the R/C circuit with the potentiometer - the purpose of that was to manually set the throttle so I could test the pieces of this project before I tried to put it all together.
This is my schematic:
![attachment.php?attachmentid=43494](http://forums.parallax.com/attachment.php?attachmentid=43494)
I created some psuedo-code which compiles, though·the use of PULSOUT in the interrupt routine·will wreck the timing. How can I incorporate the adjustment of a servo timing pulse·within the ISR?·It seems like I'd use the tix counter to adjust servo pulses.·Do I need to·make a relationship between ServoVal and tix variables, so that I use tix and HIGH/LOW Servo·in the ISR to control the servo? I·would benefit from a couple more hints.·Preliminary·psuedo-code is below, so you·can understand the·approach I'm trying to take.
'
' Throttle Feedback Control.SXB
' Magneto counting for Honda Engine / alternator coupling
' to set an RPM between two values
'
DEVICE········· SX28, OSCXT2, TURBO, STACKX, OPTIONX
FREQ··········· 4_000_000
'
' I/O Pins
'
Servo·········· PIN·RA.1· OUTPUT
Magneto········ PIN·RB.4· INPUT CMOS
RCCircuit······ PIN·RC.3· INPUT· ' not used in this code·
'
' Constants
'
HighThrottle··· CON·130
LowThrottle···· CON·190
'
' Variables
'
ServoVal······· VAR·Word
analog········· VAR·Word
RPM············ VAR·Word
MagnetoPulses·· VAR·Byte
tix············ VAR·Byte
'
· INTERRUPT 200
'
ISR_Start:
· INC tix······································ ' update tix counter
· IF tix = 10 THEN····························· ' every 50 ms
··· tix = 0
··· PULSOUT Servo, ServoVal
· ENDIF
ISR_Exit:
· RETURNINT·
' =========================================================================
· PROGRAM Start
' =========================================================================
Start:
· ServoVal = LowThrottle
CountRPMs:
· COUNT Magneto, 1000, MagnetoPulses
· RPM = MagnetoPulses * 60
· IF RPM <· 3000 THEN
··· ServoVal = ServoVal - 5 ················· ' increase throttle
··· IF RPM > 4000 THEN
··· ServoVal = ServoVal······················ ' hold throttle
····· IF RPM > 5000 THEN
····· ServoVal = ServoVal + 5················ ' decrease throttle
····· ENDIF
··· ENDIF
· ENDIF
GOTO CountRPMs
Thanks for any help ahead of time.·
Ken Gracey
Parallax, Inc. ·
Post Edited (Ken Gracey (Parallax)) : 10/6/2006 6:09:22 PM GMT
This is my first time attempting to use the SX's RTCC ISR. This portion of the·project consists of a Honda engine magneto connected to an SX, with a servo for throttle control. The goal is to control the throttle using a known RPM. The bigger project is that I've got an alternator connected to the engine for a high-powered robot power plant for over-the-snow travel. But·this is where I'm stuck.·The signals I'm dealing with look like this (servo on top, magneto on bottom):
Every 20-50 ms I generate·the servo pulse, and meanwhile I'd like to be counting magneto pulses for 1 second. The scope capture above shows the engine in an idle state, so the pulse frequency increases with RPM. I'm able to control the servo and count pulses accurately, but putting these two tasks together is where I need some help. You can ignore the R/C circuit with the potentiometer - the purpose of that was to manually set the throttle so I could test the pieces of this project before I tried to put it all together.
This is my schematic:
I created some psuedo-code which compiles, though·the use of PULSOUT in the interrupt routine·will wreck the timing. How can I incorporate the adjustment of a servo timing pulse·within the ISR?·It seems like I'd use the tix counter to adjust servo pulses.·Do I need to·make a relationship between ServoVal and tix variables, so that I use tix and HIGH/LOW Servo·in the ISR to control the servo? I·would benefit from a couple more hints.·Preliminary·psuedo-code is below, so you·can understand the·approach I'm trying to take.
'
' Throttle Feedback Control.SXB
' Magneto counting for Honda Engine / alternator coupling
' to set an RPM between two values
'
DEVICE········· SX28, OSCXT2, TURBO, STACKX, OPTIONX
FREQ··········· 4_000_000
'
' I/O Pins
'
Servo·········· PIN·RA.1· OUTPUT
Magneto········ PIN·RB.4· INPUT CMOS
RCCircuit······ PIN·RC.3· INPUT· ' not used in this code·
'
' Constants
'
HighThrottle··· CON·130
LowThrottle···· CON·190
'
' Variables
'
ServoVal······· VAR·Word
analog········· VAR·Word
RPM············ VAR·Word
MagnetoPulses·· VAR·Byte
tix············ VAR·Byte
'
· INTERRUPT 200
'
ISR_Start:
· INC tix······································ ' update tix counter
· IF tix = 10 THEN····························· ' every 50 ms
··· tix = 0
··· PULSOUT Servo, ServoVal
· ENDIF
ISR_Exit:
· RETURNINT·
' =========================================================================
· PROGRAM Start
' =========================================================================
Start:
· ServoVal = LowThrottle
CountRPMs:
· COUNT Magneto, 1000, MagnetoPulses
· RPM = MagnetoPulses * 60
· IF RPM <· 3000 THEN
··· ServoVal = ServoVal - 5 ················· ' increase throttle
··· IF RPM > 4000 THEN
··· ServoVal = ServoVal······················ ' hold throttle
····· IF RPM > 5000 THEN
····· ServoVal = ServoVal + 5················ ' decrease throttle
····· ENDIF
··· ENDIF
· ENDIF
GOTO CountRPMs
Thanks for any help ahead of time.·
Ken Gracey
Parallax, Inc. ·
Post Edited (Ken Gracey (Parallax)) : 10/6/2006 6:09:22 PM GMT
Comments
How fast can the magneto pulses be at maximum RPM ?
P.S. I hate to bring this up, but the SX48 could handle both of these functions using JUST the two hardware timers.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cheap used 4-digit LED display with driver IC·www.hc4led.com
Low power SD Data Logger www.sddatalogger.com
SX-Video Display Modules www.sxvm.com
Don't mistake experience for intelligence. And vis-vera.
·
The fastest magneto pulses I'm counting are 200 per second, and best I can tell I get two pulses per rotation. 200 x 60 / 2 = 6,000 rpm. Idle is around 50 pulses per second.
I forgot to say why I want RPM control. I've got a voltage regulator circuit which generates a known amount of current at different RPMs. I could come close to achieving what I want with an open-loop throttle, but since I've come this far. . .
I could use the SX48 Proto Board - not a problem especially if it makes the coding more practical. Sure.
Ken Gracey
Parallax, Inc.
Post Edited (Ken Gracey (Parallax)) : 10/6/2006 7:33:23 PM GMT
However, the COUNT function will not be precise for two reasons:
1) Time spent in the ISR does not count against your 1000 msecs timing interval. In your case the ISR time will vary with the width of the servo pulse. Worst case, on average around 4% of your time will be in the ISR, so this probably isn't a concern here.
2) If a magneto pulse happens during a servo pulse, it won't get counted. The COUNT function can't register a pulse unless it (and not the ISR) is running when the pulse happens. Since the magneto pulses can be shorter than the servo pulses, this is a definite possibility. Again, you may be able to convince yourself that missing a few pulses won't be a problem for this project.
If you decide you need to, you can solve both of these problems by coding the pulse counter yourself. You could add code to the ISR to set a bit flag once per second (every 200 executions of the ISR). WKPND_B.4 will be set every time there is a magneto pulse, independent of what code is running. You just have to clear it before the next pulse comes along. Create a loop that checks and clears WPKND_B.4, increments the count when it's set, and loops until the 1 second flag is set. When that happens, clear the 1 second flag and save the count.
There's a trick to using the WKPND_B register. WKPND_B = ByteVar will actually swap the value of ByteVar and the value of WKPND_B. So the the pulse counting code would be:
CountRPMS:
MagnetoPulses = 0
DO
Temp = 0
WKPND_B = Temp 'Temp gets the value of WKPND_B and WKPND_B is cleared and ready for the next pulse
IF Temp.4 = 1 THEN
INC MagnetoPulses
ENDIF
LOOP UNTIL OneSecondFlag = 1
OneSecondFlag = 0
'Update ServoVal here
GOTO CountRPMS
By the way, you'll probably want to force ServoVal to stay between LowThrottle and HighThrottle.
CountRPMS:
·· MagnetoPulses = 0
·· DO
····· Temp = 0
····· WKPND_B = Temp 'Temp gets the value of WKPND_B and WKPND_B is cleared and ready for the next pulse
····· IF Temp.4 = 1 THEN
········ INC MagnetoPulses
····· ENDIF
·· LOOP UNTIL OneSecondFlag = 1
·· OneSecondFlag = 0
·· 'Update ServoVal here
GOTO CountRPMS
· I would use RTCC to count the mag pulses. And update the servo in the program loop.
· This will work on the SX28 or SX48. And no messy interrupts are needed.
· Something like: [noparse][[/noparse]WARNING...UNTESTED CODE AHEAD!]
Bean.
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cheap used 4-digit LED display with driver IC·www.hc4led.com
Low power SD Data Logger www.sddatalogger.com
SX-Video Display Modules www.sxvm.com
Don't mistake experience for intelligence. And vis-vera.
·
Now wait just a minute...... there is nothing "messy" about interrupts. It permits you to do things exactly and deterministically. In fact, I bellieve it to be the ONLY way to code time related programs...... I would never stoop to using a "pause" (OK, perhaps a few NOPs for a few cycles) to wait for anything. With interrupts, (simple) multi-tasking is a breeze, and pre-emptive multi-tasking is very achievable in an SX28.
That said, with the exception of the PAUSE function, I do like what you have done with SX/B. You can get a lot done with only a little effort. It appears to be well respected for non time-critical applications, and has garnered quite a following. For real-time multi threading however, something more substantial is required employing those darned "ISR's", and that's the field where I like to "mess".
Keep up the good work.
Cheers,
Peter (pjv)
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cheap used 4-digit LED display with driver IC·www.hc4led.com
Low power SD Data Logger www.sddatalogger.com
SX-Video Display Modules www.sxvm.com
Don't mistake experience for intelligence. And vis-vera.
·
Interesting, your approach.
Where on the other hand, I never write a program without interrupts, even if it just returns..... it's a standard piece in my template. It becomes so second nature, and it really helps (me, at least) clarify the dissection of a software structure for any particular requirement.
Cheers,
Peter (pjv)
I agree. Time spent learning how to handle interrupts and communication between FG and BG code is time well spent. Perhaps the single strongest feature of the SX chips is the jitter free interrupt. I can treat the SX like a piece of dedicated hardware because the lack of jitter in the interrupt system allows me to have 100% deterministic response time.
In addition, by dividing tasks between FG and BG, I guarantee time critical code is executed. In one of my projects, I have an SX that communicates with a 68HC11. The SX polls the communications lines in the interrupt handler. Mind you, it doesn't block. It just checks the status and acts when the line has done what it is waiting for. By counting the duration of the code path in the 68HC11, I am able to set an RTCC interrupt rate in the SX that absolutely guarantees it will never miss a communication request by the 68HC11. There is no wondering if it's fast enough. I can prove that I am sampling the communication line at around 3X faster than the 68HC11 can toggle it. This allows my FG code to do whatever it needs with the data as it comes in because the interrupt will always catch the data and notify the FG when it is ready.
This has also given me a huge advantage in writing multi-threaded code for Windows. The lessons learned on how to synchronize communication between the FG and BG is just like synchronizing communication between threads in Windows. As a result, my multi-threaded Windows apps cruise along without running afoul of issues like race conditions because I learned how to deal with those (the hard way) writing assembly language code (using interrupts) on various micro platforms.
Thanks, PeterM
OT: Sort of
Ken,
What type of alternator are you using with the GX-35?
Is it a direct drive or are you using a pulley/chain arrangement?
Is the GX-35 electric start or pull?
Some Pics would be neat!
I've kept my daughter's motorized car she had when she was little, now 13. Was think about making a 'explorer' bot (probably just R/C for now) out of it.
Thanks,
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
tacho pulses are kinda asynchronous. Using an ISR to catch them, means that the ISR must be executetd often enough in order not to miss anya tacho pulse transition, so the ISR would act as a "fast poller" on the tacho input line. As the SX is faster than many oher controllers, this may, or may be not a problem.
Nevertheless, please don't forget another great SX feature: The "wake-up" capability of the port B inputs. What is called the "wake-up capability" is actually a endge-capture feature available on the port B inputs. You can configure each of them to capture a rising or falling input signal edge, using the WKPED_B configuration register. You may configure the individual port B inputs to issue an interrupt, or a wake-up event using the WKEN_B configuration register. But even without enabling interrupts/wakeups on port B transitions, you can always "read" the WKPND_B register to find out if the input has changed to the configured direction since the last read. Actually, you do an exchange between W and the WKPND_B registers, so the instruction sequence
mov w, #0
mode $09
mov !rb, w
copies the current status of the wakeup pending bits into w, and clears them for the next run.
This feature is especially handy when you have to deal with very short pulses. Let's assume that the pulses look like to this:
_______________-_______________-_____________
and you poll the input at times shown here:
____|____|____|____|____|____|____|____|____|____
So, you will miss all the low-high transitions, although you are polling the input faster than the pulse period.
The status of a WKPND_B register bit would look like this (assuming that it is cleared whenever it is read):
______________
____________----____________
i.e. it goes high on a rising input signal, and low again when it is read by the SX program, so you won't miss any input transition using this feature.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Greetings from Germany,
G
Thanks a bunch for the help. I'm going to do a bit more research on RTCC to see if it can achieve my goals. I'll put the tach pulses on the RTCC pin and deal with the servo in my main program. I need to see if this pin can be set to CMOS. This seems likea fairly light-duty approach compared to the edge detection tips from Guenther and Peter's encouragement to learn ISRs inside and out, but it's a small step in the right direction from my standpoint. I'll be working on this over the next day or two and will report back my findings.
Mike,
This is a direct coupling arrangement. I don't want to mess around with chains or pulleys due to safety, power loss, and general "junk" that I consider it in my system. Basically, this system is producing 15-20A without problem and the battery is acting like a giant capacitor in the project. This is the·power plant "test bed" I built, which·was only assembled to prove to myself that the concept is feasible. I've connected loads over 15A at 12V·and I can deliver this power for an hour and a half with this engine. I'll post the·whole entire project in·the "Projects" section of this forum once I get the SX to count magneto pulses. I'll post mechanical drawings, too.
Ken Gracey
Parallax, Inc.
I "THINK" I remember reading somewhere that the RTCC pin is schmitt trigger levels. So you may need to run the magneto pulse through a gate to "square it up" first. I'd try it straight in first.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cheap used 4-digit LED display with driver IC·www.hc4led.com
Low power SD Data Logger www.sddatalogger.com
SX-Video Display Modules www.sxvm.com
Don't mistake experience for intelligence. And vis-vera.
·
·
Just for interest I thought I would code up in assembler (my skills at SX/B are inadequate) what I think you are trying to do.
·
I believe your project is well served by a simple minded co-operative scheduler and state machines, so I thought it to be a good example to demonstrate those.
·
I have not followed your port bits and numbers scaling as I was not at my internet connection at the time I coded this, so I was going by memory as to what the concepts were, and that was what I implemented.
·
Essentially my example shows several concepts, and how to execute several independently timed concurrent routines "simultaneously":
·
1. use interrupt to time all events
2. read magneto pulses for one second
3. use port B change detection as per Guenther's example above
4. output servo pulses from 1 through 2 milliseconds duration
5. calculate throttle raise/lower requirements
·
A virtual A/D converter for a pot-adjusting RPM setpoint can be readily incorporated.
·
This particular implementation is not as concise as I would normally code it, as that would obscure some of the concepts for those who are trying to learn from these examples, and this version is only one of many ways to "skin this cat".
·
It's also interesting to note the difference in effort between an SX/B (your code rendering) and assembler. It took me about 3 hours to figure out what was needed, how to tackle it, write the code starting with my standard template, and another hour to debug it and run it with simulated inputs/outputs. Then it took me another two hours to edit the post so formatting was intact·for·making it·readable !
My scope verified proper operation of the servo pulse outputs, but using the imprecise internal R/C oscillator caused a little error in the timing. During "DEBUG", while the SX key was generating the clock, timing was perfect.
·
·
Anyhow do with it what you will, and I'd be happy to add the A/D or any other features you might desire.
·
Cheers,
·
Peter (pjv)
Post Edit:··· Well, it looks like my effort to retain the formatting is for naught! This is so difficult to read..... I really wish there was another way to make things easier.·I hope the attached copy is proper !
Post Edit: fixed missing literal indicator (#) in "MagnetoExit" line.
Cheers,
·Peter (pjv)
Post Edited (pjv) : 10/10/2006 3:39:31 PM GMT
You might want to take a look at:
http://www.piclist.com/images/boards/Injector-JAW/index.htm which does injector control for a motorcycle engine. The code is for the PIC, but it can be converted.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
---
James Newton, Host of SXList.com
james at sxlist,com 1-619-652-0593 fax:1-208-279-8767
SX FAQ / Code / Tutorials / Documentation:
http://www.sxlist.com Pick faster!
This is fantastic. I'm spending some time studying the code example before I reply in detail to make sure I've got a basic grasp of the concepts. I'll be at home on Tuesday evening, and should be able to run it as early as Wednesday morning. I truly appreciate the help and look forward to reporting back with results! Thanks again!
You guys have tons of solutions for me!
Sincerely,
Ken Gracey
Parallax, Inc.
That's a pretty sweet setup! Looks like you work in aluminum like I do in MDF. Wish my home built CNC router would cut aluminum, probably will but will have to make MANY passes, need to try one day. Hope to see this in the 'Projects' section soon, you've sparked my interest!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
I spotted an error in my code; a missing literal indicator (#) in the "MagnetoExit" line. Eventhough it ran fine in my trial, it might have screwed up later if you added more features.
I have "post-fixed" this.
Cheers,
Peter (pjv)
Your power generator looks great! It is a work of art. I would enjoy reading a full article on the project.
I suspect that your battery is closer to 10 Ahr rather than the 10 mAhr noted in the schematic of the LM723 voltage regulator.
Are you planning on taking the next step and replacing the LM723 with the SX for regulation of the field current? In theory it should be rather simple.
Just keep the voltage divider read the voltage with the SX. Replace the 2N3055 with a logic level MOSFET controlled with the SX (buffer with an ICL7667 style MOSFET driver if you want very fast edges) and PWM the field coil. A loop update rate of 100Hz to 200Hz should be plenty.
In addition being cool and reducing the parts count, you would also get more run time. You would save the power lost due to the base current of the 2N3055 as well as the associated I*Vce losses. You might even be able to eliminate the 16 ohm resistor in series with the field coil for additional power savings.
You might want to throw in a one-wire temperature sensor to make sure the alternator is not getting to hot at full load.
I also wanted to throw in with Guenther. The best way to accurately count short events is to use an interrupt on level change (edge). Otherwise you are guaranteed to eventually miss events unless your time between samples is shorter than the minimum event duration.
Congratulations again on such a well designed project. I look forward to reading more about the design and build.
-Shane