久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4442|回復: 6
打印 上一主題 下一主題
收起左側

基于arduino的PID平衡車程序

  [復制鏈接]
跳轉到指定樓層
樓主
ID:931725 發表于 2021-6-3 11:24 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
#include <PS2X_lib.h>  //for v1.6
#define PS2_DAT        A0  //14   
#define PS2_CMD        A1  //15
#define PS2_SEL        A2  //16
#define PS2_CLK        A3  //17
#define pressures   true
#define rumble      true
PS2X ps2x;
int error = 0;
byte type = 0;
byte vibrate = 0;
#define left_turn   0x06//按鍵左旋轉
#define right_turn  0x07//按鍵右旋轉
struct _pid{
    float SetSpeed;            //定義設定值
    float ActualSpeed;        //定義實際值
    float err;                //定義偏差值
    float err_last;            //定義上一個偏差值
    float Kp,Ki,Kd;            //定義比例、積分、微分系數
    float voltage;          //定義電壓值(控制執行器的變量)
    float integral;            //定義積分值
}pid;
void PID_init(){               //PID初始化,調整參數
    printf("PID_init begin \n");
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.voltage=0.0;
    pid.integral=0.0;
    pid.Kp=0.2;
    pid.Ki=0.015;
    pid.Kd=0.2;
    printf("PID_init end \n");
}
float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    pid.integral+=pid.err;
    pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}
enum {
  enSTOP = 1,
  enRUN,
  enBACK,
  enLEFT,
  enRIGHT,
  enUPLEFT,
  enUPRIGHT,
  enDOWNLEFT,
  enDOWNRIGHT
} enCarState;
#define level1  0x08//速度控制標志位1
#define level2  0x09//速度控制標志位2
#define level3  0x0A//速度控制標志位3
#define level4  0x0B//速度控制標志位4
#define level5  0x0C//速度控制標志位5
#define level6  0x0D//速度控制標志位6
#define level7  0x0E//速度控制標志位7
#define level8  0x0F//速度控制標志位8
int Left_motor_back = 9;     //左電機后退(IN1)
int Left_motor_go = 5;     //左電機前進(IN2)
int Right_motor_go = 6;    // 右電機前進(IN3)
int Right_motor_back = 10;    // 右電機后退(IN4)
int buzzer = 8;//設置控制蜂鳴器的數字IO腳

int control = 150;//PWM控制量

int g_carstate = enSTOP; //  1前2后3左4右0停止
int g_servostate = 0;  //1左搖 2 右搖
/*超聲波*/
int Echo = A5;  // Echo回聲腳(P2.0)
int Trig = A4; //  Trig 觸發腳(P2.1)
int Distance = 0;


/*舵機*/
int servopin = 2;  //設置舵機驅動腳到數字口2

/*點燈*/
int Led = 13; //
/*滅火*/
int Fire = 12; //
int speakerPin = 3;  //11
void PS2_Ctrol(void);


void setup()
{
  //初始化電機驅動IO為輸出方式
  pinMode(Left_motor_go, OUTPUT); // PIN 5 (PWM)
  pinMode(Left_motor_back, OUTPUT); // PIN 9 (PWM)
  pinMode(Right_motor_go, OUTPUT); // PIN 6 (PWM)
  pinMode(Right_motor_back, OUTPUT); // PIN 10 (PWM)
  pinMode(buzzer, OUTPUT); //設置數字IO腳模式,OUTPUT為輸出
  pinMode(Echo, INPUT);    // 定義超聲波輸入腳
  pinMode(Trig, OUTPUT);   // 定義超聲波輸出腳
  pinMode(servopin, OUTPUT);     //設定舵機接口為輸出接口
  pinMode(Led, OUTPUT);   // 定義點燈輸出腳
  pinMode(Fire, OUTPUT);   // 定義滅火輸出
  pinMode(speakerPin, OUTPUT); //定義唱歌引腳

  //digitalWrite(buzzer,HIGH);    //不發聲
  // digitalWrite(Led,HIGH);
  // digitalWrite(Fire,HIGH);
  Serial.begin(9600);        //波特率9600 (藍牙通訊設定波特率)
  /*PS2初始化*/
  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
  type = ps2x.readType();
  switch (type) {
    case 0:
      Serial.print("Unknown Controller type found ");
      break;
    case 1:
      Serial.print("DualShock Controller found ");  //這種
      break;
    case 2:
      Serial.print("GuitarHero Controller found ");
      break;
    case 3:
      Serial.print("Wireless Sony DualShock Controller found ");
      break;
  }

}

void Distance_test()   // 量出前方距離
{
  digitalWrite(Trig, LOW);   // 給觸發腳低電平2μs
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);  // 給觸發腳高電平10μs,這里至少是10μs
  delayMicroseconds(10);
  digitalWrite(Trig, LOW);    // 持續給觸發腳低電
  float Fdistance = pulseIn(Echo, HIGH);  // 讀取高電平時間(單位:微秒)
  Fdistance = Fdistance / 58;    //為什么除以58等于厘米,  Y米=(X秒*344)/2
  // X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
  //Serial.print("Distance:");      //輸出距離(單位:厘米)
  //Serial.println(Fdistance);         //顯示距離
  Distance = Fdistance;
}

