Robots and robotics | mortenbs.com Last updated Jan 2012.
Project is active, and updates coming regularly...
Robotic vehicle, 24 volt DC, 2 x 400W 22A motors Purpose of this project is to build a remotely controlled machine, strong enough - to carry heavy things like cases of beer or even a person. The robot is currently being rebuilt. Two new motors arrived from Monster Scooter parts.
Making of 24 volt robotic vehicle, mortenbs.com How the 24 volt robotic vehichle was made. New changes and updates. Redesigning the robo, two new motors, new updated motor control, and changes of how the remote control works. Body changes, painting, welding and more. Showing the first motor control test.
2 x Currie Technologies XYD-6D motor, 24 VDC 400W (22A), bought from monsterscooterparts.com 3 x Battery GF 12 22Y, Maintenance free, Motive power (from electric forklift) 1 x Arduino Mega, bought from electrozone.dk 1 x E-Fly 2.4 GHz DSM transmitter 1 x E-Fly er61-2.4 GHz DSM 6ch receiver(Using 4 of 6 channels...) 1 x 24 volt DC motor control for two motors. (Made from power-inverter cabinet)
1 x Power inverter cabinet(Aluminum) 2 ch. analog circuit(To control the speed of the two motors from Arduino PWM signals) 2 ch. relay H-Bridgecircuit(To reverse the two motors) 16 ch. 5v to 12v switch circuit(To control the H-Bridge from an Arduino, other relays and other 12 volt equipment) 5 volt regulator circuit(Built into the cabinet for external 5 volt output)
//Robotic vehicle motor control v1.0.00100, mortenbs.com/it/robotics
//Controlling two 24 volt DC motors from remote control, using H-Bridge.
//Project is active, and updates coming regularly...
//Currently using Duemilanove while testing, because my Arduino Mega board was damaged.
//Not enough pins on the Duemilanove for lights, so not currently in use...
//-------------|------------------------|--------------------|-----------------------------------------
const boolean RMT_ALIGNMENT_MODE = false; //Use to align remote control, see below..
const boolean USE_SERIAL_DATA = true; //Use serial data for status and align.
const boolean USE_LIGHTS = false; //Use lights for status.
const boolean FULL_SPEED_RELAY_ONLY = false; //Turn off transistors and only use extra relays when full speed
const int SERIAL_DATA_RATE = 9600; //Serial data rate if enabled above
const byte RMT_SNAPPING_PCT = 5; //Snap remote values at pct: 0%, 50%, 100%
const int LOOP_DELAY_TIME_MS = 10; //Main loop delay time (pause)
//-------------|------------------------|--------------------|-----------------------------------------
const byte NONE = 0x00; //Motor free run, no power
const byte FWD = 0x01; //Motor forward
const byte REVERSE = 0x02; //Motor reverse
const byte BRAKE = 0x03; //Motor brake (handbrake)
//-------------|------------------------|--------------------|-----------------------------------------
const byte FLASHER_NONE = NONE; //No flash lights
const byte FLASHER_LEFT = 0x01; //Flash to the left
const byte FLASHER_RIGHT = 0x02; //Flash to the right
const byte FLASHER_CATASTROPHE = 0x03; //Flash catastrophe / problem
const byte FLASHER_SHIFTING = 0x04; //Flash shifting between left and right
//-------------|------------------------|--------------------|-----------------------------------------
const byte PIN_MOTOR_L_SPEED = 6; //PWM OUTPUT, power transistor for motor
const byte PIN_MOTOR_L_BRAKE = 12; //DIGITAL OUTPUT, external relay
const byte PIN_MOTOR_L_FULL_SPEED = NONE; //DIGITAL OUTPUT, external relay
const byte PIN_MOTOR_L_REVERSE = 7; //DIGITAL OUTPUT, internal 2st. relay
const byte PIN_MOTOR_R_SPEED = 9; //PWM OUTPUT, power transistor for motor
const byte PIN_MOTOR_R_BRAKE = 13; //DIGITAL OUTPUT, external relay
const byte PIN_MOTOR_R_FULL_SPEED = NONE; //DIGITAL OUTPUT, external relay
const byte PIN_MOTOR_R_REVERSE = 8; //DIGITAL OUTPUT, internal 2st. relay
const byte PIN_REMOTE_CH1 = 2; //PWM INPUT, remote control receiver ch.1
const byte PIN_REMOTE_CH2 = 3; //PWM INPUT, remote control receiver ch.2
const byte PIN_REMOTE_CH3 = 4; //PWM INPUT, remote control receiver ch.3
const byte PIN_REMOTE_CH4 = 5; //PWM INPUT, remote control receiver ch.4
const byte PIN_BUZZER = NONE; //Buzzer (small horn)
const byte PIN_HEADLIGHTS = 13; //Headlights (and rear lights)
const byte PIN_PARKING_LIGHTS = NONE; //Parking lights (FRONT+REAR L+R)
const byte PIN_FLASH_LIGHT_L = NONE; //Flash lights L (FRONT+REAR L)
const byte PIN_FLASH_LIGHT_R = NONE; //Flash lights R (FRONT+REAR R)
const byte PIN_BRAKE_LIGHTS = NONE; //Brake lights (REAR L+R)
const byte PIN_HIGH_BEAM_LIGHTS = NONE; //High beam lights (FRONT L+R)
//-------------|------------------------|--------------------|-----------------------------------------
const byte RMT_AXIS_A_HORI = PIN_REMOTE_CH1; //lf..rh
const byte RMT_AXIS_A_VERT = PIN_REMOTE_CH2; //dn..up
const byte RMT_AXIS_B_HORI = PIN_REMOTE_CH4; //lf..rh
const byte RMT_AXIS_B_VERT = PIN_REMOTE_CH3; //dn..up
//-------------|------------------------|--------------------|-----------------------------------------
//Use alignment mode to adjust following settings of your remote control configuration
const int RMT_AXIS_AH_MIN = 1892; //Value of ctrl when moved entirely left
const int RMT_AXIS_AH_MAX = 1155; //Value of ctrl when moved entirely right
const int RMT_AXIS_AV_MIN = 1099; //Value of ctrl when moved entirely down
const int RMT_AXIS_AV_MAX = 1876; //Value of ctrl when moved entirely up
const int RMT_AXIS_BH_MIN = 1791; //Value of ctrl when moved entirely left
const int RMT_AXIS_BH_MAX = 1247; //Value of ctrl when moved entirely right
const int RMT_AXIS_BV_MIN = 1230; //Value of ctrl when moved entirely down
const int RMT_AXIS_BV_MAX = 1830; //Value of ctrl when moved entirely up
//-------------|------------------------|--------------------|-----------------------------------------
float RMT_AXIS_AH_PCT = NONE; //Current value of that control (percents)
float RMT_AXIS_AV_PCT = NONE; //Current value of that control (percents)
float RMT_AXIS_BH_PCT = NONE; //Current value of that control (percents)
float RMT_AXIS_BV_PCT = NONE; //Current value of that control (percents)
//-------------|------------------------|--------------------|-----------------------------------------
byte MOTOR_L_SPEED = NONE; //MOTOR L SPEED (00..FF)
byte MOTOR_L_STATE = FWD; //MOTOR L STATE (NONE,FWD,BRAKE,REVERSE)
byte MOTOR_R_SPEED = NONE; //MOTOR R SPEED (00..FF)
byte MOTOR_R_STATE = FWD; //MOTOR R STATE (NONE,FWD,BRAKE,REVERSE)
//-------------|------------------------|--------------------|-----------------------------------------
byte FLASHER = FLASHER_NONE; //Flash light state
boolean HEADLIGHTS = false; //Headlights state
boolean HIGH_BEAM_LIGHTS = false; //High beam lights state
boolean PARKING_LIGHTS = false; //Parking lights state
boolean BRAKE_LIGHTS = false; //Brake lights state
boolean BUZZER = false; //Buzzer state
boolean FLASH_L = false; //Flash light L state (managed internally)
boolean FLASH_R = false; //Flash light R state (managed internally)
boolean REMOTE_IS_CONNECTED = false; //Is remote connected (managed internally)
//-------------|------------------------|--------------------|-----------------------------------------
float hAmt;//amount AH
float vAmt;//amount AV
float lAmt=NONE;//amount L [-100..100]
float rAmt=NONE;//amount R [-100..100]
int ah=NONE;
int av=NONE;
int bh=NONE;
int bv=NONE;
void readRemoteControl(){
ah=readPwmPin(RMT_AXIS_A_HORI);RMT_AXIS_AH_PCT=calcRmtPct(ah,RMT_AXIS_AH_MIN,RMT_AXIS_AH_MAX);
av=readPwmPin(RMT_AXIS_A_VERT);RMT_AXIS_AV_PCT=calcRmtPct(av,RMT_AXIS_AV_MIN,RMT_AXIS_AV_MAX);
bh=readPwmPin(RMT_AXIS_B_HORI);RMT_AXIS_BH_PCT=calcRmtPct(bh,RMT_AXIS_BH_MIN,RMT_AXIS_BH_MAX);
bv=readPwmPin(RMT_AXIS_B_VERT);RMT_AXIS_BV_PCT=calcRmtPct(bv,RMT_AXIS_BV_MIN,RMT_AXIS_BV_MAX);
REMOTE_IS_CONNECTED=((ah!=NONE)&&(av!=NONE)&&(bh!=NONE)&&(bv!=NONE));//if any is zero, the signal is not right, it must be off.
if(REMOTE_IS_CONNECTED==true){
if(RMT_AXIS_AV_PCT==50){vAmt=0;}else if(RMT_AXIS_AV_PCT<50){vAmt=map(RMT_AXIS_AV_PCT,0,50,-100,0);}else{vAmt=map(RMT_AXIS_AV_PCT,50,100,0,100);}
if(RMT_AXIS_AH_PCT==50){hAmt=0;}else if(RMT_AXIS_AH_PCT<50){hAmt=-map(RMT_AXIS_AH_PCT,0,50,-100,0);}else{hAmt=-map(RMT_AXIS_AH_PCT,50,100,0,100);}
}else{hAmt=NONE;vAmt=NONE;}
}
if(USE_SERIAL_DATA==true){Serial.print("Remote control is not connected");Serial.println(".");}
}
void mainProgram(){//ONLY RUNNING WHEN REMOTE CONTROL IS CONNECTED
if(!hadWelcome){welcome();}//WELCOME ON STATUP AND WHEN REMOTE IS RECONNECTED...
if(vAmt==NONE){//"V" IN MIDDLE
if(hAmt==NONE){lAmt=vAmt;rAmt=vAmt;}else//"V+H" BOTH IN MIDDLE = free/brk //ok
{lAmt=hAmt;rAmt=-hAmt;}//ROTATE LEFT OR RIGHT //ok
}else
if(vAmt<NONE){//"V" BELOW MIDDLE
if(hAmt==NONE){lAmt=vAmt;rAmt=vAmt;}else//"H" IN MIDDLE = same REVERSE speed
if(hAmt<NONE) {lAmt=(-hAmt)/2;rAmt=vAmt;}else//REVERSE and TURN LEFT
{lAmt=vAmt;rAmt=(hAmt)/2;}//REVERSE and TURN RIGHT
}else{//"V" ABOVE MIDDLE
if(hAmt==NONE){lAmt=vAmt;rAmt=vAmt;}else//"H" IN MIDDLE = same FWD speed
if(hAmt<NONE) {lAmt=(hAmt)/2;rAmt=vAmt;}else//FWD and TURN LEFT
{lAmt=vAmt;rAmt=(-hAmt)/2;}//FWD and TURN RIGHT
}
//convert "amount" to "speed" and "state":
if(lAmt==NONE){MOTOR_L_STATE=NONE;}else
if(lAmt<NONE){MOTOR_L_STATE=REVERSE;}else{MOTOR_L_STATE=FWD;}
MOTOR_L_SPEED=floatAbs(lAmt);
Old: Robo v1.0, my first small robotic vehicle This was the first small robotic vehicle I made from my brothers old toy. A new board was made to control the main- and the turning motor (in this case a small DC motor with a clutch.)
Main board and parts A relay based H-Bridge to control the main motor. A transistor based H-Bridge to control the turning motor. An Arduino Duemilanove board. A battery-pack for the Arduino. A battery-pack for the motors. A buzzer (for small horn). 1 x Sharp GP2Y0A02YK0F, Infrared Proximity Sensor Long Range (front). 2 x Sharp GP2Y0A21YK, IR distance sensor (short range) (left+right).
Also small front+rear modules was made for lights etc...
Robo v1.0, first test First test of my Arduino controlled robotic vehicle (v1.0)
void abortAutoNav(byte aDestMode){//is used if sensor in very long time, it tries something else (aDestMode)
DIRECTION_MOVE=NONE;DIRECTION_TURN=NONE;
buzzer(50);HEADLIGHTS_ON=false;//lights off
flasher(FLASHER_BOTH);n=0;while(n<500){n=n+1;update();}//flasher catastrophe... (problem)
resumeTaskMode(aDestMode);buzzer(30);
}
void pullInReverse(byte aDestMode){//is used if sensor and high speed FWD, it will pull in reverse for some time.
digitalWrite(FWD,false);digitalWrite(BWD,true);//IMMEDIATELY PULL IN REVERSE
digitalWrite(LEFT,true);digitalWrite(RIGHT,true);
digitalWrite(HEADLIGHTS,false);digitalWrite(HORN,true);
delay(200);
MODE=aDestMode;DIRECTION_MOVE=NONE;DIRECTION_TURN=NONE;aSensTime=0;n=0;v=0;//THEN RESUME
}
void autoNav(){n=0;v=0;nFlasher=NONE;
if(irLeft||irRight){aSensTime=aSensTime+1;}else{aSensTime=0;}//Serial.println(aSensTime);
if(aSensTime>=500){if(DESIRED_DIRECTION==RIGHT){abortAutoNav(MODE_ROTATION_RIGHT);}else{abortAutoNav(MODE_ROTATION_LEFT);}}else
if(irFront&&irLeft&&irRight){tempo(TEMPO_SLOW);moveBwd();stopTurn();}else//MOVE BWD (slow speed)
//if(irFront&&irLeft){tempo(TEMPO_MEDIUM);MODE=MODE_ROTATION_RIGHT;}else//ROTATE RIGHT
//if(irFront&&irRight){tempo(TEMPO_MEDIUM);MODE=MODE_ROTATION_LEFT;}else//ROTATE LEFT
if(irFront&&irLeft){if(DESIRED_DIRECTION==RIGHT){MODE=MODE_ROTATION_RIGHT;}else{MODE=MODE_ROTATION_LEFT;}}else//ROTATE TOWARDS DESIRED DIRECTION
if(irFront&&irRight){if(DESIRED_DIRECTION==RIGHT){MODE=MODE_ROTATION_RIGHT;}else{MODE=MODE_ROTATION_LEFT;}}else//ROTATE TOWARDS DESIRED DIRECTION
if(irLeft&irRight){tempo(TEMPO_MEDIUM);moveBwd();stopTurn();}else//MOVE BWD (turn smallest navigation) (medium speed)
if(irLeft){tempo(TEMPO_MEDIUM);moveFwd();turnRight();}else//MOVE FWD, and TURN RIGHT (medium speed)
if(irRight){tempo(TEMPO_MEDIUM);moveFwd();turnLeft();}else{//MOVE FWD, and TURN LEFT (medium speed)
if(irFront){pullInReverse(MODE_ROTATION_LEFT);}else//ROTATE TO SMALLEST
tempo(TEMPO_FAST);moveFwd();stopTurn();//MOVE FWD (fast speed)
}
}
switch(BEHAVIOUR){
case BEHAVIOUR_SILENT:aLen=10;aPause=100;aPauseTurn=35;break;
case BEHAVIOUR_RELAXED:aLen=10;aPause=15;aPauseTurn=25;break;
case BEHAVIOUR_ACTIVE:aLen=10;aPause=12;aPauseTurn=20;break;
case BEHAVIOUR_ANGRY:aLen=8;aPause=10;aPauseTurn=15;break;
}
void tempo(byte aTempo){
switch(BEHAVIOUR){
case BEHAVIOUR_SILENT:switch(aTempo){
case TEMPO_SLOW:aMoveLen=60;aMoveSplit=2;break; //SILENT SLOW
case TEMPO_FAST:aMoveLen=60;aMoveSplit=4;break; //SILENT FAST
default:aMoveLen=60;aMoveSplit=3;break;}break; //SILENT MEDIUM
case BEHAVIOUR_RELAXED:switch(aTempo){
case TEMPO_SLOW:aMoveLen=30;aMoveSplit=2;break; //RELAXED SLOW
case TEMPO_FAST:aMoveLen=30;aMoveSplit=4;break; //RELAXED FAST
default:aMoveLen=30;aMoveSplit=3;break;}break; //RELAXED MEDIUM
case BEHAVIOUR_ACTIVE:switch(aTempo){
case TEMPO_SLOW:aMoveLen=20;aMoveSplit=3;break; //ACTIVE SLOW
case TEMPO_FAST:aMoveLen=20;aMoveSplit=6;break; //ACTIVE FAST
default:aMoveLen=25;aMoveSplit=5;break;}break; //ACTIVE MEDIUM
case BEHAVIOUR_ANGRY:switch(aTempo){
case TEMPO_SLOW:aMoveLen=15;aMoveSplit=3;break; //ANGRY SLOW
case TEMPO_FAST:aMoveLen=15;aMoveSplit=5;break; //ANGRY FAST
default:aMoveLen=15;aMoveSplit=4;break;}break; //ANGRY MEDIUM
}
}
void hornBehaviour(){
switch(BEHAVIOUR){
//case BEHAVIOUR_SILENT:break;
//case BEHAVIOUR_RELAXED:break;
case BEHAVIOUR_ACTIVE:buzzer(1);break;
case BEHAVIOUR_ANGRY:buzzer(2);break;
}
}
//-----------------------------------------------------------------------------------------------------
void update(){
aMovePos=aMovePos+1;if(aMovePos>aMoveLen){aMovePos=0;}//MOVING SPEED BALANCE
digitalWrite(FWD,(DIRECTION_MOVE==FWD)&&((MODE!=MODE_AUTONAV)||(aMovePos<=aMoveSplit)));//MOVE FWD
digitalWrite(BWD,(DIRECTION_MOVE==BWD)&&((MODE!=MODE_AUTONAV)||(aMovePos<=aMoveSplit)));//MOVE BWD
digitalWrite(LEFT,DIRECTION_TURN==LEFT);//TURN LEFT
digitalWrite(RIGHT,DIRECTION_TURN==RIGHT);//TURN RIGHT
digitalWrite(HEADLIGHTS,HEADLIGHTS_ON&&USE_HEADLIGHTS);digitalWrite(HORN,USE_HORN&&(nHorn>0));if(nHorn>0){nHorn=nHorn-1;}//HEADLIGHTS AND HORN
if(USE_FLASHLIGHTS){nFlash=nFlash+1;if(nFlash>=FLASHER_LENGTH){nFlash=0;blFlash=blFlash==false;}//MANAGE FLASHER
digitalWrite(FLASHLIGHT_LEFT,blFlash&&((nFlasher==FLASHER_LEFT)||(nFlasher==FLASHER_BOTH)||(nFlasher==FLASHER_SHIFT)));//FLASH LEFT
digitalWrite(FLASHLIGHT_RIGHT,(blFlash&&((nFlasher==FLASHER_RIGHT)||(nFlasher==FLASHER_BOTH)))||((nFlasher==FLASHER_SHIFT)&&(blFlash==false)));//FLASH RIGHT
}delay(MAIN_ROUTINE_DELAY);
}