|
差速控制转向,可以用X/Y参数(这里用PS2手柄的一个摇杆)控制车辆前后、调速,转向;简化了操纵难度。
本人习惯用Promini328p,取其性价比高,体积小巧,功能够用;用74LS595实现SPI扩展并行接口;前四位驱动一个四相五线步进电机(炮塔),后四位通过754410驱动两个有刷电机。开机音乐尚没进步开发应用。
本机增加LCD1602作为人机对话,便于调试阶段检测遥控通讯。 - /**
- Version 2020.3.2
- by SJL
- **/
- #include <PS2X_lib.h> //PS2X
- #include <LiquidCrystal.h> //lcd
- #include "pitches.h" //tone
- //LCD initial
- const int rs = 5, en = 4, d4 = A0, d5 = A1, d6 = A2, d7 = A3;
- //const int rs = A2, en = A1, d4 = A3, d5 = A4, d6 = A5, d7 = 5;数据脚皆可用模拟替代。
- LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
- //74HC595 SPI initial
- #define latchPin 12
- #define clockPin 11
- #define dataPin 10
- //tone
- const int Speaker=3;
- int melody[] = {NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4}; // notes in the melody:
- int noteDurations[] = {4, 8, 8, 4, 4, 4, 4, 4}; // note durations: 4 = quarter note, 8 = eighth note, etc.:
- //PS2 initial
- #define PS2_DAT 8 // 2019.10.20旧版本 dat、cmd 不能用模拟管脚。
- #define PS2_CMD 7
- #define PS2_SEL A5
- #define PS2_CLK A4
- #define motorL_En12 9 //754410 PinEnable,PWMpin
- #define motorR_En34 6
- int motorDr[]={B0101,B1010,B0000}; //(-+ -+,+-+-,----)/gofront,goback,stop motorCode
- //可调节管脚正负配置,{B1010,B0101,B0000}
- int L_EnValue=0, R_EnValue=0;
- PS2X ps2x; // create PS2 Controller Class
- int PS_LX; //PS2手柄左摇杆X轴数据 左摇杆用于行走
- int PS_LY;
- int PS_RX; //PS2手柄右摇杆X轴数据 右摇杆用于炮塔 Turret
- int PS_RY; //暂空
- int error = 0; //ps2连接正确与否的判断标志
- byte type = 0; //ps2x.readType()转换判别标志
- byte vibrate = 0;
- int carCoad=0; //car move mode code
- int F=0; //car move value
- int Turn=0; //car turn value
- int T=0; //Turrent round value
- int Degree=1100; //most value of turrent round
- int StepNumber = 0; //stepmotor wont moveNumber
- int old_Degree = 0;
- int StepData=0; //步进电机的执行编码
- int stepCode[] = {8, 12, 4, 6, 2, 3, 1, 9}; //8步编码
- int stepCodeIndex=0; //步编码-电机当前位于0~7的哪一步
- void setup() {
- lcd.begin(16, 2); // set up the LCD's number of columns and rows:
-
- lcd.print("Lx");
- lcd.setCursor(0,1);
- lcd.print("Rx");
- lcd.setCursor(8,0);
- lcd.write("Ly");
- lcd.setCursor(8,1);
- lcd.write("Ry");
- pinMode(dataPin,OUTPUT); pinMode(clockPin,OUTPUT); pinMode(latchPin,OUTPUT); //74HC595管脚配置
- pinMode(motorL_En12,OUTPUT); pinMode(motorR_En34,OUTPUT); //电机使能管脚配置
- //tone
- for (int thisNote = 0; thisNote < 8; thisNote++) {
- int noteDuration = 1000 / noteDurations[thisNote];
- tone(Speaker, melody[thisNote], noteDuration);
- int pauseBetweenNotes = noteDuration * 1.30; // to distinguish the notes, set a minimum time between them.
- // the note's duration + 30% seems to work well:
- delay(pauseBetweenNotes);
- noTone(3); // stop the tone playing:
- }
- // initialize the serial communications
- Serial.begin(9600);
- delay(50);
- error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT);
- }
- void loop() {
- int number=5 ;
- ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
-
- /*if(ps2x.Button(PSB_START)) //start选中
- Serial.println("Start is being held");
- if(ps2x.Button(PSB_SELECT)) //select选中
- Serial.println("Select is being held");*/
-
- PS_LX=ps2x.Analog(PSS_LX); //把PS2手柄左摇杆X轴数据赋值PS_LX
- PS_RX=ps2x.Analog(PSS_RX); //把PS2手柄右摇杆X轴数据赋值PS_RX
- PS_LY=ps2x.Analog(PSS_LY); //把PS2手柄左摇杆Y轴数据赋值PS_LY
- PS_RY=ps2x.Analog(PSS_RY); //把PS2手柄右摇杆Y轴数据赋值PS_RY
- lcd.setCursor(3,0); //LCD显示手柄参数
- lcd.print(PS_LX);
- lcd.setCursor(11,0);
- lcd.print(PS_LY);
- lcd.setCursor(3,1);
- lcd.print(PS_RX);
- lcd.setCursor(11,1);
- lcd.print(PS_RY);
-
- /******************* 行走控制 ************************/
- if(PS_LY<=125){ //轮使能/电机运转旋向配置
- F = map(PS_LY,125,0,90,255); //电机使能值确定
- carCoad = motorDr[0]; //各电机运行方向确定 goFront
- }
- else if(PS_LY>=130){
- F = map(PS_LY,130,255,90,255);
- carCoad = motorDr[1]; //goBack
- }
- else {F=0; carCoad=motorDr[2];} //Stop
- //转向影响旋转使能的百分比
- if(PS_LX<=125){ //左转
- Turn = map(PS_LX,125,0,90,40);
- L_EnValue = F * Turn/100; //转向侧电机使能值 按照百分比减弱
- if(L_EnValue<30)L_EnValue=0; //若使能值小于某值,直接定义为0;以免烧电机。
- R_EnValue = F;
- }
- else if(PS_LX>=130){ //右转
- Turn = map(PS_LX,130,255,90,40);
- L_EnValue = F;
- R_EnValue = F * Turn/100; //转向侧电机使能值 按照百分比减弱
- if(R_EnValue<30)R_EnValue=0; //若使能值小于某值,直接定义为0;以免烧电机。
- }
- else { //Turn=0;
- L_EnValue = F;
- R_EnValue = F;
- }
-
- carMove(carCoad,L_EnValue,R_EnValue,StepData); //用所得参数 调用行走子程序。
-
- /***************** 炮塔控制 *************************/
- { }
- }
- /********************************************
- 走行子程序(行走模式,en_L, en_R, Turrent_StepData)
- *******************************************/
- void carMove(int carCoad,int L_EnValue,int R_EnValue,int StepData)
- {
- byte DataByte;
- digitalWrite(motorL_En12,LOW); //first turnOff every enPin
- digitalWrite(motorR_En34,LOW);
-
- DataByte = (StepData<< 4) | carCoad; //字节组合
- //Serial.print(" StepData ");Serial.print(StepData);Serial.print(" carCoad ");Serial.println(carCoad);
-
- digitalWrite(latchPin, LOW); //数据串行输出,关断latchPin。
- shiftOut(dataPin, clockPin, MSBFIRST, DataByte); //逐个字节发送
- //delay(5);
- digitalWrite(latchPin, HIGH); //打开latchPin,数据并行输出
-
- analogWrite(motorL_En12, L_EnValue);
- analogWrite(motorR_En34, R_EnValue);
- }
-
复制代码 |
|