void run()     // 前進
{
  int speed=PID_realize(200.0);
  analogWrite(Right_motor_back, speed);
  analogWrite(Left_motor_back, speed);
  analogWrite(Right_motor_go, control); //PWM比例0~255調速,左右輪差異略增減
  analogWrite(Left_motor_go, control - 25); //PWM比例0~255調速,左右輪差異略增減
  //delay(time * 100);   //執行時間,可以調整
}

void brake()         //剎車,停車
{
  int speed=PID_realize(0.0);
  analogWrite(Right_motor_back, speed);
  analogWrite(Left_motor_back, speed);
  //delay(time * 100);//執行時間,可以調整
}

void left()         //左轉(左輪不動,右輪前進)
{
  int speed=PID_realize(200.0);
  analogWrite(Right_motor_back, speed);
  analogWrite(Left_motor_back, 0);
}

void right()        //右轉(右輪不動,左輪前進)
{
  int speed=PID_realize(200.0);
  analogWrite(Right_motor_back, speed);
  analogWrite(Left_motor_back, speed);
}
void upright()        //右上(右輪不動,左輪前進)
{
  digitalWrite(Right_motor_back, LOW);
  digitalWrite(Left_motor_back, LOW);
  digitalWrite(Right_motor_go, HIGH); // 右電機前進
  digitalWrite(Left_motor_go, HIGH); // 左電機前進

  analogWrite(Right_motor_go, 120); //PWM比例0~255調速,左右輪差異略增減  右電機減速
  analogWrite(Left_motor_go, 180); //PWM比例0~255調速,左右輪差異略增減
}
void front_detection()
{
  //此處循環次數減少,為了增加小車遇到障礙物的反應速度
  for (int i = 0; i <= 5; i++) //產生PWM個數,等效延時以保證能轉到響應角度
  {
//    servopulse(servopin, 90); //模擬產生PWM
  }
}

void left_detection()
{
  for (int i = 0; i <= 15; i++) //產生PWM個數,等效延時以保證能轉到響應角度
  {
//    servopulse(servopin, 175); //模擬產生PWM
  }
}

void right_detection()
{
  for (int i = 0; i <= 15; i++) //產生PWM個數,等效延時以保證能轉到響應角度
  {
//    servopulse(servopin, 5); //模擬產生PWM
  }
}



void loop()
{
  int temp = 0;
  PS2_Ctrol();
  switch (g_carstate)
  {
    case enRUN: run();  break;
    case enLEFT: left();  break;
    case enRIGHT: right(); break;
    //case enBACK: back(); break;
    default: break;
  }
  switch (g_servostate)
  {
    case 0: if (temp != 0) {
        temp = 0;
        front_detection();
      } break;
    case 1: if (temp != 1) {
        temp = 1;
        left_detection();
      } break;
    case 2: if (temp != 2) {
        temp = 2;
        right_detection();
      } break;
    default: break;
  }
  delay(50);
}

void PS2_Ctrol(void)
{
  int X1, Y1, X2, Y2;
  if (error == 1) //skip loop if no controller found
    return;
  if (type != 1) //skip loop if no controller found
    return;
  //DualShock Controller
  ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed

  if (ps2x.Button(PSB_START))        //will be TRUE as long as button is pressed
    Serial.println("Start is being held");
  if (ps2x.Button(PSB_SELECT))
    Serial.println("Select is being held");

  if (ps2x.Button(PSB_PAD_UP)) {     //will be TRUE as long as button is pressed
    Serial.print("Up held this hard: ");
    Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
    g_carstate = enRUN;
  }
  else if (ps2x.Button(PSB_PAD_RIGHT)) {
    Serial.print("Right held this hard: ");
    Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
    g_carstate = enRIGHT;
  }
  else if (ps2x.Button(PSB_PAD_LEFT)) {
    Serial.print("LEFT held this hard: ");
    Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
    g_carstate = enLEFT;
  }
  else if (ps2x.Button(PSB_PAD_DOWN)) {
    Serial.print("DOWN held this hard: ");
    Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);
    g_carstate = enBACK;
  }
  else
  {
    g_carstate = enSTOP;
  }

  vibrate = ps2x.Analog(PSAB_CROSS);  //this will set the large motor vibrate speed based on how hard you press the blue (X) button
  if (ps2x.NewButtonState())
  { //will be TRUE if any button changes state (on to off, or off to on)
    if (ps2x.Button(PSB_L3))//停止
    {
      g_carstate = enSTOP;
      Serial.println("L3 pressed");
    }
    if (ps2x.Button(PSB_R3)) //復位
    {
      front_detection();
      Serial.println("R3 pressed");
    }
    if (ps2x.Button(PSB_L2)) //加速
    {
      Serial.println("L2 pressed");
      control += 50;
      if (control > 255)
      {
        control = 255;
      }
    }
    if (ps2x.Button(PSB_R2))
    {
      Serial.println("R2 pressed");
      control -= 50;
      if (control < 50)
      {
        control = 100;
      }
    }
    if (ps2x.Button(PSB_TRIANGLE)) //點燈
    {
      Serial.println("Triangle pressed");
      digitalWrite(Led, !digitalRead(Led));  //反轉電平
    }
  }

  if (ps2x.ButtonPressed(PSB_CIRCLE))//滅火              //will be TRUE if button was JUST pressed
  {
    Serial.println("Circle just pressed");
    digitalWrite(Fire, !digitalRead(Fire));   //反轉電平
  }
  if (ps2x.NewButtonState(PSB_CROSS))//鳴笛              //will be TRUE if button was JUST pressed OR released
  {
    Serial.println("X just changed");
//   whistle();
  }
  if (ps2x.ButtonReleased(PSB_SQUARE))//唱歌             //will be TRUE if button was JUST released
  {
    Serial.println("Square just released");
   //PlayTest();
  }


  if (ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1))
  { //print stick values if either is TRUE
    Serial.print("Stick Values:");
    Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX
    Serial.print(",");
    Serial.print(ps2x.Analog(PSS_LX), DEC);
    Serial.print(",");
    Serial.print(ps2x.Analog(PSS_RY), DEC);
    Serial.print(",");
    Serial.println(ps2x.Analog(PSS_RX), DEC);
    Y1 = ps2x.Analog(PSS_LY);
    X1 = ps2x.Analog(PSS_LX);
    Y2 = ps2x.Analog(PSS_RY);
    X2 = ps2x.Analog(PSS_RX);

    /*左搖桿*/
    if (Y1 < 5 && X1 > 80 && X1 < 180) //上
    {
      g_carstate = enRUN;
    }
    else if (Y1 > 230 && X1 > 80 && X1 < 180) //下
    {
      g_carstate = enBACK;
    }
    else if (X1 < 5 && Y1 > 80 && Y1 < 180) //左
    {
      g_carstate = enLEFT;
    }
    else if (Y1 > 80 && Y1 < 180 && X1 > 230)//右
    {
      g_carstate = enRIGHT;
    }
    else if (Y1 <= 80 && X1 <= 80) //左上
    {
      g_carstate = enUPLEFT;
    }
    else if (Y1 <= 80 && X1 >= 180) //右上
    {
      g_carstate = enUPRIGHT;
    }
    else if (X1 <= 80 && Y1 >= 180) // 左下
    {
      g_carstate = enDOWNLEFT;
    }
    else if (Y1 >= 180 && X1 >= 180) //右下
    {
      g_carstate = enDOWNRIGHT;
    }
    else//停
    {
      g_carstate = enSTOP;
    }

    /*右搖桿*/
    if (X2 < 5 && Y2 > 110 && Y2 < 150) //左
    {
      g_servostate = 1;
    }
    else if (Y2 > 110 && Y2 < 150 && X2 > 230)//右
    {
      g_servostate = 2;
    }
    else//歸位
    {
      g_servostate = 0;
    }


  }
}

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:471632 發表于 2021-6-10 07:25 | 只看該作者
給個圖片
回復

使用道具 舉報

板凳
ID:465009 發表于 2021-6-10 14:16 | 只看該作者
感覺很不錯,可以用用試試
回復

使用道具 舉報

地板
ID:171746 發表于 2021-6-17 18:01 | 只看該作者
用什么硬件?
回復

使用道具 舉報

5#
ID:458472 發表于 2021-6-18 08:11 | 只看該作者
有硬件實物圖么?
回復

使用道具 舉報

6#
ID:946672 發表于 2021-6-29 13:16 | 只看該作者
看著還不錯,感謝樓主分享。
回復

使用道具 舉報

7#
ID:955021 發表于 2021-7-20 16:51 | 只看該作者
想請問一下樓主,有沒有是基于51單片機來實現蹺蹺板上,pid的程序?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 在线不卡| 日韩一区二区三区视频 | 精品久久一区 | 美国十次成人欧美色导视频 | 69电影网| 亚洲精品播放 | 日本一卡精品视频免费 | 日韩电影免费在线观看中文字幕 | 国产精久久久久久久 | 国产精品视频一二三区 | 国产一区二区三区在线观看免费 | 亚洲欧洲精品一区 | 国产午夜精品视频 | 亚洲一区二区视频在线观看 | 在线免费av电影 | 国产日韩欧美一区二区在线播放 | av无遮挡| 亚洲精品一区二区在线观看 | 一级片在线免费播放 | 欧美乱码精品一区二区三区 | 91视频导航 | 人人人人爽 | 国产精品资源在线 | 亚洲乱码一区二区三区在线观看 | 久久不射电影网 | 欧美精品在线观看 | 成人在线免费看 | 理论片午午伦夜理片影院 | 精品久草 | 久久亚洲欧美日韩精品专区 | 欧美一区二区三区的 | 日韩精品在线播放 | 国产99久久精品 | 草草视频在线播放 | 999久久精品 | 国产在线精品一区二区 | 亚洲欧美日韩一区 | 婷婷国产一区 | 欧美视频区 | 91玖玖| 91在线精品视频 |