用4个电磁铁,一个永久磁铁圈,一个arduino uno单片机,一个tb6612,线性霍尔ah3503
使用的东西不要那么死板
1、线性霍尔元件两个,必须成垂直交叉,但是在实际做的过程中,完全垂直交叉可能性不大,就需要手动调整
这是非常重要的,而且会影响后面的调试,特别是初期,你根本感觉不到问题,什么是正确的,什么是错误的
只能凭借经验.
到最后,实际上当你感受到力,使得浮子被夹在中间,但是位置不正确,就可以手动去调整霍尔元件。
如果是加5v电,就没必要加放大器,直接接到主板里就好。
获取霍尔数据最好用中断的方式,这样速度快。
2、当你上电后,如果能感觉浮子在x轴、y轴都有力量控制在中间,那么距离成功就不远了。如果没感觉到这个力
多半是线路颠倒。
3、在上电施加的力,必须反应足够快,如果你听到有很大的电流声,就要提高频率,直到听不到电流声音。
发现抖动太大,可以减小力量
4、pid算法很简单,不需要太复杂,但调试参数就有点花费时间,
但我们通常把注意力集中在具体代码上,这是错误的方向
kp是主要的力参数,这个只要你感受到能承受浮子被夹在中间,并且软绵绵的就可以了
ki似乎没太大作用,设置大了,浮子摆动太大。
kd控制浮子摆动,调合适为止
pid->Kp=0.8500; //K比例
pid->Ki=0.01; //K积分,注意,和上几次相比,这里加大了积分环节的值
pid->Kd=1.6000; //K微分
5、对于pwm的设置,实际上没有特别的,根据芯片的说明书来做就好,还可以问一问GPT大仙。
6、整体的反应用时钟中断来做,这样速度才能跟上。
这是获得的数据,大家可以分析
x0 | y0 | pidx | pidy |
21.1 | -45.8 | 19.3 | -39.56 |
31.1 | -45.8 | 32.23 | 48.89 |
31.1 | -45.8 | -1.45 | -9.86 |
51.1 | -45.8 | -54.12 | -36.4 |
91.1 | -45.8 | -57.7 | -85.57 |
-58.9 | -35.8 | -65.46 | 147.87 |
-38.9 | -35.8 | 57.12 | 83.73 |
-38.9 | -35.8 | 27.01 | 63.51 |
-28.9 | -35.8 | -22.42 | 32.96 |
-18.9 | -35.8 | 21.54 | 43.87 |
-8.9 | -35.8 | 39.08 | -38.11 |
-8.9 | -35.8 | 36.05 | 72.83 |
1.1 | -35.8 | 76.28 | -1.43 |
1.1 | -35.8 | -12.02 | -14.98 |
1.1 | -35.8 | -10.37 | 16.5 |
1.1 | -35.8 | -11.71 | 57.34 |
11.1 | -35.8 | -42.37 | 40.45 |
11.1 | -35.8 | 9.08 | -64.33 |
11.1 | -35.8 | 6.93 | 18.81 |
11.1 | -35.8 | -13.6 | -7.18 |
11.1 | -35.8 | -7.26 | 34.57 |
11.1 | -35.8 | -14.27 | 44.8 |
21.1 | -35.8 | -14.75 | 35.43 |
21.1 | -35.8 | -33.01 | -24.24 |
31.1 | -35.8 | 18.18 | -8.75 |
51.1 | -35.8 | 42.85 | 91.34 |
51.1 | -35.8 | -8.43 | 12.73 |
-38.9 | -25.8 | -57.49 | 41.12 |
-18.9 | -25.8 | -1.04 | 23.13 |
-8.9 | -25.8 | 44.41 | 57.94 |
-8.9 | -25.8 | 43.26 | 105.96 |
-8.9 | -25.8 | -33.78 | 34.68 |
-8.9 | -25.8 | -6.25 | 73.72 |
-8.9 | -25.8 | 13.28 | 50.95 |
-8.9 | -25.8 | 31.58 | 26.07 |
-8.9 | -25.8 | 0.01 | 86.18 |
-8.9 | -25.8 | -0.76 | 43.64 |
-8.9 | -25.8 | 13.1 | 27.06 |
1.1 | -25.8 | 103.7 | 70.14 |
1.1 | -25.8 | 29.29 | 41.91 |
1.1 | -25.8 | 8.52 | 12.27 |
下面是代码,包含了注释和制作过程,所以非常值
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_VL53L0X.h>
float geta00,geta01; //原点
float geta0,geta1,geta2; //获取的数据
float getas0,getas1; //getas0=geta0-geta00;
float geta10s0,geta10s1; //geta00=(float)geta10s0/(float)read10;
int geta10i=0; //读书数据次数
float getapid0,getapid1; //获取pid值
int geti=0;
int chei,ultrasonic_x_i;
float ultrasonic_x_old;
int pinultrasonic=12;
uint16_t Infrared_ranging=0;
int Infraredranging_ultrasonic=0;
int timer2_maglev_i=0;
// 定义霍尔传感器输入引脚
int Pina0 = A1;
int Pina1 = A2;
int Pina2 = A4;
int Pina2i = 0;
int encoderPin1A = 2;
int encoderPin1B = 8;
int encoderPin2A = 3;
int encoderPin2B = 11;
long encoderCount1 = 0;
long encoderCount2 = 0;
float encoderspeed1 = 0;
float encoderspeed2 = 0;
float millisold=0;
// 定义pwm电磁铁输出引脚
int pwm0 = 9;
int pwm1 = 10;
volatile uint16_t adcValue0; // 定义一个全局变量来存储ADC通道0的读数
volatile uint16_t adcValue1; // 定义一个全局变量来存储ADC通道1的读数
volatile uint16_t adcValue2; // 定义一个全局变量来存储ADC通道2的读数
bool getadbValues100=false;//是否读最初值,开始算pid
bool geta2Values=false;//是否有磁铁来
struct _pid{
float SetSpeed; //定义设定期望值,目标值
float ActualSpeed; //定义实际值
float Proportion_err; //定义比例误差
float err; //定义偏差值
float err_last; //定义上一个偏差值
float err_lastlast; //定义上上一个偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
float voltage; //定义电压值(控制执行器的变量)
float integral; //定义积分值
float isintegral; //是否积分
float derivative; //计算微分项
float u; //本次输出
float umax;
float umin;
float elapsedTime;