Page 3 of 100

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 11:35 am
by Fred
I had a bit of a "moment of truth and enlightenment" last night in the shower. I already knew that the hardware timer could be extended by incrementing another variable on overflow, but (of course) that can not be used to switch the hardware outputs. Thus, the input side of counting can be arbitrarily precise out to the nth degree, but the output side is bounded by two things, maximum period, and unit of measure. Obviously we want the unit of measure to be as small as possible, but what about the period... well, we need to be able to inject enough under high load, low rpm, heavy enrichment situations. If we used 16 as the prescaler, we get 400ns units, and 26.2144ms maximum pulse width. That is not enough for all situations. The next step gives 52.4288ms which should be plenty for most situations and still has less than 1us accuracy (800ns/0.8us). There is going to need to be a minimum pulse width limit too because of the latency of the code that switches the hardware timer register. That should be very small indeed. But it will exist as a limitation.

Things that I need to do :
  • Ensure that "pulse width" is above min and below max at all times by force. (maybe set a flag for each condition that says something is wrong)
  • Make overlapping periods transition to full on cleanly and transition back to switching cleanly again
  • Read the signal properly with a good usable on car strategy
That last one needs to involve some or all of the following (and maybe more) :
  • Hardware tooth throwing out (introduces a 256,512,1024 bus cycle delay before interrupt if used)
  • Software tooth throwing out (means performing actions at end of tooth (better for VR anyway)
  • Counter increment on leading edge, decrement on trailing if invalid tooth (needs thought and status)
  • History and comparison of the previous gaps between main teeth
  • History and comparison of the previous tooth widths
  • Comparison of second trigger location with where expected
  • History and comparison of second trigger tooth width
I'm working on it :-)

When thats done, it will be ready for on car manual pulsewidth control idle testing :-)

Admin.

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 1:24 pm
by Fred
I've been experimenting :-)

What I have discovered is that it is possible to switch edges and interrupt without changing the state of the port (OC mode).

What this means is that we can turn the timer down to really fine grain control and set the edge and counter to interrupt without switching it off, inc a var, reset the same, etc and finally set to go low at the predefined time.

This also means we can have arbitrarily long pulse widths and arbitrarily fine grain control of fueling for awesome precision at ALL RPM and widths :-) Sweet!!!

http://www.google.com/search?hl=en&safe ... tnG=Search

0.1us control anybody? That gives max period of 6.5ms meaning for a typical sort of 20ms high width pulse you would get 3 or 4 interrupts for each injector channel for each injection. Could be worth it, perhaps something to work on later.

I'll stick to making more conventional control work right first.

Admin.

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 1:33 pm
by Fred
Additionally, if 16 bits takes 52ms, then the longest measurable period with an overflow counter extension is 3400 seconds or 57 minutes, a little excessive really. If we knock it to 6.5ms period we get 7 minutes which is still WAY more than we need at all.

The worst case tooth measuring is this :

One tooth of 180 degrees on the Cam, so one edge every 2 revolutions.
If you say that it could spin as low as 1rpm then those edges are 1 minute apart and we still hose in. Yet, at high rpm, our input capture is going to be uber fast and accurate. Nice stuff.

Admin.

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 1:47 pm
by Fred
Of course, what I didn't mention is that the benefit (large) of this is to be able to do the final pulse width calculation as late as possible before turn off. Combined with my cunning main loop segregation we could have a rather significant increase in transient behaviour accuracy :-)

If only the code could just materialise :-)

Admin.

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 1:49 pm
by Fred
Also, careful selection of exactly when those interrupts are at could potentially allow us to use the IC/OC timers to bit bang the staged injectors! That could get complex though, and I'd rather keep it simple, but It should be possible :-)

Damn! I'm on a roll this morning. (making up for a slow yesterday)

Admin.

FreeEMS v0.0.7 released.

Posted: Wed Mar 05, 2008 5:50 pm
by Fred
This release is significant in that the basics of injection control for a NipponDenso 24/2 are sort of there.

I would NOT try this on a car at this time!!

...because there is NO error checking and it definitely misbehaves when the start and end of pulses overlap, and when the input signal is rough/dodgy.

On the other hand, if you are silly enough to ignore me and get an engine idling on this exact code (or any later one with a similar warning at your option) please share it with us here :-)

0.0.7 - 6/3/08
Moved pins for ignition around
Changed obsolete code in main.c with idea inspired by Alex
Tidied and removed some TODOs
Added port A and B access together for ignition output (registers are conveniently next to each other for word access)
Moved PWM experimentation to a function and init.c
Shifted all macros for main injectors to freeems.h for use in (at least) two source files
Rearranged and changed all global variables
Added new status and settings bitwise variables
Implemented very basic NipponDenso decoder that I would not trust to do much at all.

http://www.youtube.com/watch?v=7WXvQi2gpg8

http://sourceforge.net/project/showfile ... _id=581928

I apologise for the large rate of change of the code. If you are trying to work from it, the best you can hope to do is hand remerge your changes on each release. As things stabillise into the future I expect that the difficulty in merging changes to older releases forward will diminish somewhat.

Enjoy!

Admin.

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 8:30 pm
by Fred
Admin wrote:Additionally, if 16 bits takes 52ms, then the longest measurable period with an overflow counter extension is 3400 seconds or 57 minutes, a little excessive really. If we knock it to 6.5ms period we get 7 minutes which is still WAY more than we need at all.

The worst case tooth measuring is this :

One tooth of 180 degrees on the Cam, so one edge every 2 revolutions.
If you say that it could spin as low as 1rpm then those edges are 1 minute apart and we still hose in. Yet, at high rpm, our input capture is going to be uber fast and accurate. Nice stuff.

