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: