|
本帖最后由 donglaile 于 2017-8-2 10:40 编辑
现在x宝上电子模块真心便宜,前段时间心血来潮,买模块拼了个循迹小车玩玩,50块左右就搞定了。
原理图大概这样,没找到L9110s,用L298画了,理解意思就行:
电池使用两节锂电池串联,用了个5A的可调降压模块给电机模块供电。这里主控另外供电,用以前剩下的带移动电源功能项目板子5V升压的。
特别注意一点光电对管的安装间隔最好是黑胶带的宽度,竖着安装(就是模块PCB与小车前进方向平行),用万能的热熔胶粘在废弃的芯片壳上再粘贴到小车前面的。
来张错误安装光电对管的图:
之前这样安装一直没搞好。
控制代码: - //电机电压:6.1V左右的参数,如果不加积分项,可以循线跑,但是无法回到中间传感器位置。
- float Kp = 10, Ki = 0.02, Kd = 20;
- float error = 0, P = 0, I = 0, D = 0, PID_value = 0;
- float previous_error = 0, previous_I = 0;
- static int initial_motor_speed = 100; //期望速度
- int left_motor_speed = 0;
- int right_motor_speed = 0;
- uint8_t irs = 0;
- //引脚定义
- const int IR_PIN[] = {A0, A1, A2, A3, A4}; //红外对管引脚定义
- const int IN_A1 = 3; // 电机A1
- const int IN_A2 = 9; // 电机A2
- const int IN_B1 = 10; // 电机B1
- const int IN_B2 = 11; // 电机B2
- void read_ir_values(void);
- void calculate_pid(void);
- void motor_control(void);
- void setup()
- {
- // 初始化
- pinMode(IN_A1, OUTPUT);
- pinMode(IN_A2, OUTPUT);
- pinMode(IN_B1, OUTPUT);
- pinMode(IN_B2, OUTPUT);
- for (int i = 0; i < 5; i++) {
- pinMode(IR_PIN[i], INPUT);
- }
- Serial.begin(9600); //调试用
- }
- void loop()
- {
- read_ir_values();
- calculate_pid();
- motor_control();
- print_debug();
- // motorsWrite(255,255); // 调试电机
- // delay(3000);
- // motorsWrite(-255,-255);
- // delay(3000);
- }
- void read_ir_values()
- {
- for (int i = 4; i < 9; i++) {
- if (digitalRead(IR_PIN[i])) {
- bitSet(irs, (i - 4));
- } else {
- bitClear(irs, (i - 4));
- }
- }
- switch (irs) {
- case B00000:
- if (error < 0) {
- error = -9;
- } else {
- error = 9;
- }
- break;
- case B00001: error = -7; break;
- case B00011: error = -5; break;
- case B00010: error = -3; break;
- case B00110: error = -1; break;
- case B00100: error = 0; break;
- case B01100: error = 1; break;
- case B01000: error = 3; break;
- case B11000: error = 5; break;
- case B10000: error = 7; break;
- //对以上值进行处理,其他的就自由发挥
- }
- }
- void calculate_pid()
- {
- P = error;
- I = I + error;
- D = error - previous_error;
- PID_value = (Kp * P) + (Ki * I) + (Kd * D);
- PID_value = constrain(PID_value, -100, 100);
- previous_error = error;
- }
- void motor_control()
- {
- //计算每个电机的速度
- left_motor_speed = initial_motor_speed - PID_value;
- right_motor_speed = initial_motor_speed + PID_value;
- constrain(left_motor_speed, -255, 255); //速度限定在(-255,255)
- constrain(right_motor_speed, -255, 255);
- motorsWrite(left_motor_speed, right_motor_speed);
- }
- //速度设定范围(-255,255)
- void motorsWrite(int speedL, int speedR)
- {
- if (speedR > 0) {
- analogWrite(IN_A1, speedR);
- analogWrite(IN_A2, 0);
- } else {
- analogWrite(IN_A1, 0);
- analogWrite(IN_A2, -speedR);
- }
- if (speedL > 0) {
- analogWrite(IN_B1, speedL);
- analogWrite(IN_B2, 0);
- } else {
- analogWrite(IN_B1, 0);
- analogWrite(IN_B2, -speedL);
- }
- }
- void print_debug()
- {
- // 打印串口调试信息
- Serial.print("IRS:");
- String irs2bin = String(irs, 2);
- int len = irs2bin.length();
- if(len < 5){
- for(int i=0;i<5-len;i++){
- irs2bin += "0" + irs2bin;
- }
- }
- Serial.print(irs2bin);
- Serial.print(" ML:");
- Serial.print(left_motor_speed, OCT);
- Serial.print(" MR:");
- Serial.print(right_motor_speed, OCT);
- Serial.print(" er:");
- Serial.print(error, OCT);
- // Serial.print(" P:");
- // Serial.print(Kp, OCT);
- Serial.print(" PID:");
- Serial.print(PID_value, OCT);
- Serial.println();
- }
复制代码
运行视频:
1.速度较慢的,忘记初速度设的多少了
http://v.youku.com/v_show/id_XMjg5MjE5MTc3Mg==.html?spm=a2h3j.8428770.3416059.1
2.这个是设置140初速度的,比较前面的快点
http://v.youku.com/v_show/id_XMjg5MjE5Mzk2MA==.html?spm=a2h3j.8428770.3416059.1
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|