During xMas holidays, I've been thinking about my Weeling Project, I had the impression that something was not yet ok and also simulations show me that sometime the RPM calculaion is not precise enough. The Weeling Project goal is to show how much the rear weel is weeling (spinning) in respect to the front weel, but if the HW / SW would be not enough precise, I fear that all will be for nothing at the end.
Therefore I had the idea to define a state machine for the Weeling Project in order to filter the spurious signals. Let's see what I mean:
Therefore I defined 5 states:
0) IDLE (or neutral gear): when the bike is running below 5 Km/h
1) DRIVE: when the bike is moving
2) ACCELLERATING: when the bike is accelerating
3) BOOST: when the bike is accellerating very very fast. In this state the Weeling factor will be calculated (in the other states not, so to filter spurious impulses)
4) BRAKE: when the bike is braking (speed variation is negative or used gear is decreased)
From the state diagrams it is clear how the states are connected each other, I had to take some decision and I can not promise that I'll not change it (expecially I'm not really sure if the transition from BOOST back to ACCELLERATING makes really sense). In any case the SW is:
#define STATE_IDLE 0 // Neutral Gear
#define STATE_DRIVE 1 // Drive slow (V > 5 Km/h)
#define STATE_BOOST 3 // dV / dT >> xx
#define STATE_BRAKE 4 // dV / dT <>
void main(void)
{
// USER CODE BEGIN (Main,2)
unsigned int uiWeeling; // ratio between rear / front weels RPM
unsigned int uiTmp;
unsigned int bTransmit; // loop counter
// USER CODE END
MAIN_vInit();
// USER CODE BEGIN (Main,4)
// T4 As RPM Generator
GPT1_vStopTmr(GPT1_TIMER_4);
GPT12E_T4= T4_25ms;
GPT1_vStartTmr(GPT1_TIMER_4);
// Clear T6 and Start
GPT2_vClearTmr(GPT2_TIMER_6);
GPT2_vStartTmr(GPT2_TIMER_6);
// LED constantly on to indicate that SW is not yet started
P1L_P3 = 1;
// RS232 Start Message
printf ( "WEELING is RUNNING !!!\n\n" ); /* the 'printf' function call */
ASC0_ubTxDataReady();
bTransmit = FALSE;
while (1)
{
// Skip First 5 execution to stabilize acquisition
if (iGPT_Counter > 5)
{
// Derivate Calculation
iDelta_FRONT = (int) ( uiRPM_FRONT - uiOldRPM_FRONT );
iDelta_REAR = (int) ( uiRPM_REAR - uiOldRPM_REAR );
if ( iDelta_REAR > 10 )
bTransmit = TRUE; // In case of a weeling Comunication is started
uiOldRPM_FRONT = uiRPM_FRONT;
uiOldRPM_REAR = uiRPM_REAR;
// Speed Calculation
uiSpeed = ( (float) (uiRPM_REAR) * 7.9 ); // to get the first decimal digit, divide by 10
// Calculate the actual inserted Gear and Display it
uiTmp = (unsigned int) ( ( (float) uiRPM_ENGINE * 1000 ) / ( (float) uiRPM_REAR ) );
CalculateGear (uiTmp);
// Update current State Machine Status
uiOldWeelingStatus = uiWeelingStatus;
switch (uiWeelingStatus)
{
case STATE_IDLE: // :0
// Initialize the Derivative calculation
uiOldRPM_FRONT = uiRPM_FRONT;
uiOldRPM_REAR = uiRPM_REAR;
iGearShift = 0;
if ( uiSpeed > 50 )
uiWeelingStatus = STATE_DRIVE;
break;
case STATE_DRIVE: // :1
if ( iGearShift > 0 )
uiWeelingStatus = STATE_ACCELLERATING;
if ( iGearShift < uiweelingstatus =" STATE_BRAKE;" uiweelingstatus =" STATE_IDLE;"> 0 )
uiWeelingStatus = STATE_BOOST;
if ( iDelta_REAR >= 10 )
uiWeelingStatus = STATE_BOOST;
if ( iGearShift < uiweelingstatus =" STATE_BRAKE;" uiweeling =" ((float)uiRPM_REAR" igearshift =" 0;" uiweelingstatus =" STATE_ACCELLERATING;" uiweelingstatus =" STATE_BRAKE;"> 0 )
uiWeelingStatus = STATE_ACCELLERATING;
if ( (uiSpeed < 50) (uiGEAR == 0) )
uiWeelingStatus = STATE_IDLE;
break;
}
if (uiOldWeelingStatus != uiWeelingStatus)
bTransmit = TRUE; // In case of Status Change Comunication is started
// Transmit the measured values to RS232 for debug purpose
if ( bTransmit )
{
printf ( "\n\nSTATE: %d\n", uiWeelingStatus);
printf ( "SPEED: %3.1f [Km/h]\n", (float)(uiSpeed/10.0) );
printf ( "ENGINE RPM: %4.2f [RPM]\n", (float)(uiRPM_ENGINE*60.0) );
printf ( "GEAR: %d\n", uiGEAR );
printf ( "FRONT WEEL RPM: %4.2f [RPM]\n", (float)(uiRPM_FRONT*60.0) );
printf ( "REAR WEEL RPM: %4.2f [RPM]\n", (float)(uiRPM_REAR*60.0) );
printf ( "FRONT WEEL D/Dt: %d [RPM]\n", iDelta_FRONT );
printf ( "REAR WEEL D/Dt: %d [RPM]\n", iDelta_REAR );
printf ( "WEELING RATIO: %3.2f [%%]\n", (float)(uiWeeling/10.0) ); // in percentage
// no transmission for the following loops
bTransmit = FALSE;
}
}
}
// USER CODE END
} // End of function main
As visible in the main() function, I have also improved the RS232 transmission in order to transmit only when something is happening. The printed messages are:
Since the above picture is not really readable, I copy here an example:
STATE: 2
SPEED: 72.6 [Km/h]
ENGINE RPM: 7020.00 [RPM]
GEAR: 2
FRONT WEEL RPM: 9120.00 [RPM]
REAR WEEL RPM: 5520.00 [RPM]
FRONT WEEL D/Dt: 0 [RPM]
REAR WEEL D/Dt: 0 [RPM]
WEELING RATIO: 60.50 [%] As it is visible the front weel speed is a too high, this is due to the fact that I executed the "start ACCELLERATION" simulation macro that change only the rear weel speed without changing the front weel and the engine speed (since I do not know how to do it with Keil), here the macro code:
signal void accUp (void)
{
float frequency; // pulse frequency in Hz
int gear; // gear used
int pulses; // 1000 pulses per simulation
frequency = 63; // Hz
gear = 1;
pulses = 0;
printf("Rear: %f [Hz]\n", frequency);
while(gear < 7)
{
swatch (0.5 / frequency);
PORT5 |= (1 << 12); // set pin 5.12
swatch (0.5 / frequency);
PORT5 &= ~(1 << 12); // reset pin 5.12
pulses = pulses + 1;
if (pulses > 700)
{
pulses = 0;
gear = gear + 1;
if (gear == 2) frequency = 92;
else if (gear == 3) frequency = 115;
else if (gear == 4) frequency = 134;
else if (gear == 5) frequency = 150;
else if (gear == 6) frequency = 165;
// printf("Rear: %f [Hz]\n", frequency);
}
}
} Where the REAR WEEL speed starts from 63 Hz (= 3775 RPM, first gear) and increases to the second, third, ... gear incresing the rear weel speed accordly. This macro is very useful since permit to simulate all the gears from 1 to 6. For the viceversa, I use:
signal void accDown (void)
{
float frequency; // pulse frequency in Hz
int gear; // gear used
int pulses; // 1000 pulses per simulation
frequency = 165; // Hz
gear = 6;
pulses = 0;
printf("Rear: %f [Hz]\n", frequency);
while(gear > 0)
{
swatch (0.5 / frequency);
PORT5 |= (1 << 12); // set pin 5.12
swatch (0.5 / frequency);
PORT5 &= ~(1 << 12); // reset pin 5.12
pulses = pulses + 1;
if (pulses > 500)
{
pulses = 0;
gear = gear - 1;
if (gear == 1) frequency = 63;
else if (gear == 2) frequency = 92;
else if (gear == 3) frequency = 115;
else if (gear == 4) frequency = 134;
else if (gear == 5) frequency = 150;
else if (gear == 6) frequency = 165;
// printf("Rear: %f [Hz]\n", frequency);
}
}
} As you can see at the end is quite easy to create own simulation scripts, clearly after accUp() and accDown() I have also created an accUpDownUpDown() (for space reasons I do not attach the macro code, if you are interested, just write to me, I'll mail you).
As summary of the various simulations, I have compiled:
Overall I've tested various gears, speeds and States (of the state machine), but not all...
(meanwhile I'm simulating the SW, I also stared the HW, so stay tuned!!!)