PDA

View Full Version : Unwanted output signal jitter



LinkMTech
- 3rd January 2008, 21:31
Hello everyone,
First of all, thank you all for sharing your time and wisdom so others can excel.

I'm making a fuel injection circuit using the PIC16F737 that would allow me to control the outputs ON/OFF +/-. After gleaning the data specs on my part for understanding and researching this forum to get me this far plus experimentally trying different ideas, I hoped that an expert would be able to spot why I'm experiencing this unwanted signal jitter.
Attached are:
1. Copy of sample code working just one input. You'll notice that the ADC settings are not the usual settings but were left this way because I got a nicer response from the pot control. This might also be the band aid to the problem.

2. Scope screen shot of ouput signal with ON time delayed and with unwanted jitter at opposite end. If I turn the pot CCW from center, the output turn ON delay is increased from 0 to 500us.

3. Scope screen shot of ouput signal with OFF time delayed and with unwanted jitter at opposite end. If I turn the pot CW from center, the output turn OFF delay is increased from 0 to 500us.
The top trace (Yellow) is the input, bottom trace (Blue) is the output.

Input signal is 5V with 2.5ms LOW pulse and 20K pull up, pot is a 5K from 5V to GND. Output driving a current limited LED at the moment.

skimask
- 3rd January 2008, 22:05
Hello everyone,
2. Scope screen shot of ouput signal with ON time delayed and with unwanted jitter at opposite end. If I turn the pot CCW from center, the output turn ON delay is increased from 0 to 500us.
3. Scope screen shot of ouput signal with OFF time delayed and with unwanted jitter at opposite end. If I turn the pot CW from center, the output turn OFF delay is increased from 0 to 500us.
The top trace (Yellow) is the input, bottom trace (Blue) is the output.
Input signal is 5V with 2.5ms LOW pulse and 20K pull up, pot is a 5K from 5V to GND. Output driving a current limited LED at the moment.

At first glance, your loops take different paths at different times, therefore, different numbers of instruction cycles. Look at your .lst file, count them up for the different if/then possibilities. You might need to throw a @nop in here or there to keep the timing correct.
Your 'jitter' is 500ns, which happens to be one instruction cycle at 8Mhz (2Mhz instruction rate). Which also happens to be the difference between a NOP (one cycle) and a GOTO (2 cycles).

mister_e
- 3rd January 2008, 22:10
euhh 500 uSec Skimask, which is way over a NOP or GOTO ;)

skimask
- 4th January 2008, 01:42
euhh 500 uSec Skimask, which is way over a NOP or GOTO ;)

Yep, sure is...but that u looked so much like an n.
...unless the PIC is running at 8Khz

LinkMTech
- 4th January 2008, 03:01
Yep, sure is...but that u looked so much like an n.
...unless the PIC is running at 8Khz

I'm glad I'm not the only one that sees things!

LinkMTech
- 4th January 2008, 03:35
Just remembered something about the jitter...
If I commented the ADCIN command from the internal loop and just relied on the initial ADCIN read at the start of the program, the variable adjustment wouldn't work of course but be fixed at the pot setting instead and would get a clean output signal.
I read through the ADC section of the data specs that specified Rs be less than 10K, my pot is 5K and left me thinking the sampling time has to be set correctly.
Am I getting close or still wandering in the dark with a LED on a 2V battery?

skimask
- 4th January 2008, 04:00
[QUOTE=LinkMTech;48591]A couple of thoughts...



CLRW ' Clear all registers<<<-----CLRW works with PBP?

ADCON1 = %00000000 '<<<---What's the default 'JUSTIFY' on a 16F737?

DEFINE ADC_BITS 5 <<<<---Why not use all 8 bits?
-------and the manual says only 8,10,12... I don't see 5 as a legal value

Low_Adj var byte ' Input declared as byte size <<<-- You might want WORD here
Low_set var word ' Input declared as byte size <<<<- it is? :)

Low_set = (abs(low_adj-128))*8 <<<<---these lines look a bit scary to me

That last one...
If you get a value above 32, when multiplied by 8 will overflow a byte variable. Low_set is a word, but low_adj isn't. I seem to have bad luck when mixing variable sizes like that. But that's just me...
I think the ADC_BITS might be your killer. Keep it at 8 bits, AND out the low 3 bits, and shift it down by 3 bits.

EDIT: Notice I changed OR to AND. My mistake..duhhhh...

LinkMTech
- 4th January 2008, 06:06
Thanks for the info Skimask.
Yeah, some of my comments are left overs from the different attempts to feel my way through when thinking got too hard. Now I've got something else to study "Default Justify".
I implemented all your suggestions except that one until I know what I'm doing.

Thanks again,
You guys rock!

