Saturday, March 14, 2009

Putting it together (Con't...)

After one day on the race-track, I've try to understand the YAMAHA R6 (2003 model) ECU signals, these are the garage photos: after I have connected the new weels speed sensors: and the rear one: as is visible in the photo, the inductive sensor does not detect the metal braking disk (LED is OFF), when moving the weel it comes near by the metal the contact is activated (LED in ON): I also take some oscillograms of the engine PRM and rear RPM (output of the inductive sensor), here the 1st gear at RPM=1000:

this is WEELING:

Sunday, March 1, 2009

Putting it together...

It is time to put the pieces together.... even if all is not ready. The "XE164 to Display connections" post explayin how the XE164 is driving the Display module, now remains only to solder the connectors: I decided to solder connectors to the XE164 KeyChain board so to be flexible to replace it (you never know... and since I have not done any dedicated PCB, I'm afraid that I will need maintenance!). For the insystem flash programming and for the debug the XE164 KeyChain makes available the JTAG interface, I solder then a dedicated conector on the top side, all is visible in the picture:
The little adaptor board is intended to:
- supply the the XE164 KeyChain providing 5V (I just use an old fashion 7805 linear voltage regulator)
- be the interface board connecting the display to the XE164
- be the interface board for speed sensors (electronics not yet soldered)
- be the interface board for Oil Temperature sensor (I use the one already available on the YAMAHA R6, so I just need to protect the XE164 and convert the signal with the ADC) - be the interface board for fuel level signal
- be the interface board for any forther expansion (feel free to post ideas...).

At the end, this is the video of the first power-on:

where I have created a demo project where the weels and engine speed are generated by the SW itself, this permit to observe all the Display Messages (real debug will come once the weeling speed sensors will be connected). Anyhow, the first bug has been discovered: the Display refresh speed is too slow !!!
To fix it I had to reload Timer_4 counter to the 480Hz value after each Interrupt Service occours:
//****************************************************************************
// @Function void GPT1_viTmr4(void)
//
//----------------------------------------------------------------------------
// @Description This is the interrupt service routine for the GPT1 timer 4.
// It is called up in the case of over or underflow of the
// timer 4 register.
// If the incremental interface mode is selected and the
// interrupt for this mode is not disabled it is called up if
// count edge or count direction was detected.
//
// Please note that you have to add application specific code
// to this function.
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters None
//
//----------------------------------------------------------------------------
// @Date 3/1/2009
//
//****************************************************************************

void GPT1_viTmr4(void) interrupt T4INT
{
// Stop Timer first !
GPT1_vStopTmr(GPT1_TIMER_4);


if ( ucDisplayDigit[ucIdx] != 0xFF )
{
SelectDigit ( 0 ); // Deselect any DIGIT
Display ( ucDisplayDigit[ucIdx] );
// DOT driver
if ( ucDisplayDigit[ucIdx]>>4 )
IO_vSetPin ( IO_P0_6 );
else
IO_vResetPin ( IO_P0_6 );

SelectDigit ( ucIdx );
}
ucIdx++;
if ( ucIdx > 5 ) ucIdx = 0;

// Start Timer
GPT12E_T4 = TIMER4_480Hz;
GPT1_vStartTmr(GPT1_TIMER_4);

} // End of function GPT1_viTmr4
... now, beliewe me, the refresh speed is as expected and the digits are really bright and stable.

Saturday, February 28, 2009

Logger

It is also time to use the internal Flash Memory for Logging various important parameters. In order to do this, I like to use the XE164 internal flash memory: in fact it has 3x256Kb flash modules and for my purpose one module could be enought:











The SW becomes:
// Update LOG data
LogData.uiSpeed = uiSpeed;
LogData.uiRPM_REAR = uiRPM_REAR;
LogData.uiRPM_ENGINE = uiRPM_ENGINE;
LogData.uiRPM_FRONT = uiRPM_FRONT;
LogData.uiGEAR = uiGEAR;
LogData.uiDistanceOdo = uiDistanceTrip;
// Transmit the measured values to RS232 for debug purpose or store in some external memory as a log-file
if ( bTransmit )
{
LOGGER_AppendChunk( (void near *) &LogData );
}

XE164 to Display connections

It is time to connect the XE164 KeyChain to the display. I start from the XE164 KeyChain schematic: it is published by Infineon at (also Eagle Layout is available). Based on this, I created the list of used I/Os (it is easier to show it instead of explayining it):




One important note is to presenve the HWCFG[0] = HWCFG[1] = 1 otherwise the uC will not boot from internal flash memory (this I/Os have been already pulled, but if you connect some external circuit, it could be that this sink too much current during boot phase changing the HWCFG[0-1] state).
So, Display digit selection is made by using P0 port (bits 0..5), the digit dot is connected to P0.6, while the digit value is driven by port P1 (bits 0..3):

this simplify a lot the SW:
//****************************************************************************
// @Function void Display
//
//----------------------------------------------------------------------------
// @Description Convert the Character code into I/O port level
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters
// num: 0-9 number to be displayed on the 7 segment LED
//
//----------------------------------------------------------------------------
// @Date 12/17/2008
//
//****************************************************************************

void Display(char num)
{
IO_vWritePort ( P1, 0x0F & num );
}

//****************************************************************************
// @Function void SelectDigit
//
//----------------------------------------------------------------------------
// @Description Select one 7-segment display digit
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters
// num: 0-5 digit selector
//
//----------------------------------------------------------------------------
// @Date 12/17/2008
//
//****************************************************************************

void SelectDigit(char num)
{
IO_vWritePort ( P0, 0x01 << num );
}

void GPT1_viTmr4(void) interrupt T4INT
{
if ( ucDisplayDigit[ucIdx] != 0xFF )
{
SelectDigit ( 0 ); // Deselect any DIGIT
Display ( ucDisplayDigit[ucIdx] );
// DOT driver
if ( ucDisplayDigit[ucIdx]>>4 )
IO_vSetPin ( IO_P0_6 );
else
IO_vResetPin ( IO_P0_6 );

SelectDigit ( ucIdx );
}
ucIdx++;
if ( ucIdx > 5 ) ucIdx = 0;

} // End of function GPT1_viTmr4

Display It! (cont...)

Step by step I have also built an alluminium box for the Display...
For the front panel, I have followed the instructions of some other blogger and I have created a front panel design:

(I'm not so proud of it, but is a starting point...).

I started drawing it, I printed on transparent paper and painted with White syntetic spray paint after having protected the two areas that must remain transparent:

After 1h, I peel-off the protection tape (clearly I painted the back side of it):

Building the Display Box:
I prefer to build from scratch the box using alluminium and a bit of manual work: in my workshop I have all necessary for this...


The proceedings are:
- cut the alluminium pieces at the right size and with 45° angles to form a box:

- cut the glass and the rear sealing alluminium plate:
- seal it using black silicon rubber:


- seal also the front side (after having ptotected it with paper tape):


Is not yet ready, but I like to try it to check if it fits with the real display size:


(final pictures will come....)

Sunday, February 8, 2009

Display It! (Cont...)

Finally I added some LEDs on the 7-Segment display: a very bright set of 5 LEDs for the Weeling Flash indicator and a set of 5 standard red LEDs for the FUEL indication (if tank is empty, it should be ON).
Due to the uC IO max current limitation (I mean, the fact that the uC could not supply more then 2mA per IO), I have inserted a NPN transistor (BC337). Here the electrical circuit:

With very bright LEDs, the equation to calculate the series resistances is:
R = (5V - Vce - Vd) / Id
Where Vce is about 0.013V, Vd is the working LED voltage: Vd = 3V and Id is the working LED current: Id = 20mA (those walues are for very bright LEDs), therefore:
R = (5V - 0.013V - 3V) / 20mA = 100 Ohm.
While for normal LED (where Vd = 1.5V, Id = 10mA):
R = (5V - 0.013V - 1.5V) / 10mA = 360 Ohm
This is what the LEDs looks like after saldering on the DISPLAY board:


So, summarizing, the DISPLAY looks like:

where are shown all the available display elements.

It is clear that the DISPLAY will show different informations depending on the weeling status, so for the OFF status:

therefore each time the bike will stop for more then 3', the display will commute to shows engine water temperature, total distance and fuel status.

IDLE status:

therefore each time the bike is in IDLE status (V < 5Hm/h), the display will commute to shows engine water temperature, ODO Trip and fuel status.

DRIVE status:

therefore each time the bike will drive, the display will commute to shows engine water temperature, gear and fuel status.

ACCELLERATING status:

therefore each time the bike will accellerate, the display will commute to shows engine water temperature, gear and fuel status.

BOOST status:

therefore each time the bike will accellerate very fast (with the risk of spinning), the display will commute to shows engine water temperature, gear, percentage of spinning and fuel status.

BRAKE status:
therefore each time the rider will brake, the display will commute to shows engine water temperature, gear and fuel status (while braking is very important to show the used gear to help the driver to avoid mistakes).

Software:
At the end, I decide to use a timer (TIMER 4) to refresh the display every 40Hz. This is to avoid flickering and a better software architecture. The 6 digits are store in:
unsigned char ucDisplayDigit[6]; // Display Buffer
every 25ms, the timer interrupt service will display one digit only, one by one. Therefore the display software is drawing one digit by one every 25msec (40Hz), the human eyes are integrating the light and the image happear as a whole (if refresh frequency is higher then 25Hz, it is also without flickering).
Here the interrupt service routine for Timer 4:
void GPT1_viTmr4(void) interrupt T4INT using RB_LEVEL9
{
// USER CODE BEGIN (Tmr4,2)

// USER CODE END


// USER CODE BEGIN (Tmr4,5)

if ( ucDisplayDigit[ucIdx] != 0xFF )
{
SelectDigit ( 0 ); // Deselect DIGIT
Display ( ucDisplayDigit[ucIdx] );
// DOT driver
P1L_P6 = ucDisplayDigit[ucIdx]>>4;
SelectDigit ( ucIdx );
}
ucIdx++;
if ( ucIdx > 5 ) ucIdx = 0;

// USER CODE END

} // End of function GPT1_viTmr4
As mentioned, the information to display are stored in the ucDisplayDigit character array. If a digit must not be displayed, then the respective value has to be 0xFF. If the relat DOT must be on, the forth digit must have the high nibble to 1 (i.e. 0x14 -> DOT is on, digit is 4). Here some further examples:

Thursday, January 29, 2009

Weeling Project (cont...)

Finally I start to look in deep to the weeling ratio (I intend to buid an ECU capable to show me if rear weel is spinning by flashing a LED).
The SW must do:
6. LED must blink (flash) proportionally to the spinning ratio:
  • slow spin -> LED is blinking slow
  • high spin -> LED is blinking very fast

The Angular speed is:

while the Tangential speed is:

where r (weel radius) can be derived from the weel circonference lenght:
r = 2 x PI x r

Therefore we have:

what I mean in the picture is that at low speed the front and rear weels can not slip, therefore at low speed it can be calculated the
WeelRatio = RPM_REAR / RPM_FRONT.

The SW must be updated then to calculate such ratio every time the bike is running slow, for example every time the bike speed is between 10 Kh/h and 20 Km/h and save it to a dedicated static variable, as for example:
float fWeelRatio;

During fast accellerating phase, the instant weels ratio can be compared with the stored fWeelRatio variable and the LED can be driven proportionally as described in the following draw:

The thresholds (i.e. 120%, 130%, etc..) can be used defined in a configuration flash area without the need to recompile the project each time.
The software will be updated soon...