For YRL Robot Arm
Diff: robotarm.cpp
- Revision:
- 0:b14dfd8816da
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/robotarm.cpp Fri Mar 03 13:28:54 2017 +0000 @@ -0,0 +1,228 @@ +/* University of York Robotics Laboratory Robot Arm Controller Board + * + * Robot Arm Controller + * + * File: robotarm.cpp + * + * (C) Dept. Electronics & Computer Science, University of York + * + * James Hilder, Alan Millard, Shuhei Miyashita, Homero Elizondo, Jon Timmis + * + * February 2017, Version 1.0 + */ + +#include "robotarm.h" + +Display display; //Connects to i2c(p28,p27) +Remote remote; +Serial pc(USBTX,USBRX); +Servo servo(p9,p10); +short target_base = 2048; +short target_shoulder = 2048; +short target_elbow = 2048; +short target_wrist = 2048; + +void Robotarm::init() +{ + pc.baud(115200); + //hardware_test(); + pc.printf("Robot Arm Controller\nSoftware Version %1.2f\n",SOFTWARE_VERSION_CODE); + display.init(); + init_servos(); +} + +void Robotarm::init_servos() +{ + Timeout fail_timeout; + fail_timeout.attach(this,&Robotarm::fail_init,2); + display.clear_display(); + wait(0.1); + display.set_position(0,0); + display.write_string("CHECKING SERVOS:"); + pc.printf("Initialising robot arm\n"); + wait(0.1); + + if(HAS_BASE) { + display.set_position(1,0); + display.write_string("BASE:"); + pc.printf("Check servo %d [BASE]:",BASE); + if(servo.GetModelNumber(BASE) != MX28_MODEL) fail_init(); + servo.SetLowVoltageLimit(BASE, LOW_VOLTAGE_LIMIT); + servo.SetHighVoltageLimit(BASE, HIGH_VOLTAGE_LIMIT); + servo.SetTemperatureLimit(BASE, HIGH_TEMPERATURE_LIMIT); + //servo.SetCWLimit(BASE, 0); + //servo.SetCCWLimit(BASE, 0); + servo.LockEeprom(BASE); + pc.printf("OK\n"); + display.set_position(1,9); + display.write_string("[OK]"); + wait(0.2); + } + + if(HAS_SHOULDER) { + display.set_position(1,0); + display.write_string("SHOULDER: "); + pc.printf("Check servo %d [SHOULDER]:",SHOULDER); + if(servo.GetModelNumber(SHOULDER) != MX28_MODEL) fail_init(); + servo.SetLowVoltageLimit(SHOULDER, LOW_VOLTAGE_LIMIT); + servo.SetHighVoltageLimit(SHOULDER, HIGH_VOLTAGE_LIMIT); + servo.SetTemperatureLimit(SHOULDER, HIGH_TEMPERATURE_LIMIT); + //servo.SetCWLimit(SHOULDER, 0); + //servo.SetCCWLimit(SHOULDER, 0); + servo.LockEeprom(SHOULDER); + pc.printf("OK\n"); + display.set_position(1,9); + display.write_string("[OK]"); + wait(0.2); + } + + if(HAS_ELBOW) { + display.set_position(1,0); + display.write_string("ELBOW: "); + pc.printf("Check servo %d [ELBOW]:",ELBOW); + if(servo.GetModelNumber(ELBOW) != MX28_MODEL) fail_init(); + servo.SetLowVoltageLimit(ELBOW, LOW_VOLTAGE_LIMIT); + servo.SetHighVoltageLimit(ELBOW, HIGH_VOLTAGE_LIMIT); + servo.SetTemperatureLimit(ELBOW, HIGH_TEMPERATURE_LIMIT); + //servo.SetCWLimit(ELBOW, 0); + //servo.SetCCWLimit(ELBOW, 0); + servo.LockEeprom(ELBOW); + pc.printf("OK\n"); + display.set_position(1,9); + display.write_string("[OK]"); + wait(0.2); + } + + if(HAS_WRIST) { + display.set_position(1,0); + display.write_string("WRIST: "); + pc.printf("Check servo %d [WRIST]:",WRIST); + if(servo.GetModelNumber(WRIST) != AX12_MODEL) fail_init(); + servo.SetLowVoltageLimit(WRIST, LOW_VOLTAGE_LIMIT); + servo.SetHighVoltageLimit(WRIST, HIGH_VOLTAGE_LIMIT); + servo.SetTemperatureLimit(WRIST, HIGH_TEMPERATURE_LIMIT); + //servo.SetCWLimit(WRIST, 0); + //servo.SetCCWLimit(WRIST, 0); + servo.LockEeprom(WRIST); + pc.printf("OK\n"); + display.set_position(1,9); + display.write_string("[OK]"); + wait(0.2); + } + + fail_timeout.detach(); +} + +float zero_time_delay; +Timeout zero_timeout; + +void Robotarm::zero_servos(float time_delay) +{ + if(time_delay <= 0)_zero_servos(); + else { + zero_time_delay = time_delay; + display.clear_display(); + display.set_position(0,0); + display.write_string("ZEROING ARM IN"); + display.set_position(1,0); + char message[17]; + sprintf(message,"%2.1f SECONDS",zero_time_delay); + display.write_string(message); + if(zero_time_delay < 0.1)zero_timeout.attach(this,&Robotarm::_zero_servos,zero_time_delay); + else zero_timeout.attach(this,&Robotarm::_zero_servos_display_update,0.1); + } +} + +void Robotarm::_zero_servos_display_update() +{ + display.set_position(1,0); + zero_time_delay-=0.1; + char message[17]; + sprintf(message,"%2.1f SECONDS",zero_time_delay); + display.write_string(message); + if(zero_time_delay < 0.1) zero_timeout.attach(this,&Robotarm::_zero_servos,zero_time_delay); + else zero_timeout.attach(this,&Robotarm::_zero_servos_display_update,0.1); +} + +void Robotarm::_zero_servos() +{ + display.clear_display(); + servo.SetGoal(BASE,2048,1); + servo.SetGoal(SHOULDER,2048,1); + servo.SetGoal(ELBOW,2048,1); + servo.trigger(); + target_base = 2048; + target_shoulder = 2048; + target_elbow = 2048; + target_wrist = 2048; +} + +void Robotarm::fail_init() +{ + display.clear_display(); + display.set_position(0,0); + display.write_string("SERVO ERROR"); + while(1) { + remote.set_led(1); + wait(0.2); + remote.set_led(0); + wait(0.1); + } +} + +void Robotarm::hardware_test() +{ + pc.printf("\nBeginning extended hardware test\n"); + wait(0.5); + pc.printf("Scanning for servos:\n"); + servo.ScanForServos(); + pc.printf("\nDone."); + while(1); +} + +// Important: initialise_servo() is ONLY used when setting the servo IDs for the first time, +// do not run once the arm has been set up! +void Robotarm::initialise_servo(int target_servo) +{ + pc.printf("RUNNING SERVO SETUP ROUTINE FOR SERVO %d\n\n",target_servo); + + // MX-28s default to a baud rate of 57600 with delay time of 500us + servo.SetInitBaud(57600, 250); + + int model = servo.GetModelNumber(1); + if(model != MX28_MODEL) { + pc.printf("Error: No MX-28 servo with ID 1 found...\n"); + while(1); + } + servo.DebugData(1); + + pc.printf("\n\nSetting up MX-28 servo to ID %d\n",target_servo); + servo.SetID(0x01,target_servo); + wait(0.25); + //Uncomment the following block to setup servo to use 1Mbps baud rate + /* + pc.printf("Setting baud rate for servo to 1000000\n"); + servo.SetBaud(target_servo,1); + wait(0.25); + pc.printf("Setting return delay time for servo to %dus\n",RETURN_DELAY + RETURN_DELAY); + servo.SetDelayTime(target_servo,RETURN_DELAY); + wait(0.25); + pc.printf("Resetting connecting baud rate\n"); + servo.SetInitBaud(1000000, RETURN_DELAY); + wait(0.25); + */ + pc.printf("Getting servo data:\n"); + servo.DebugData(target_servo); + while(0.25); +} + +/* + * Copyright 2016 University of York + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ \ No newline at end of file