b1arrk5
- 5th January 2008, 00:15
This is just a guess, but the adc has to charge it's capacitor for each read, I'm wondering if you're doing the ADCIN commands too fast to allow it to fully charge between readings. You are using the R/C timer in the ADC, and the sampling time is set to 20us. I usually set it for 50us, and use a little delay between successive readings.

Good Luck!

Jerry.

LinkMTech
- 5th January 2008, 06:27
I've been doing some more digging using Darrel Taylor's upgrade to the search engine: http://www.picbasic.co.uk/forum/showthread.php?t=4751
and found a nice description of another way to use A/D instead of ADCIN from Melanie that I am also going to try: http://www.picbasic.co.uk/forum/archive/index.php/t-352.html

I remember increasing the sample time to 100us before and maybe even more but it didn't make a difference. I'm sure if it's not configured right in the first place it wouldn't even matter! Man, am I glad that these devices are made to handle the all the flashing I can muster up.
One thing that's really bugging me, for lack of understanding, is that I have to keep the pot variable "Low_set" in the FOR/NEXT loop or else it won't give me the adjustable output. I thought that declaring Low_set = (ABS(low_adj-128))*8 once before going into the loop would be enough and that occasionally opening the door to let the flies in with ADCIN to update the variable "Low_set" would do the trick. BUT NOOO!!! I got the one read and it stayed fixed at that setting no matter how many flies I let in.



Low_Add_pulse:
IF low_adj<=127 THEN GOTO Low_Trim_pulse ' Check pot position and go
FOR x = 1 to 10 ' Count to 10
FOR i = 1 to 100 ' Count to 100
IF Sig1=1 then ' Input OFF then:
PAUSEUS low_set ' Adjustable delay using pot
LOW Inj1 ' Turn OFF output
ENDIF
IF Sig1=0 THEN HIGH Inj1 ' Output ON if input ON
NEXT i
ADCIN 1, low_adj ' Check pot after a 100 loops
' for smooth adjustment
NEXT x
Low_set = (ABS(low_adj-128))*8 ' Declare every 1000 loops or
' adjustment not possible

GOTO Low_Add_pulse ' Do it again

I gotta believe that it's possible to do what I'm trying to do. The tired part of me says "just show me how to do it!" but the bigger part thanks you guys for the clues and direction so I can learn to be a confident PBP programming dude.

Thanks

skimask
- 5th January 2008, 07:27
Maybe I'm missing the point here...
What are you trying to accomplish?
You have a pulse from 'Something A' going to 'Something B', and you want to build a programmable delay, not to change the pulse width, but to delay the pulse itself by X time? Like a time shift or something?
What's this for? Ignition timing or injector timing?

LinkMTech
- 5th January 2008, 08:04
Hi skimask,
I'm putting this circuit between the motorcycle's ECU and fuel injectors. You may already know how they work but just for clarification; the ECU will pull the injector low for about 2.5ms and it's pulse width will vary about 8%. I want to to able to expand that to about +/- 20% within three RPM ranges along with some other fancy hoop jumping.
The -20% control will delay the ON time of the output signal to the injector but supposed to keep the OFF time unchanged for reduced pulse width.
The +20% control should keep the ON time intact but delays the OFF time of the output signal for increased pulse width.
I tried PULSIN, that will never do. Especially at 14K RPM where I will have to deal with input signal overlapping!
I tried PULSOUT, looked promising, if I was helping an old lady across the street, but that got nasty looking with all the looping and checking I had going.
So dealing with the signal as it happens seems to be the right direction if only for the jitter at the opposite end!

skimask
- 5th January 2008, 08:27
the ECU will pull the injector low for about 2.5ms and it's pulse width will vary about 8%
On all of the fuel injectors I've ever put a 'scope on, the pulse varies a heck of a lot more than 8%. I'd even venture to say that any injector's pulse width would vary 8% at a steady state just to keep the closed loop program in the ECM happy. It's possible this bike has something else going on that keeps the fuel injector pulse practically steady, but I tell ya, that's something I haven't heard of lately.


The -20% control will delay the ON time of the output signal to the injector but supposed to keep the OFF time unchanged for reduced pulse width.
The +20% control should keep the ON time intact but delays the OFF time of the output signal for increased pulse width.
If it was me, I don't think I'd delay the start of the pulse. If you delay the pulse width at the start, the fuel might not be there in time for the intake valve to open. Remember, it takes X amount of time for an injector to open and start spraying that nice cone shape properly, whereas the closing an injector is much more of a solid event, at least that's what I've seen from the high speed video from one of my relatives at GM (neat video too, can see practically every tiny little droplet of atomized fuel in the spray pattern). I think I would shorten up the tail end of the pulse. If anything, at least the fuel will be sitting there on the intake valve or at least in the intake stream, ready to be sucked in, even if it is pooled up on the intake valve, which in any halfway decently designed intake system, will get swirled up and re-atomized by the swirl and heat of the valve.

