Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
main.cpp
- Committer:
- kageyuta
- Date:
- 2018-12-17
- Revision:
- 1:3ae63be5592b
- Parent:
- 0:111abd91b0cb
File content as of revision 1:3ae63be5592b:
//2018/12/15 腰回転をシリンダに変更
#include "mbed.h"
#include "EC.h"
#include "KondoServo.h"
#include "hcsr04.h"
Serial pc(USBTX,USBRX);
Timer timer;
//パラメタ
double dutylimit = 0.4; // duty出力の上限値
int resolution = 1000; //エンコーダの分解能×逓倍
int ecgear = 35; //エンコーダのギアの歯数
double Kp = 0.342000; //P値
double Ki = 0.013062; //I値
double Kd = 0.003266; //D値
double leg_wait_time = 0.5; //脚の伸縮にかかる時間
double turn_wait_time = 0.7; //旋回にかかる時間
double target_max = 300; //直動機構の目標座標の上限(オーバーシュートを考慮して短めに設定)
double target_min = 20; //直動機構の目標座標の下限(オーバーシュートを考慮して短めに設定)
double rail_len = 710;
double turn_error=10; //旋回の際のY脚のずれの許容誤差
double servo_iniposi=105; //サーボ初期角度
double target_plot[][2]={ //(mode,target) mode 0→standby 1→straight 2→turn 3→sand dune 4→tussock 5→wait_shagai 6→mountain~finish
{0,0},
{1,3450},
{2,-45},
{3,0},
{2,-45},
{1,1030},
{2,90},
{1,2390},
{2,90},
{5,0},
{6,0}
};
//定数
#define Pi 3.14159265359 //円周率π
//変数
double linear_posi=0; //直線移動での距離 1プロットごとにリセットする?
int target_num=0; //現在の目標プロット
//ピン宣言
PwmOut motor_f(p21); //モータ正転
PwmOut motor_b(p22); //モータ逆転
DigitalIn switch_max(p9); //直動機構の上限のリミットスイッチ
DigitalIn switch_min(p8); //直動機構の下限のリミットスイッチ
DigitalIn switch_x(p7); //X脚の接地を判定するスイッチ(今後実装予定)
DigitalIn switch_y(p5); //Y脚の接地を判定するスイッチ(今後実装予定)
DigitalIn switch_hand(p6); //ゲルゲ回収アームのスイッチ
DigitalOut air_x(p18); //X脚の伸縮
DigitalOut air_y(p17); //Y脚の伸縮
DigitalOut air_x_sub(p14); //X脚の先端の伸縮(今後実装予定)
DigitalOut air_turn(p16); //Y脚の先端の伸縮(今後実装予定)
DigitalOut air_hand(p19); //ゲルゲ回収アームのハンド部開閉
DigitalOut air_trig(p20); //ゲルゲ持ち上げ機構のロック解除
Ec ec(p24,p23,NC,resolution,0.01); //直動機構のエンコーダ
KondoServo servo(p28,p27,1,115200); //旋回用のシリアルサーボ
HCSR04 sensor(p30, p29);
void setup();
void out(double);//モーターの出力
void move(double,double); //PID (移動先の座標(機体内)[mm],許容誤差の絶対値[mm])
void up_x();
void down_x();
void up_y();
void down_y();
void move_x (double,double);//X脚を移動
void move_y (double,double);//Y脚を移動
void reset(); //脚位置の初期化
void turn(double); //旋回動作
void straight(double); //目的地まで直進
void wait_MR1();
int main() {
setup();
while(switch_x==1){}
reset();
while(1) {
switch((int)(target_plot[target_num][0])){
case 0:
wait_MR1();
break;
case 1:
straight(target_plot[target_num][1]);
pc.printf("%f\r\n",linear_posi);
//while(1);
break;
case 2:
turn(target_plot[target_num][1]);
break;
case 3:
move_x(target_max,10);
move_y(target_min,10);
move_x(target_max,10);
move_y(target_min,10);
move_x(rail_len*0.5,10);
default:
break;
}
target_num++;
linear_posi=0;
}
}
double get_dist(){
sensor.start();
wait_ms(50); //sensor.start()で信号を送ったあと反射波が帰ってきてから距離データが更新されるため、少し待つ必要がある。
//何ループも回す場合は不要。また、時間は適当だから調整が必要。
return sensor.get_dist_cm();
}
//初期設定
void setup()
{
motor_f.period_us(100);
motor_b.period_us(100);
switch_max.mode(PullUp);
switch_min.mode(PullUp);
switch_x.mode(PullUp);
switch_y.mode(PullUp);
switch_hand.mode(PullUp);
air_x=0;
air_y=0;
air_x_sub=0;
air_turn=0;
air_hand=0;
air_trig=0;
servo.setSpeed(0,127);
wait_us(1000);
servo.init();
//servo.set_degree(0,servo_iniposi);
}
//モーターの出力
void out (double duty)
{
if(duty > 0) { //入力duty比が正の場合
if(switch_max == 0){ //上限のリミットスイッチが押されていない場合
if( fabs( duty ) < dutylimit ) { //制限値内
motor_f = fabs(duty);
motor_b = 0;
} else { //制限値超
motor_f = dutylimit;
motor_b = 0;
}
} else { //上限のリミットスイッチが押されている場合
motor_f = 0;
motor_b = 0;
//pc.printf("%f\r\n",1.0*ecgear*Pi*ec.getCount()/resolution);
}
} else {//入力duty比が負の場合
if(switch_min == 0){ //下限のリミットスイッチが押されていない場合
if( fabs(duty) < dutylimit) { //制限値内
motor_f = 0;
motor_b = fabs(duty);
} else { //制限値超
motor_f = 0;
motor_b = dutylimit;
}
}else { //下限のリミットスイッチが押されている場合
motor_f = 0;
motor_b = 0;
}
}
}
//PID制御
void move(double target,double error) //(移動先の座標(機体内)[mm],許容誤差の絶対値[mm])
{
double pile=0,deviation,distance,distance_old=0;
int i=0;
timer.start();
while(1) {
distance = 1.0*ecgear*Pi*ec.getCount()/resolution;
deviation = target - distance;
pile += deviation;
double period = timer.read();
out(deviation * Kp - (distance - distance_old) / period * Kd + pile * Ki * period);
timer.reset();
distance_old = distance;
if (fabs(deviation) < error) {
i++;
if (i==3000) {
out(0);
timer.stop();
//pc.printf("%f\r\n",1.0*ecgear*Pi*ec.getCount()/resolution);
break;
}
} else {
i=0;
}
}
}
//X脚を上げる
void up_x()
{
air_x =1;
wait(leg_wait_time);
}
//X脚を降ろす
void down_x()
{
air_x =0;
wait(leg_wait_time);
}
//Y脚を上げる
void up_y()
{
air_y =1;
wait(leg_wait_time);
}
//Y脚を降ろす
void down_y()
{
air_y =0;
wait(leg_wait_time);
}
//X脚を移動
void move_x (double x,double error)
{
//pc.printf("x target=%f , posi=%f\r\n",x,linear_posi);
double pre_posi=1.0*ecgear*Pi*ec.getCount()/resolution;
up_x();
if(x>target_max)x=target_max;
else if(x<target_min)x=target_min;
move(x,error);
down_x();
linear_posi+=1.0*ecgear*Pi*ec.getCount()/resolution-pre_posi;
}
//Y脚を移動
void move_y (double y,double error)
{
//pc.printf("y target=%f , posi=%f\r\n",y,linear_posi);
up_y();
if(y>target_max)y=target_max;
else if(y<target_min)y=target_min;
move(y,error);
down_y();
}
int k=0;
//脚位置の初期化
void reset()
{
//servo.set_degree(0,servo_iniposi);
up_x();
while(switch_min == 0) {
out(-0.2);
k++;
if(k>5000){
servo.set_degree(0,servo_iniposi);
k=0;
}
}
//pc.printf("%d\r\n",ec.getCount());
ec.reset();
out(0);
down_x();
//pc.printf("%d\r\n",ec.getCount());
}
//旋回動作
void turn(double degree)
{
if(fabs(1.0*ecgear*Pi*ec.getCount()/resolution-rail_len*0.5)>turn_error){
move_y(rail_len*0.5,turn_error);
}
/* bool turn_finish=0;
while(turn_finish==0){
double degree_out=0;
if(fabs(degree)<=45){
degree_out=degree;
turn_finish=1;
}else if(degree>45){
degree_out=45;
degree-=45;
}else{
degree_out=-45;
degree+=45;
}*///!!削除
if(degree == 45){
up_y();
air_turn=1;
wait(turn_wait_time);
down_y();
up_x();
air_turn=0;
wait(turn_wait_time);
down_x();
} else if(degree == 90){
up_y();
air_turn=1;
wait(turn_wait_time);
down_y();
up_x();
air_turn=0;
wait(turn_wait_time);
down_x();
up_y();
air_turn=1;
wait(turn_wait_time);
down_y();
up_x();
air_turn=0;
wait(turn_wait_time);
down_x();
}
if(degree == -45){
up_x();
air_turn=1;
wait(turn_wait_time);
down_x();
up_y();
air_turn=0;
wait(turn_wait_time);
down_y();
}else if(degree == -90){
up_x();
air_turn=1;
wait(turn_wait_time);
down_x();
up_y();
air_turn=0;
wait(turn_wait_time);
down_y();
up_x();
air_turn=1;
wait(turn_wait_time);
down_x();
up_y();
air_turn=0;
wait(turn_wait_time);
down_y();
}else{}
}
void straight(double target){
while(1){
double xleg_posi=1.0*ecgear*Pi*ec.getCount()/resolution; //機体内のX脚位置
double dist=target-linear_posi;
pc.printf("leg=%f,dist=%f,linear_posi=%f\r\n",xleg_posi,dist,linear_posi);
if(fabs(dist)<10){
break;
}else if((dist>0 && dist<=(target_max-xleg_posi)) || (dist<0 && dist>=(target_min-xleg_posi))){
move_x(xleg_posi+dist,10);
}else if(dist<0){
pc.printf("distance < 0");
break;
}else if(dist<=(target_max-target_min-10)){
if(dist<=(rail_len*0.5-target_min-10)){
move_y(dist+xleg_posi-rail_len*0.5,10);
}else{
move_y(target_min,10);
}
}else{
if(xleg_posi<(rail_len*0.5))move_x(target_max,10);
else move_y(target_min,10);
}
}
}
void wait_MR1(){
while(switch_x==1){
}
//while(switch_hand==0);
air_hand=1;
wait(1);
}