My Mouse Robot uses two continuous rotation servos and three IR emitter detectors pointing left, front and right. Acknowledgements to M Backus for the ideas and code principles.
The code that I have listed below are the classes, this will be followed in future posts by the application sketches.
Mouse sensors There are a number of IR emitters and detectors on the market, but the one I have had most success with is the TCRT5000 from Vishay.
This is a module with an IR emitter and IR phototransistor built in one package. The general wiring diagram for the eventual three detectors is:
The motors on the mouse are continuous rotation servos from Parallax.
LIBRARIES
There are two class files, for motors and sensors.
MOTORS
The calls to the motors class are:
motors.attach(); // connects the servo motors to the pins
motors.halt(); // stoops the motors
motors.fwd(dist, error); // motors forwards for diet (0 = continuous) with steering error
motors.turn(dir, deg); // turn West (left) or East (right) by degrees
// *** MouseMotors MASTER FILE *** 16-7-14 #include#include // servo pins #define LS 10 #define RS 11 // servo HALT position, forward SPEED speed, TURN speed, ROTATION (ms/deg) // and CM (ms/cm) #define HALT 1500 #define SPEED 30 #define TURN 30 #define ROTATE 13 #define CM 185 // proportional multiplier (float) #define KP 0.5 // sensor bits, event value // 3 2 1 0 // N 0 0 0 1 = 1 // W 0 0 1 0 = 2 // E 0 1 0 0 = 4 // S 1 0 0 0 = 8 // events map // 7 // 3 1 5 // 2 4 #define N 0 #define W 1 #define E 2 #define S 3 Servo leftServo; Servo rightServo; class MouseMotors { public: // attach servos to pins void attach() { leftServo.attach(LS); rightServo.attach(RS); } // halts the motors void halt() { leftServo.writeMicroseconds(HALT); rightServo.writeMicroseconds(HALT); delay(100); // wait 100 ms for inertia } // forward for dist (cm, 0 = continuous) error + W, error - E void fwd(byte dist, float error) { error = error * KP; leftServo.writeMicroseconds(HALT + SPEED - error); rightServo.writeMicroseconds(HALT - SPEED - error); if(dist != 0) { delay(CM * dist); halt(); } } // turn in direction by degrees void turn(byte dir, byte deg) // turn in dir by deg { switch (dir) { case W: // left leftServo.writeMicroseconds(HALT - TURN); rightServo.writeMicroseconds(HALT - TURN); break; case E : // right leftServo.writeMicroseconds(HALT + TURN); rightServo.writeMicroseconds(HALT + TURN); break; } delay(deg * ROTATE); // convert degrees to ms runtime halt(); } };
SENSORS
The calls to the sensors class are:
sensors.sense(); // sense all three sensors and load west, north & east variables
sensors.state(); // returns an event (0-7) showing walls around the sensors
sensors.init(); // calls sense AVG times
sensors.calibrate(); // measured west and east sensors, takes average and sets thset distance for wall following
// *** MouseSensors MASTER FILE *** 16-7-14 // cellwalls and mouse direction use NWES, see bitmap below and event values // this version is for mousebox.ino and uses a fixed detect distance in state() #include// sensor emitter and detector L, F & R pins #define LE 2 #define LD A0 #define FE 3 #define FD A1 #define RE 4 #define RD A2 // bitmap, event value // 3 2 1 0 // N 0 0 0 1 = 1 // W 0 0 1 0 = 2 // E 0 1 0 0 = 4 // S 1 0 0 0 = 8 // resulting events map // 7 // 3 1 5 // 2 6 4 #define N 0 #define W 1 #define E 2 #define S 3 // number of sensor reading to take for init, event detect level #define AVG 10 #define DETECT 20 class MouseSensors { public: // sensor smoothed readings int west; int north; int east; // threasholds for state() north detect and hall navigation int ndet; int hall; int wall; // init ports void enable() { pinMode(LE, OUTPUT); pinMode(FE, OUTPUT); pinMode(RE, OUTPUT); } // read sensors, laod west, north & east ints void sense() { float comb; float amb; float refl; // WEST digitalWrite(LE, HIGH); // emitter on delay(1); comb = analogRead(LD); // save combined value digitalWrite(LE, LOW); // emitter off delay(1); amb = analogRead(LD); // save ambient value refl = comb - amb;// calculate reflected west = int(refl * 0.1 + west * 0.9); // NORTH digitalWrite(FE, HIGH); // emitter on delay(1); comb = analogRead(FD); // save combined value digitalWrite(FE, LOW); // emitter off delay(1); amb = analogRead(FD); // save ambient value refl = comb - amb;// calculate reflected north = int(refl * 0.1 + north * 0.9); // RIGHT digitalWrite(RE, HIGH); // emitter on delay(1); comb = analogRead(RD); // save combined value digitalWrite(RE, LOW); // emitter off delay(1); amb = analogRead(RD); // save ambient value refl = comb - amb;// calculate reflected east = int(refl * 0.1 + east * 0.9); } // read sensors, return event byte byte state() { byte event; byte detect; sense(); detect = DETECT; // set detection limit event = 0; // init to zero if(north >= detect) bitSet(event, N); // 0001 if(west >= detect) bitSet(event, W); // 0010 if(east >= detect) bitSet(event, E); // 0100 return event; } // init sensors averages by calling sense() AVG times void init() { byte i; for(i = 0; i < AVG; i++) sense(); } };
No comments:
Post a Comment