But, be all that as it may be, it's nearly impossible to determine what the ECM will determine should be the NEXT pulse width. If it was me, I think I'd try a system that would LAG by one pulse event. Keep tabs on the previous pulse, modify that pulse width, shoot that pulse width on the next event, while at the same time, using a timer, measuring the current pulse width, while again, using a timer, to keep track of the current pulse width and stop it as required.
But then again, as fast as today's ECMs operate, it may (and probably will) still flag a failure and go to open loop, because you're messing with the pulse width, thereby the air/fuel ratio, which the ECM will eventually see in the O2 sensor. Unless, you plan on running open loop continuously...which in that case...never mind...Go for it! Just remember that a stoich A/F ratio of 14.7:1 with 20% of the fuel removed is an A/F ratio of about 17.6:1...lean enough to make donuts out of piston heads and make sticks out of exhaust valves and instantly put ports in your otherwise smooth cylinder walls!

LinkMTech
- 5th January 2008, 20:52
But, be all that as it may be, it's nearly impossible to determine what the ECM will determine should be the NEXT pulse width. If it was me, I think I'd try a system that would LAG by one pulse event. Keep tabs on the previous pulse, modify that pulse width, shoot that pulse width on the next event, while at the same time, using a timer, measuring the current pulse width, while again, using a timer, to keep track of the current pulse width and stop it as required.

That was my initial thought too! But since I'm just coming out of the starting gate, I didn't know how that would be possible without a crystal ball. Thanks to some info I found on slick ways of using timers by DT, you're right, I think I will drop the notion of delaying the start of the pulse and keep tabs of the previous pulse to work off that.
This circuit will not be used blindly but in a monitored state on a dyno and is only the basis of the system. I know there are products out there for this but then there are also more than one type of shoes too.
Thanks for the confirmation!

skimask
- 6th January 2008, 06:23
This circuit will not be used blindly but in a monitored state on a dyno and is only the basis of the system.

I guess my big question is...why do you want to mess with the pulse width anyways?
Are you adding on some crazy turbo, tuned pipe type things or what?
I mean, closed loop is closed loop is closed loop. It's efficient, clean, keeps parts where they're supposed to be, etc.etc.etc. (and again I don't what kind of system you're dealing with).
Now...WOT is another story... Are you looking to basically 'bypass the rom' in the ECM and feed more fuel under WOT/open-loop conditions?

LinkMTech
- 6th January 2008, 19:25
I guess my big question is...why do you want to mess with the pulse width anyways?
Are you adding on some crazy turbo, tuned pipe type things or what?
Most street bikes (not all) do not currently use an O2 sensor, so minor adjustments to the fuel delivery are possible and needed in different parts of the RPM range when aftermarket upgrades are installed and will help smooth out the power delivery. You'd be surprised how much a little improvement feels "at the seat of the pants" to the rider. Maybe you already know.
Now the +/-20% range is adjustable and will probably never see 20% and may be reduced to some narrower range in the end, but until then, I'm starting at +/-20%.

Now since I'm taking your advice to sample the leading pulse to configure the next pulse out, I downloaded Mr. DT's Instant Interupt-14 super duper program template and aww man, all I could do was look straight up! You guys are in the zone to understand this stuff. But if I'm gonna eat that elephant, it'll be one byte at a time.
Quick question,... will I need to have a PIC device with 4 timers to be able to trigger off 4 inputs to "sample one, build the next"?

Thanks

b1arrk5
- 6th January 2008, 23:14
In keeping with my philosophy of keeping it simple, how about this idea, dump the ADC altogether, and use the CCP input to read the signal pulse duration. Bruce has posted an example how to do it using Darrel's Instant Interrupts. Instead of a pot to adjust, just read two buttons, up and down. I think you could get far greater resolution than you will turning a pot, and you could read the buttons using interrupts, or watch them in a loop. Wouldn't the four input signals, and the four injector pulses be pretty much identical for each revolution? I wonder if you could just read one or two input pulses on each revolution, and make all the outputs identical. Given the mass of the pistons and the fact that they are connected to the same crankshaft I'd be surprised if there needs to be a great variance between cylinders on a single revolution. If you can assume that the input signals and output signals would be identical that makes you job a lot easier, one timer would do it. I'm thinking that having an up and down button would allow a rider to make adjustments on the track, not just on a dyno, it would be hard to tweak a pot while sitting on a bike at speed, and eventually you will likely want to get this on the road I imagine. Your software could adjust the range of adjustment based upon the rpms of the engine, so at higher rpms you couldn't make a drastic change if you held a button too long, but at lower rpms holding the button could make a faster (greater percentage) change.