Admin.
Of course (and no, I didn't think of this earlier) this also limits the time after the schedule tooth that the pulse can start. Unless you do the same thing with advance, at which point it becomes arbitrary. (code for one should be very much the same as for the other)

Admin.

Re: Fred's firmware development diary

Posted: Wed Mar 05, 2008 9:15 pm
by Fred
EDIT : See next post!

I measured the run time of the really simple switch on code :

Code: Select all

void Injector5ISR(void)
{
	/* Clear the interrupt flag for this channel */
	TFLG1 = MAIN5ON;

	/* If rising edge triggered this */
	if(PTIT & MAIN5ON){ // Stuff for switch on time
		// set the time to turn off again
		MAIN5TIME += ATD0DR7 + totalPulseWidth;

		// display the amount we are adding
		PORTA = ATD0DR7 >> 2;
		
		/* Set the action for compare to switch off */
		MAIN5CTL &= MAIN5GOLOW;
	}
}
193 timer units = 154.4us run time including all loading function handling etc. not including the rest, and unloading etc. just an interesting thing to note...

Admin.

Re: Fred's firmware development diary

Posted: Thu Mar 06, 2008 10:14 am
by Fred
Not only has the measurement changed (added some caps to the board) but I think I did the calculation wrongly too.

Actually, 8 Timer units seems to be the code run time 6.4us (probably a bit less, but with 4 it jittered on and off) which gives us 128 - 256 bus cycles from output trips to when the timer gets reset. Much more reasonable. There is hope for us yet, off to apologise to Flacid for misleading him about his viagra.

Admin.

Re: Fred's firmware development diary

Posted: Fri Mar 07, 2008 1:59 pm
by Fred
I'm going to fix a few things up such that changing the prescaler for the timer doesn't affect operation (other than max pulsewidth).

Secondly, I realised that the table for timer prescalers in the manual is just an example. not a full table. So we can pick and choose our time base down to the finest grain.

Thirdly, I have some very basic code that piggy backs output compares on top of each other by giving a count and final period.

This can be further optimised by using divide and modulus to ensure that the last time period is not too small.

Then you just take a time count in (arbitrarily large) figure out how many periods fit within it and what the left over is, and find a main period and final period that are all in the large region that is safe.

if a pulse is timeperiod - 1, you use it (or similar)
if it is time period + 1, you cut in half, and add the left over on to one of them ensuring that it doesn't exceed max.

currently I'm doing 7 second periods with 1000 interrupts and 7ms chunks.

Additionally, the output compare code can watch the timer overflow variable and by careful examination of the interrupt flags when it is triggered know exactly where it is at absolute time wise. This only works till the final pulse as these interrupts are generated while trying to switch an On injector On again. Once you set it to switch off, its off... so knowing where you are is useless. However on the second to last you could fine tune the pulsewidth to the latest measurement/calculation if done right.

here is the uber basic code that does this (took far too long to write with a handful of errors here and there) :

Code: Select all

void Injector6ISR(void){
	TFLG1 = MAIN6ON; // clear flag
	PORTK++; // blink k7 if we are still interrupting despite edge being already high
	PORTS_BA = periodCount;
	PORTM = MAIN6CTL;
	
	if(timerTestFlag){
		if(periodCount == 0){
			// configure count variable from spare on Jim
			periodCount = ATD0DR7 + 1;

			// configure final pulse variable
			trimLength = (ATD0DR3 << 6) + 1000;
		}else if(periodCount == 1){
			// set next time to be trimlength from now
			MAIN6TIME += trimLength;
			
			if(MAIN6CTL & MAIN6GOHIGH){ // invert direction prior last edge
				MAIN6CTL &= MAIN6GOLOW; // change to go low
			}else{
				MAIN6CTL |= MAIN6GOHIGH; // change to go high	
			}
		}
		
		periodCount--; // decrement counter		
	}else{
		// turn int off
		TIE &= 0x7F;
		// disable switching
		MAIN6CTL &= MAIN6DISABLE;
		
		// turn of pin(s) lazy...
		PORTT = ZEROS;
	}
}
misc_isrs.c :

Code: Select all

	case 0x08 : // Trigger timed pulse
		if(!timerTestFlag){
			PORTK = ONES; // set k

			// set flag
			timerTestFlag = TRUE;
			
			// configure count variable from spare on Jim
			periodCount = ATD0DR7 + 1;

			// configure final pulse variable
			trimLength = (ATD0DR3 << 6) + 1000;
			
			// configure timer to switch on
			MAIN6CTL |= MAIN1ENABLE;

			// configure time to be (short-max/2 +tcnt later)
			MAIN6TIME = TCNT + 1000; // start very soon for now (could use force too)
			
			// configure the interrupt to be on
			TIE |= 0x80;
		}else{
			PORTK = ZEROS; // clear k

			// unset flag
			timerTestFlag = FALSE;
			
			// turn the interrupt off
			TIE &= 0x7F;
			
			// switch off channel
			PORTT = ZEROS;
			
			// disable compare
			MAIN6CTL &= MAIN6DISABLE;
		}
		break;
some of each is probably superfluous/wrong, but it works as it is and I dont want to do a release for it (there are more changes to some variables and flags in init.c too and commenting out of stuff in enginepos.c

see :

/* section 10.3.5 page 290 68hc11 reference manual e.g. groups.csail.mit.edu/drl/courses/cs54-2001s/pdf/M68HC11RM.pdf */

for timer extension implementation details.