So, I finished programming the forklift…
Features:
- infrared remote control for driving forward and reverse
- infrared for turning left and right
- infrared for moving fork up and down
- ultrasonic to avoid fork going too far up or down
- two motors for driving
- one motor for fork
I had some issues with traction (resistance to the tires), switched to tracks, but still had to program some sense into the driving. I think the source code explains it all (listed below).
I also made a youtube movie (that shows I am a lousy driver). Some of the delays in the movie are because the infrared remote is not working properly, about one in three key-presses is ignored (maybe my fault…).
The source code. I am not a developer, so this can probably be improved a lot (please let me know how).
#include <Me_BaseShield.h>
#include <Me_MotorDriver.h>
#include <Me_BaseShieldMotorDriver.h>
#include <Me_UltrasonicSensor.h>
#include <Me_InfraredReceiver.h>
Me_BaseShieldMotorDriver baseShieldMotorDriver;
Me_MotorDriver motorDriver(PORT_1); // port 1
Me_UltrasonicSensor ultraSensor(3); // port 3
Me_InfraredReceiver infraredReceiver; // port 4
// moving fork up and down
// uses UltraSonic to avoid going too far up or down
const int i_forkDown = 8; // we don't drop the fork lower than 8cm
const int i_forkUp = 16; // we don't lift the fork higher than 16cm
const int i_forkDownSpeed = 80; // speed for dropping the fork
const int i_forkUpSpeed = 120; // speed for lifting the fork (requires more force than dropping)
// driving forward and backward
// sometimes it would not start driving (too much resistance)
// solution is to start with much higher motor speed for 100ms
const int i_accelSpeed = 120; // accelerate from 0
const int i_accelDelay = 100; // delay in ms until normal drive speed
const int i_driveSpeed = 60; // normal driving speed
// turning left and right
// precision needed, but again slow speeds won't work (resistance)
// so high speed for very short time
const int i_turnSpeed = 170; // turn speed
const int i_turnDelay = 100; // milliseconds until full stop
void setup()
{
baseShieldMotorDriver.begin(); // driving
motorDriver.begin(); // fork
ultraSensor.begin(); // fork
infraredReceiver.begin(); // remote control
baseShieldMotorDriver.runMotors(0,0); // sometimes when uploading code, one motor spins very fast, this does not help
motorDriver.run(0); // sometimes when uploading code, this motor also spins three/four seconds, this does not help
}
void loop()
{
int key = infraredReceiver.read();
if(key>=0)
{
Serial.println(key);
switch (key) // about one in three key-presses is missed (unknown code in serial monitor like 4976 or 9824...)
{
case IR_PLUS_BUTTON:f_forkUp();break;
case IR_MINUS_BUTTON:f_forkDown();break;
case IR_PLAY_BUTTON:f_driveForward();break;
case IR_RETURN_BUTTON:f_driveReverse();break;
case IR_NEXT_BUTTON:f_turnLeft();break;
case IR_PREVIOUS_BUTTON:f_turnRight();break;
case IR_CLR_BUTTON:f_stopAllMotors();break;
default:break;
}
}
}
void f_forkUp()
{
int i_distance = ultraSensor.distanceCm(); // how far up are we ?
if ( i_distance < i_forkUp ) { motorDriver.run(i_forkUpSpeed); } // only move up when not too far up
delay(900);
motorDriver.run(0); // stop going up
}
void f_forkDown()
{
int i_distance = ultraSensor.distanceCm(); // how far down are we ?
if ( i_distance > i_forkDown ) { motorDriver.run(-i_forkDownSpeed); } // only move down when not too far down
delay(700);
motorDriver.run(0); // stop going down
}
void f_stopAllMotors() // emergency break ;-)
{
motorDriver.run(0); // stop fork movement
baseShieldMotorDriver.runMotors(0,0); // stop driving
}
void f_driveForward()
{
baseShieldMotorDriver.runMotors(i_accelSpeed,-i_accelSpeed); // high power
delay(i_accelDelay);
baseShieldMotorDriver.runMotors(i_driveSpeed,-i_driveSpeed); // normal drive power (forever)
}
void f_driveReverse()
{
baseShieldMotorDriver.runMotors(-i_accelSpeed,i_accelSpeed); // high power
delay(i_accelDelay);
baseShieldMotorDriver.runMotors(-i_driveSpeed,i_driveSpeed); // normal drive power (forever)
}
void f_turnLeft()
{
baseShieldMotorDriver.runMotors(i_turnSpeed,i_turnSpeed); // high power
delay(i_turnDelay); // short delay
baseShieldMotorDriver.runMotors(0,0); //stop now
}
void f_turnRight()
{
baseShieldMotorDriver.runMotors(-i_turnSpeed,-i_turnSpeed); // high power
delay(i_turnDelay); // short delay
baseShieldMotorDriver.runMotors(0,0); // stop now
}
I am happy to know the basics of Makeblock, the next project could be a better forklift, or something completely different.