Jerry.

b1arrk5
- 6th January 2008, 23:16
I found the link I was thinking of;
http://www.picbasic.co.uk/forum/showthread.php?t=7507&highlight=interrupt+capture
this shows Bruce's example for reading the pulse width.

Jerry.

LinkMTech
- 7th January 2008, 01:50
It's been a long day, my eyes hurt from all the reading...
Making all the outputs the same on a pass makes capitol sense. Then update with the gathered timer info next time around. I'm all for simple as soon as I get some speed on this learning curve.
The adjustments will be almost a one time setting until the bike gets upgraded again or has to be readjusted on track day at the track due to temp., elevation, and things like that. But one thing for sure, can't have the rider racing one handed except for cruel entertainment pleasure on the spectators part.
Thanks for the added info b1arrk5. I will study it and try it out.

skimask
- 7th January 2008, 02:58
Now the +/-20% range is adjustable and will probably never see 20% and may be reduced to some narrower range in the end, but until then, I'm starting at +/-20%.
If I was you, I'd kill that 20% idea and stick with something less, like maybe 5%. Like I said earlier, 20% is the difference between stoich and melted pistons, especially at high rev's, heck 20% is the difference between slobbering rich (say 12.5:1) and the lean side of detonation (12.5:1 - 20% = 15:1).


will I need to have a PIC device with 4 timers to be able to trigger off 4 inputs to "sample one, build the next"?
One timer, keep track for 4 start/end value pairs, do the subtraction math on the pairs to find time differences.


In keeping with my philosophy of keeping it simple...
Jerry.
I agree 100%+ with every one of those comments...and with that agreement and $1.25, you might be able to buy a bottle of Dew! :D
But seriously, dead on, let the hardware do the work for you.

LinkMTech
- 18th January 2008, 02:31
Okay, I took most of your advices and got to this point where I am sampling one signal to construct another and is working very nice and smooth without any jitter (which I also realized why it was happening in the first place).
Here is the working portion of the code I would like to use TMR1 in so that I can measure time between occurrances if possible:


Third:


PULSIN Sig3,0,S1 ' Monitor for and measure Sig3
ADCIN 1, Low_pot ' Read Low Pot setting
Low_adj = ABS(Low_pot-128) ' Make pot adjustable from center

IF Low_pot <128 then ' If pot on left side then make
Low_set= S1-(S1/(AR/Low_adj)) ' negative adjustment
ENDIF

IF Low_pot >=128 then ' If pot on right side then make
Low_set= S1+(S1/(AR/Low_adj)) ' positive adjustment
ENDIF

WHILE sig2=1: WEND ' Wait for trigger signal
PULSOUT Inj2, Low_set ' Send output pulse =% of Sig3
' input signal
GOTO Third


This is my understanding of a way to use the TMR1; Wait for something to occur then set the CAPTURE flag (PIR1.2 in this case) and read the high and low timer bits, clear the flag. Wait for something else to occur and read the high and low timer bits again, clear the flag and get the difference of the two timer values for time elapsed! Seemed simple enough but if it worked I would not be asking for direction. So the question here, can the TMR be software controlled like I'm trying to do or am I restricted to rely on the CCP1 input pin for triggering?


Third:

TMR1H = 0 ' Clear TMR1 high byte counter
TMR1L = 0 ' Clear TMR1 low byte counter
T1CON.0 = 1 ' Turn on TMR1

PULSIN Sig3,0,S1 ' Monitor for and measure Sig3
Capture1 = 1 ' Set capture flag bit
T1.HighByte = CCPR1H : T1.LowByte = CCPR1L
Capture1 = 0 ' Clear capture flag bit
ADCIN 1, Low_pot ' Read Low Pot setting
Low_adj = ABS(Low_pot-128) ' Make pot adjustable from center

IF Low_pot <128 THEN ' If pot on left side then make
Low_set= S1-(S1/(AR/Low_adj)) ' negative adjustment
ENDIF

IF Low_pot >=128 THEN ' If pot on right side then make
Low_set= S1+(S1/(AR/Low_adj)) ' positive adjustment
ENDIF

WHILE Sig2=1: WEND ' Wait for trigger signal
PULSOUT Inj2, Low_set ' Send output pulse =% of Sig3
' input signal
Capture1 = 1 ' Set capture flag bit
T2.HighByte = CCPR1H : T2.LowByte = CCPR1L
Capture1 = 0 ' Clear capture flag bit

RPM = T2-T1

HIGH Inj4
PAUSEUS RPM
Low Inj4
GOTO Third


END