#include // CRYSTAL EQU 12000000 ; The crystal speed // TMRCYCLE EQU 12 ; The number of crystal cycles per timer increment // TMR_SEC EQU CRYSTAL/TMRCYCLE ; The # of timer increments per second // F20TH_OF_SECOND EQU TMR_SEC * .05 // RESET_VALUE EQU 65536-F20TH_OF_SECOND ; which is 3CAFh // Sweep will drive along, randonly changing direction, sweeping up rubbish // when sweep hits something, it reverses (or goes forward) for a certain amount of time // then re-checks the sensors. // // Sweep also has a brush he activates when sweeping, while going forwards, his brush is // active, when reversing the brush is stopped. This stops sweep dumping all his rubbish // on the floor. // Sweep has five sensor types: // Bump Sensors - to know when he has hit something. // Light Sensor - to know when it is dark // Sound Sensor - to know when it is quiet // IR Sensor - to know where home is. // Battery Sensor - to know when he is hungry. // the battery and light sensors will be from an LM399 quad voltage comparator // when, so when they hit a certain level, they will trigger the pins high, which the // housekeeping rountine will pick up on. // the sound sensor should be probably triggered from an interrupt, as it needs to know right // away when there is some noise. // bump sensors are to keep him moving around. // light sensor tells Sweep when to activate, it's it's dark and quiet then he'll sweep the floor // the Sound sensor is as above. // IR Sensor tells him where the re-charge station is. // Sweep lives in his charging station, when it gets light he will run and hide in // his base station, charging his battery. As soon as it gets dark, and he can't // hear anything around he will emerge from his base station and begin sweeping the // floor it someone enters the room makes a noise and/or switches the light on he will // spin around looking for his base station using his IR sensor, then heads for it, // and stays there until it's dark and quiet again. // // If, while he is sweeping his battery gets low, it triggers him to return to his base // station to re-charge. Re-charging is done on a timer, and he will continue sweeping // again once he is charged up. // Problems: // Can't empty his bucket of rubbish. It will have to be done for him. // The noise he makes may make him hide again. #define timer1_h 0x3C #define timer1_l 0xAF #define uchar unsigned char #define FALSE 0 #define TRUE !FALSE #define LEFT_MOTOR_FORWARD _P1_0 // there are obvious #define LEFT_MOTOR_BACK _P1_1 // aren't they? #define RIGHT_MOTOR_FORWARD _P1_2 // oh..... #define RIGHT_MOTOR_BACK _P1_3 // well never mind :-) #define BUMP_SENSOR_LEFT P1_4 // I think these are too #define BUMP_SENSOR_RIGHT P1_5 // #define BUMP_SENSOR_FRONT P1_6 // #define BUMP_SENSOR_BACK P1_7 // #define BUMP_PORT P1 // bump port, actual sensors, are the high nibble. #define BatterySensor P3_3 // to know when we're running low on juice. #define Sweeper P3_4 // our little sweeping brush #define SoundSensor P3_5 // the sound sensor. #define IRSensor P3_6 // IR Sensor - locate power suppy with it. #define LightSensor P3_7 // Light Sensor. #define ST_FORWARDS 0x00 // both motors forwards #define ST_BACKWARDS 0x01 // both motors backwards #define ST_LEFT_FORWARDS 0x02 // left motor forwards, right motor stopped #define ST_LEFT_BACKWARDS 0x03 // left motor backwards, right motor stopped #define ST_RIGHT_FORWARDS 0x04 // right motor forwards, left motor stopped #define ST_RIGHT_BACKWARDS 0x05 // left motor backwards, left motor stopped #define ST_CLOCKWISE 0x06 // left motor forwards, right motor backwards #define ST_ANTICLOCKWISE 0x07 // left motor backwards, right motor forwards #define ST_RESUME_NORMAL 0x08 // carry on sweeping! #define STATE_TIMER 0x08 // re-load value of state timer. void InitTimer1(void); data uchar Tmp=20; data uchar Ticks=20; data uchar Seconds=0; data uchar Minutes=0; data uchar Hours=0; data uchar StateTimer=STATE_TIMER; data uchar CurrentState=ST_FORWARDS; // we go forwards to start with. data uchar DriveState=ST_FORWARDS; // we go forwards to start with. data uchar SetPieceIdx=0; data unsigned char * xdata p; code uchar * data pSetPiece = 0; // pointer to our current set piece move bit bTimerExpired=0; bit bIsSetPiece=0; // flag to indicate we have gone into a set-piece action. bit bStateChange=0; // flag to indicate drive state has changed. bit bReturningToBase=0; // flag to indicate we are returning to base. //--------------------------------------------------------------------------------------- // 'set-piece' actions to get out of trouble... code unsigned char spHitFront[] = { ST_BACKWARDS,ST_BACKWARDS,ST_LEFT_BACKWARDS, ST_BACKWARDS,ST_LEFT_BACKWARDS, ST_RESUME_NORMAL}; code unsigned char spHitFrontLeft[] = { ST_RIGHT_BACKWARDS,ST_BACKWARDS,ST_LEFT_BACKWARDS, ST_RESUME_NORMAL}; code unsigned char spHitFrontRight[] = { ST_BACKWARDS,ST_RIGHT_BACKWARDS,ST_BACKWARDS,ST_RIGHT_BACKWARDS,ST_RESUME_NORMAL}; code unsigned char spHitBack[] = { ST_FORWARDS,ST_RIGHT_FORWARDS,ST_FORWARDS,ST_RIGHT_FORWARDS,ST_RESUME_NORMAL}; code unsigned char spHitBackLeft[] = { ST_FORWARDS,ST_LEFT_FORWARDS, ST_FORWARDS,ST_LEFT_FORWARDS, ST_RESUME_NORMAL}; code unsigned char spHitBackRight[] = { ST_FORWARDS,ST_LEFT_FORWARDS, ST_FORWARDS,ST_RIGHT_FORWARDS,ST_RESUME_NORMAL}; code unsigned char spHitLeft[] = { ST_CLOCKWISE,ST_FORWARDS,ST_CLOCKWISE,ST_RESUME_NORMAL}; code unsigned char spHitRight[] = { ST_ANTICLOCKWISE,ST_FORWARDS,ST_ANTICLOCKWISE,ST_RESUME_NORMAL}; // used to scoot away randomly, if we were heading forwards, and the rear sensor was hit, then // someone/something hit us! Panic and run around for a bit! code unsigned char spHitPanic[] = {ST_BACKWARDS,ST_CLOCKWISE,ST_FORWARDS,ST_ANTICLOCKWISE,ST_ANTICLOCKWISE,ST_FORWARDS,ST_CLOCKWISE,ST_RESUME_NORMAL}; //--------------------------------------------------------------------------------------- void InitTimer1(void) { TH1=timer1_h; TL1=timer1_l; PT0=1; TR1=1; ET1=1; IT1=1; EA=1; } //--------------------------------------------------------------------------------------- void TimerOne(void) interrupt 3 _naked { _asm push acc // We'll use the accumulator, so we need to protect it push PSW // Protect PSW flags clr TR1 // Turn off timer 1 as we reset the value mov TH1,#timer1_h // Set the high byte of the reset value mov TL1,#timer1_l // Set the low byte of the reset value setb TR1 // Restart timer 1 now that it has been initialized // uncomment these 3 lines if you want housekeeping every 1/2 a second. // cmp _ticks,#10 // jne 0005$ // setb _bTimerExpired // put in by me, so we do housekeeping every second. 0005$: djnz _Ticks,0010$ // Decrement TICKS, if not yet zero we exit immediately mov _Ticks,#20 // Reset the ticks variable inc _Seconds // Increment the second varaiable setb _bTimerExpired // put in by me, so we do housekeeping every second. // based on this flag. mov A,_Seconds // Move the seconds variable into the accumulator cjne A,#60,0000$ // If we haven't counted 60 seconds, we're done. mov _Seconds,#0 // Reset the seconds varaible inc _Minutes // Increment the number of minutes mov A,_Minutes // Move the minutes variable into the accumulator cjne A,#60,0000$ // If we haven't counted 60 minutes, we're done mov _Minutes,#0 // Reset the minutes variable inc _Hours // Increment the hour variable 0010$: pop PSW // Restore the PSW register pop acc // Restore the accumulator reti // Exit the interrupt routine _endasm; } //--------------------------------------------------------------------------------------- void LeftForward() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_FORWARD // if it's going forward stop it. setb LEFT_MOTOR_FORWARD // and make it turn forwards ret // finished _endasm; } //-------------------------------------------------------------------------------- void LeftBackward() _naked { _asm clr LEFT_MOTOR_FORWARD // if it's going forward stop it. clr RIGHT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_FORWARD // if it's going forward stop it. setb LEFT_MOTOR_BACK // and make it turn backwards ret // finished _endasm; } //-------------------------------------------------------------------------------- void RightForward() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr LEFT_MOTOR_FORWARD // if it's going forward stop it. clr RIGHT_MOTOR_BACK // if it's going back stop it setb RIGHT_MOTOR_FORWARD // and make it turn forwards ret // finished _endasm; } //-------------------------------------------------------------------------------- void RightBackward() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr LEFT_MOTOR_FORWARD // if it's going forward stop it. clr RIGHT_MOTOR_FORWARD // if it's going forward stop it. setb RIGHT_MOTOR_BACK // and make it turn backwards ret // finished _endasm; } //-------------------------------------------------------------------------------- void LeftStop() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr LEFT_MOTOR_FORWARD // if it's going forward stop it. ret // finished _endasm; } //-------------------------------------------------------------------------------- void RightStop() _naked { _asm clr RIGHT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_FORWARD // if it's going forward stop it. ret // finished _endasm; } //-------------------------------------------------------------------------------- void AllStop() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr LEFT_MOTOR_FORWARD // if it's going forward stop it. clr RIGHT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_FORWARD // if it's going forward stop it. ret // finished _endasm; } //-------------------------------------------------------------------------------- void AllForwards() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_BACK // if it's going back stop it setb LEFT_MOTOR_FORWARD // forwards setb RIGHT_MOTOR_FORWARD // forwards. ret // finished _endasm; } //-------------------------------------------------------------------------------- void AllBackwards() _naked { _asm clr LEFT_MOTOR_FORWARD // if it's going forward stop it clr RIGHT_MOTOR_FORWARD // if it's going forward stop it setb LEFT_MOTOR_BACK // backwards setb RIGHT_MOTOR_BACK // backwards ret // finished _endasm; } //-------------------------------------------------------------------------------- void Clockwise() _naked { _asm clr LEFT_MOTOR_BACK // if it's going back stop it clr RIGHT_MOTOR_FORWARD // if it's going forward stop it. setb LEFT_MOTOR_FORWARD // spin clockwise setb RIGHT_MOTOR_BACK // on yourself. ret // finished _endasm; } //-------------------------------------------------------------------------------- void AntiClockwise() _naked { _asm clr LEFT_MOTOR_FORWARD // if it's going forward stop it. clr RIGHT_MOTOR_BACK // if it's going back stop it setb LEFT_MOTOR_BACK // spin anti-clockwise setb RIGHT_MOTOR_FORWARD // on yourself. ret // finished _endasm; } //--------------------------------------------------------------------------------------- void InitSetPiece(code *const uchar Type) { pSetPiece=Type; bIsSetPiece=1; // flag to indicate we have gone into a set-piece action. bStateChange=1; // flag to indicate drive state has changed. } //--------------------------------------------------------------------------------------- ReturnToBase() { bReturningToBase=1; // umm, I have no idea } //--------------------------------------------------------------------------------------- void HouseKeeping() { // alternate version..... // and for some reason, it does not optimise the switch as well as the // big if statements down below, it keeps using :- // mov dpl,#_spHitBackLeft // mov dph,#(_spHitBackLeft >> 8) // rather than :- //; Peephole 182a use 16 bit load of DPTR // mov dptr,#_spHitPanic // lcall _InitSetPiece uchar bumpers= (BUMP_PORT& 0xF0) >>4; switch(bumpers) { case 0: break; case 1: // LEFT InitSetPiece(spHitLeft); break; case 2: // RIGHT InitSetPiece(spHitRight); break; case 3: // LEFT & RIGHT InitSetPiece(spHitPanic); break; case 4: // FRONT InitSetPiece(spHitFront); break; case 5: // FRONT & LEFT InitSetPiece(spHitFrontLeft); break; case 6: // FRONT & RIGHT InitSetPiece(spHitFrontRight); break; case 7: // FRONT & LEFT & RIGHT InitSetPiece(spHitFront); break; case 8: // BACK InitSetPiece(spHitBack); break; case 9: // BACK & LEFT InitSetPiece(spHitBackLeft); break; case 10:// BACK & RIGHT InitSetPiece(spHitBackRight); break; case 11:// BACK & LEFT & RIGHT InitSetPiece(spHitBack); break; case 12:// BACK & FRONT case 13:// BACK & FRONT & LEFT case 14:// BACK & FRONT & RIGHT case 15:// BACK & FRONT & LEFT & RIGHT InitSetPiece(spHitPanic); break; } /* if(BUMP_SENSOR_FRONT) { if(BUMP_SENSOR_LEFT) { InitSetPiece(spHitFrontLeft); } else if (BUMP_SENSOR_RIGHT) { InitSetPiece(spHitFrontRight); } else { InitSetPiece(spHitFront); } if(BUMP_SENSOR_BACK) // front AND rear? eek! panic!!!!! { InitSetPiece(spHitPanic); } } else if(BUMP_SENSOR_BACK) { if(BUMP_SENSOR_LEFT) { InitSetPiece(spHitBackLeft); } else if (BUMP_SENSOR_RIGHT) { InitSetPiece(spHitBackRight); } else { InitSetPiece(spHitBack); } } else if(BUMP_SENSOR_LEFT) { if(BUMP_SENSOR_RIGHT) { InitSetPiece(spHitPanic); } else { InitSetPiece(spHitLeft); } } else if (BUMP_SENSOR_RIGHT) { if(BUMP_SENSOR_LEFT) { InitSetPiece(spHitPanic); } else { InitSetPiece(spHitRight); } } */ // check the battery and light sensors if(BatterySensor || LightSensor) { ReturnToBase(); } } //--------------------------------------------------------------------------------------- void CleanTheFloor() { if(bIsSetPiece) // if we are doing a 'set piece' action { if(bTimerExpired) // and the timer has expired (once a second by default) { DriveState = *pSetPiece; // set the DriveState to the current action pSetPiece++; // move to the next action if(DriveState==ST_RESUME_NORMAL) // if we are returning to normal { AllForwards(); // just drive in a straight line Sweeper=1; // switch the brush back on bIsSetPiece=0; // we are no longer doing set piece actions pSetPiece=0; // wipe out the pointer } } } else if (bTimerExpired) // otherwise, if the timer has expired { HouseKeeping(); // do some housekeeping } if(CurrentState!=DriveState) // if the current state is not the same as the requested state { switch(DriveState) // based on the new drive state, change what we are doing. { case ST_FORWARDS: AllForwards(); Sweeper=1; break; case ST_BACKWARDS: Sweeper=0; AllBackwards(); break; case ST_LEFT_FORWARDS: Sweeper=0; LeftForward(); break; case ST_LEFT_BACKWARDS: Sweeper=0; LeftBackward(); break; case ST_RIGHT_FORWARDS: Sweeper=0; RightForward(); break; case ST_RIGHT_BACKWARDS: Sweeper=0; RightBackward(); break; case ST_CLOCKWISE: Sweeper=0; Clockwise(); break; case ST_ANTICLOCKWISE: Sweeper=0; AntiClockwise(); break; case ST_RESUME_NORMAL: Sweeper=1; break; } CurrentState=DriveState; // set the current state to this state. } } //--------------------------------------------------------------------------------------- void main(void) { int a=12,b=10,c=0; Tmp=a%b; InitTimer1(); while(TRUE) { if(bReturningToBase) { ReturnToBase(); } else { CleanTheFloor(); } } } //--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------