论坛» DIY与开源设计» 电子DIY

助工
2015-06-06 21:52 11楼

如何让小车检测到一个坡度?这就要涉及卡尔曼相关算法。

简单来说,卡尔曼滤波器是一个“optimal recursive data processing algorithm(最优化自回归数据处理算法)”。对于解决很大部分的问题,他是最优,效率最高甚至是最有用的。他的广泛应用已经超过30年,包括机器人导航,控制,传感器数据融合甚至在军事方面的雷达系统以及导弹追踪等等。近来更被应用于计算机图像处理,例如头脸识别,图像分割,图像边缘检测等等。 卡尔曼滤波器的介绍 : 为了可以更加容易的理解卡尔曼滤波器,这里会应用形象的描述方法来讲解,而不是像大多数参考书那样罗列一大堆的数学公式和数学符号。但是,他的5条公式是其核心内容。结合现代的计算机,其实卡尔曼的程序相当的简单,只要你理解了他的那5条公式。 在介绍他的5条公式之前,先让我们来根据下面的例子一步一步的探索。 假设我们要研究的对象是一个房间的温度。根据你的经验判断,这个房间的温度是恒定的,也就是下一分钟的温度等于现在这一分钟的温度(假设我们用一分钟来做时间单位)。假设你对你的经验不是100%的相信,可能会有上下偏差几度。我们把这些偏差看成是高斯白噪声(White Gaussian Noise),也就是这些偏差跟前后时间是没有关系的而且符合高斯分布(Gaussian Distribution)。另外,我们在房间里放一个温度计,但是这个温度计也不准确的,测量值会比实际值偏差。我们也把这些偏差看成是高斯白噪声。 好了,现在对于某一分钟我们有两个有关于该房间的温度值:你根据经验的预测值(系统的预测值)和温度计的值(测量值)。下面我们要用这两个值结合他们各自的噪声来估算出房间的实际温度值。 假如我们要估算k时刻的实际温度值。首先你要根据k-1时刻的温度值,来预测k时刻的温度。因为你相信温度是恒定的,所以你会得到k时刻的温度预测值是跟k-1时刻一样的,假设是23度,同时该值的高斯噪声的偏差是5度(5是这样得到的:如果k-1时刻估算出的最优温度值的偏差是3,你对自己预测的不确定度是4度,他们平方相加再开方,就是5)。然后,你从温度计那里得到了k时刻的温度值,假设是25度,同时该值的偏差是4度。 由于我们用于估算k时刻的实际温度有两个温度值,分别是23度和25度。究竟实际温度是多少呢?相信自己还是相信温度计呢?究竟相信谁多一点,我们可以用他们的协方差(covariance)来判断。因为Kg=5^2/(5^2+4^2),所以Kg=0.61,我们可以估算出k时刻的实际温度值是:23+0.61*(25-23)=24.22度。可以看出,因为温度计的协方差(covariance)比较小(比较相信温度计),所以估算出的最优温度值偏向温度计的值。 现在我们已经得到k时刻的最优温度值了,下一步就是要进入k+1时刻,进行新的最优估算。到现在为止,好像还没看到什么自回归的东西出现。对了,在进入k+1时刻之前,我们还要算出k时刻那个最优值(24.22度)的偏差。算法如下:((1-Kg)*5^2)^0.5=3.12。这里的5就是上面的k时刻你预测的那个23度温度值的偏差,得出的3.12就是进入k+1时刻以后k时刻估算出的最优温度值的偏差(对应于上面的3)。 就是这样,卡尔曼滤波器就不断的把(协方差(covariance)递归,从而估算出最优的温度值。他运行的很快,而且它只保留了上一时刻的协方差(covariance)。上面的Kg,就是卡尔曼增益(Kalman Gain)。他可以随不同的时刻而改变他自己的值,是不是很神奇!

助工
2015-06-10 16:33 12楼

最近事情比较多,但是也不能阻挡我发一些自己的学习eepw小车的一个进度:

超声波模块

有4个引脚

1号是VCC,2号是TRIG,3号是ECHO,4号是GND。

这是超声波的一个协议的时序:

超声波模块基本是可以测定3米的距离。

好一些的可以达到5米距离。

接着就是超声波测距的小车的代码了。

助工
2015-06-21 23:19 13楼

这周末楼主有幸去到深圳maker faire活动。楼主有五个非常强烈的感受,最主要的就是共享,1+1+1>3.第二点就是有问题就提出来,创新精神,就来源于不停的提问,然后,就是从立下一个技术可以创造世界的念头,第四点就是maker其实可以是非常热爱生活的人,技术不一定宅,最后一个就是在这个时代创新创业真的非常方便,在这个时代,就许多硬件都开源了,再加上3D打印机,产品设计建模什么的都不用太担心,软件也有一大堆可以供你使用,所以制作新的产品真的像是搭建乐高积木一般的\(^o^)/~。我只说前3点LA:maker就是有一种共享精神在里面。无论是maker的基本利器arduino,还是3D打印机,共享,开源几乎是maker的支柱,以前很NB的技术,何止是软件,就连算法都有着很多大牛做出类似的开源版本。好比谷歌的mapreduce算法,就有ApacheHadoop作为开源的版本。而在硬件领域,也有好比我们的EEPW举行的各种DIY活动。硬件DIY本身就是共享的maker精神的代表。还有我们的passoni同学的优秀的源代码可供参考和jackwang和活动主办方的组织,都是这次智能平衡车DIY活动办的好的保障,而在这次的深圳的活动之中,遇到了许多抱着技术改变世界的技术达人,无论是从飞行四轴多轴飞行器还是航空火箭,或者是图像识别的打飞行器机器人,再或者是Arm的mbed工作坊。节目呢真的是非常的好。这次,一个香港的参会的人和我聊到了这个趋势,他提到了怎么就可以说这不会变成一次高潮,完了几年之后,就又消失无见。我也考虑很久,其实,技术这东西,不就是一代替换一代吗?现在stm32好用,但是几年之后呢,几十年之后呢?现在是使用KEIL,IAR完成代码编写的,以后会不会变为labview+图形化拖拽完成功能,还有就是遇到问题该肿么办?寻找开源的东西使用吗?开源的就是好用,但是符合你的要求吗?就像jackwang说的,要把遇到的问题提出来,有我们的passoni同学为代表的一群同学帮你解答,不要因为不好意思,或者怕别人嘲笑自己没有视频就把问题匿了,这是最最糟糕的一种做法╮(╯_╰)╭


助工
2015-06-22 21:10 14楼

超声波模块的使用及程序

主要是要看懂上面的一个时序图

主要的代码如下



GPIO_SetBits(GPIOA,GPIO_Pin_2); delay_us(20);//拉高超过10us,发射超声波 GPIO_ResetBits(GPIOA,GPIO_Pin_2); TIM2->CNT=0;//计数器清0 while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)==0);//等待ECHO脚高电平 TIM_Cmd(TIM2, ENABLE);// TIM2 enable counter [允许tim2计数] while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)==1)&&(TIM2->CNTARR-10)); TIM_Cmd(TIM2, DISABLE); count=TIM2->CNT;//ECHO脚低电平后读取计数器的值,从而算出往返时间 length=count/58.0; printf("测试距离=%fcm\r\n",length);

加一个循环就可以了

程序每一次上传显示上传成功我插入却没有反应,正在申请百度云,准备完了放到云网盘上面。


助工
2015-06-24 00:44 15楼
蓝牙模块,使用的是SPP-CA模块,淘宝上面可以搜索到的,非常nice的一个无线通信设备。
相对于WiFi,ZigBee,2.4g等通信方式,蓝牙有其独特的应用之处,有其最近一段时间,蓝牙由于其安全通信的特点被应用于一些密匙上面。RSSI的特点可以使用来室内定位,所以其应用领域还是非常广泛的。
接下来就说怎么样写程序做一个简单蓝牙对话吧!
首先是看原理图,顺便看了原版程序关于蓝牙的程序,感觉有些乱,所以楼主自己又从头写了一个驱动。
既然要自己写,那么就要考虑首先是使用寄存器还是库函数,库函数是使用cmsis还是hal,最后还是选择先把大多数人使用的cmsis写了。
由于一直无法以附件形式上传,所以只能通过每一个模块函数,具体的实现来说明
main函数关于蓝牙的归结为非常简单的四个函数

RCC_Configuration(); //系统时钟初始化
GPIO_Configuration();//端口初始化
USART_Configuration();//串口初始化 NVIC_Configuration();
然后就是串口初始化具体实现:
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate=9600;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;

USART_Init(USART3,&USART_InitStructure);
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
USART_Cmd(USART3,ENABLE);

USART_ClearFlag(USART3,USART_FLAG_TC);
}

接下来就是端口的实现


void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//TX
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;//RX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}


接着是时钟的部分



与蓝牙有关的也是简单的 四个函数



SystemInit();//72m
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);





最后是嵌套中断的部分


NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);



然后就是处理蓝牙通信事务的部分:


void USART3_IRQHandler(void)
{
u8 temp=0;
if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)
{
temp=USART_ReceiveData(USART3);

USART_SendData(USART3,temp+4);
while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);
}
}
/*
powered by zhongkeyuan
*/




具体到学习蓝牙通信的协议,以及其他一些SPP-CA附件,可以到http://pan.baidu.com/s/1c0D3bdm来下载






助工
2015-10-21 23:23 16楼

PID的基本概念:

1、被调量

被调量就是反映被调对象的实际波动的量值。被调量是经常变化的。
2、设定值
PID调节器设定值就是人们期待被调量需要达到的值。设定值可以是固定的,也可以是变化的。
3、控制输出
控制输出指PID调节器根据被调量的变化情况运算之后发出的让外部执行结构按照它的要求动作的指令。在PID调节器和执行机构之间还会有其他环节,比如限幅、伺服放大器等。限幅功能通常在PID调节器内完成;如果如果将PID、限幅和伺服放大器功能做在一台仪表内就构成阀位控制PID调节器;将伺服放大器和限幅做在执行机构里就构成智能执行机构。
4、输入偏差
输入偏差是被调量和设定值之间的差值
5、P(比例)
P就是比例作用,简单说就是输入偏差乘以一个系数。
6、I(积分)
I就是积分,简单说就是将输入偏差进行积分运算。
7、D(积分)
D就是微分,简单说就是将输入偏差进行微分运算
8、PID基本公式
PID调节器参数整定过程通俗讲就是先把系统调为纯比例作用,逐步增强比例作用让系统振荡,记录下比例作用和振荡周期,然后这个比例作用乘以0.6,积分作用适当延长 KP=0.6 Km
KD= KP×π/4ω
KI= KP×ω/π
公式中KP为比例控制参数;KD为积分控制参数;KI为微分控制参数;Km为系统开始振荡是的比例值;ω为极坐标下振荡时的频率

PID调试的基本方法:

直立控制:PD 控制,这是最核心的控制,其他的控制相对直立控制而言都是干扰。

速度控制:PI 控制对编码器信息进行低通滤波可以削弱电机控制的比重, 提高系统稳定性。

转向控制:PD 控制结合了Z 轴陀螺仪PD控制。

在一个系统中可以只用到PPIPD,或者PID其中的一种,并不是完全的要用上的。

很显然,在这段直立环控制函数中:

int balance(float Angle,float Gyro) { float Bias,kp=50,kd=0.13; int balance; Bias=Angle-4; balance=kp*Bias+Gyro*kd; return balance; }

Bias=Angle-4;这行代码中,Bias我们可以理解为“相对重心角”,也就是我们所说的当前角度相对重心所在角度的差值,即小车的输入偏差,而我们的重心角度即设定值;




助工
2015-10-23 22:53 17楼

虽然在调试的过程中遇到了各种各样的困难和各种各样的繁杂事情,但是我一直觉得这个小车带给我无比的快乐,就像是认识身边的一个美女,从觉得人长得非常的漂亮,后来慢慢了解到她的世界丰富多彩,了解到她的过去到现在,知道她为什么是这样的性格,还是要不可不说stm32的强大,以前只知道单片机怎么去制作一个小的控制设备,所以对一个喜欢折腾的人来说,真的是非常的难受在这么晚的时候才接触到这样的系统工程,这里还要重新写一下电机编码器的数据获取
电机的编码器其实就是一种传感器,可以把旋转位移转换成一串数字脉冲信号,MCU可以读取这段脉冲信号通过计数来获取电机的转速。



可以看出小车的原理图中显示编码器的接口分别为PA0和PA1,PB6和PB7:

PA0和PA1对应着TIM2,PB6和PB7对应着TIM4.所以系统应该采用定时器2和4分别对编码器结果进行计数。参考数据手册中定时器用作编码器接口模式的内容:选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011。 通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以对输入滤波器编程。 两个输入TI1和TI2被用来作为增量编码器的接口。参看表77,假定计数器已经启动(TIMx_CR1寄存器中的CEN=’1’),计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。TI1FP1和TI2FP2是TI1和TI2在通过输入滤波器和极性控制后的信号;如果没有滤波和变相,则TI1FP1=TI1,TI2FP2=TI2。根据两个输入信号的跳变顺序,产生了计数脉冲和方向信号。依据两个输入信号的跳变顺序,计数器向上或向下计数,同时硬件对TIMx_CR1寄存器的DIR位进行相应的设置。不管计数器是依靠TI1计数、依靠TI2计数或者同时依靠TI1和TI2计数。在任一输入端(TI1或者TI2)的跳变都会重新计算DIR位。 编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在0到TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0到ARR计数,或是ARR到0计数)。所以在开始计数之前必须配置TIMx_ARR;同样,捕获器、比较器、预分频器、触发输出特性等仍工作如常。

void Encoder_Init_TIM2(void) { RCC->APB1ENR|=1<<0; RCC->APB2ENR|=1<<2; GPIOA->CRL&=0XFFFFFF00;//PA0 PA1 GPIOA->CRL|=0X00000044; TIM2->PSC = 0x0; TIM2->ARR = ENCODER_TIM_PERIOD-1; TIM2->CCMR1 |= 1<<0; TIM2->CCMR1 |= 1<<8; TIM2->CCER |= 0<<1; TIM2->CCER |= 0<<5; TIM2->SMCR |= 3<<0; //SMS='011' TIM2->CR1 |= 0x01; } int Read_Encoder(u8 TIMX) { int Encoder_TIM; switch(TIMX) { case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 ->CNT=0;break; case 3: Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;break; case 4: Encoder_TIM= (short)TIM4 -> CNT; TIM4 -> CNT=0;break; default: Encoder_TIM=0; } return Encoder_TIM; }



助工
2015-10-23 23:09 18楼

由于之前写的那篇直立车调试写的不是很直观,所以看了论坛里5,6篇有关于直立车调试的帖子,被吸引了好久,其中夏季在下季同学的文章非常不错,所以我复制了过来,以后可以多看看。

实验目的:按键修改PID各个参数值,通过Nrf24l01无线通讯把修改的数据传递给小车,进行调试,参数内容实时显示在OLED屏上。

PID这个东西还是比较难的。不仅需要理论基础,还需要多年的调试经验,掌握起来比较困难。和我一样的初学者可以看看这个PID通俗易懂.pdf

源程序中涉及到的PID控制主要有直立PD控制、速度PI控制、转向PD控制。

(1)直立PD控制






最上面红圈数值为平衡的角度中值,也就是小车重心,注释已经很清楚了。这一数值要先调好,否则会影响后面参数的调试。我的方法是,看小车平衡时OLED屏上的

angle角度值,会在一个范围变化,取最大值与最小值的中间值。例如:我的小车在359度与2度之间徘徊,所以我取0.5。

下面两个参数分别为直立时P参数和D参数,需要后面调的。我用变量BP和BD代替。

(2)速度PI控制










如果没有速度PI控制,小车会往重心方向加速运行,并倒下。

红圈两个参数分别为速度P参数和I参数,我用变量VP和VI代替。

(3)转向PD控制








如果没有转向PD控制,小车会在原地慢慢的打转。

红圈两个参数分别为转向P参数和D参数,我用变量TP和TD代替。



来看看另一块板子上的按键排布如下













只用到前4个按键:


S1用于BP,BD,VP,VI,TB,TD六个参数的选择键;

S2用于BP,BD,VP,VI,TB,TD六个参数的选择键(相反方向);

S3用于BP,BD,VP,VI,TB,TD六个参数数值增加键;

S4用于BP,BD,VP,VI,TB,TD六个参数数值减少键;


软件修改

(1)修改按键程序key.c和key.h

void KEY_Init(void) { RCC->APB2ENR|=1<<3; //使能PORTB时钟 GPIOB->CRH&=0X0000FFFF; GPIOB->CRH|=0X88880000;//PB12 PB13 PB15 PB15 上拉输入 GPIOB->ODR|=0X0000F000; //PB12 PB13 PB15 PB15 上拉 } void KEY_Scan (void) { if(s1==0) { delay_ms(10); if(s1==0) { s1num++; while(!s1); if(s1num==7) s1num=0; } } if(s2==0) { delay_ms(10); if(s2==0) { s1num--; while(!s2); } } if(s1num!=0) { if(s3==0) { delay_ms(10); if(s3==0) { while(!s3); if(s1num==1) BP+=1; if(s1num==2) BD+=0.005; if(s1num==3) VP+=0.5; if(s1num==4) VI+=0.001; if(s1num==5) TP+=0.5; if(s1num==6) TD+=0.002; } } if(s4==0) { delay_ms(10); if(s4==0) { while(!s4); if(s1num==1) BP-=1; if(s1num==2) BD-=0.005; if(s1num==3) VP-=0.5; if(s1num==4) VI-=0.001; if(s1num==5) TP-=0.5; if(s1num==6) TD-=0.002; } } }


(2)修改无线通讯程序24l01.c中的void NRF24L01()函数

void NRF24L01(void) { u8 mode=1,count; u8 tmp_buf[33]; if(mode==0)//RX模式 { RX_Mode(); while(1) { if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到信息,则显示出来. { key_flag=1; BP=(tmp_buf[1]*256+tmp_buf[2])/10.0; BD=(tmp_buf[3]*256+tmp_buf[4])/1000.000; VP=(tmp_buf[5]*256+tmp_buf[6])/10.0; VI=(tmp_buf[7]*256+tmp_buf[8])/1000.000; TP=(tmp_buf[9]*256+tmp_buf[10])/10.0; TD=(tmp_buf[11]*256+tmp_buf[12])/1000.000; s1num=tmp_buf[13]; oled_show(); }else break; }; }else//TX模式 { TX_Mode(); while(1) { if(++count>100)count=0; tmp_buf[1]=BP*10/256; tmp_buf[2]=(u16)(BP*10)%256; tmp_buf[3]=BD*1000/256; tmp_buf[4]=(u16)(BD*1000)%256; tmp_buf[5]=VP*10/256; tmp_buf[6]=(u16)(VP*10)%256; tmp_buf[7]=VI*1000/256; tmp_buf[8]=(u16)(VI*1000)%256; tmp_buf[9]=TP*10/256; tmp_buf[10]=(u16)(TP*10)%256; tmp_buf[11]=TD*1000/236; tmp_buf[12]=(u16)(TD*1000)%256; tmp_buf[13]=s1num; if(NRF24L01_TxPacket(tmp_buf)==TX_OK) { key_flag=1; }else break; } } }

(3)修改显示程序show.c中oled_show()程序

void oled_show(void) { OLED_Display_On(); //显示屏打开 //=============显示BP=======================// OLED_ShowString(00,0,"BP"); OLED_ShowNumber(30,0, BP,3,12); OLED_ShowString(48,0,"."); OLED_ShowNumber(54,0, (u16)(BP*10)%10,1,12); if(s1num==0) OLED_ShowString(100,0," "); if(s1num==1) OLED_ShowString(100,0,"BP"); //=============显示BD=======================// OLED_ShowString(00,10,"BD"); OLED_ShowNumber(30,10, BD,3,12); OLED_ShowString(48,10,"."); OLED_ShowNumber(54,10, (u16)(BD*1000)%1000,3,12); if(s1num==2) OLED_ShowString(100,0,"BD"); //=============显示VP=======================// OLED_ShowString(00,20,"VP"); OLED_ShowNumber(30,20, VP,3,12); OLED_ShowString(48,20,"."); OLED_ShowNumber(54,20, (u16)(VP*10)%10,1,12); if(s1num==3) OLED_ShowString(100,0,"VP"); //=============显示VI=======================// OLED_ShowString(00,30,"VI"); OLED_ShowNumber(30,30, VI,3,12); OLED_ShowString(48,30,"."); OLED_ShowNumber(54,30, (u16)(VI*1000)%1000,3,12); if(s1num==4) OLED_ShowString(100,0,"VI"); //=============显示TP=======================// OLED_ShowString(00,40,"TP"); OLED_ShowNumber(30,40, TP,3,12); OLED_ShowString(48,40,"."); OLED_ShowNumber(54,40, (u16)(TP*10)%10,1,12); if(s1num==5) OLED_ShowString(100,0,"TP"); //=============显示TD=======================// OLED_ShowString(00,50,"TD"); OLED_ShowNumber(30,50, TD,3,12); OLED_ShowString(48,50,"."); OLED_ShowNumber(54,50, (u16)(TD*1000)%1000,3,12); if(s1num==6) OLED_ShowString(100,0,"TD"); if(key_flag==1) OLED_ShowString(100,50,"OK"); //=============刷新=======================// OLED_Refresh_Gram(); }

观察现象

先看看OLED屏的显示状态












一手要按键,另一只手要拍摄,没有多余的手去扶小车,所以上电直接给源程序中的PID初值。

小车装上测距模块和无线模块,拆下OLED屏(因为只有一个,不够使),装在另一块板子上。

视频不知道怎么了,在自己电脑上播放器播放正常,传到优酷就倒过来了,不太影响效果,就不更改了。

一开始上电,传给小车的是源程序的PID参数值,小车左右摆动大约7cm。按键增加BP值,增加到BP=70,小车左右摆动大约4cm。重启板子,小车PID值恢复到初始状态,小车左右摆动恢复到大约7cm。哈哈,接下来可以尽情的调试PID了。

助工
2015-10-26 20:01 19楼

一直琢磨,怎么样可以写的更好一些,稍微和大家已经发的帖子内容不一样,给大家新鲜的鸡汤的感觉,但是说到这里就不得不说一下自己的惰性了,这里的惰性就是思维上面只是需要得到更多的知识,却不喜欢去思考为什么,从小学一直到中学,大学里面就是感觉大家许多知识的欠缺。

平时别人问什么,我都可以说一个大概。有人说,这没有什么不好啊,你显得比较博学,有学问家的潜质,但我觉得这就是最可怕的事情,我做过飞行器,做过四轴,做过扑翼飞机,会写控制代码,却对为什么不是很了解,像这次的小车我也是看的懂代码,会写一部分代码,去讲原理,也说的上一个大概。

如果要深入问我一部分问题,我十有八九是回答不上。

其中许多的联系点,我多一笔带过,这就是为什么我学东西,做事情很快,比别人要高效多,但是过了之后却没有什么圆通之处,就像我理解stm32的定时器的用法,却不可以了解为什么是这样的,已经整体上是什么情况。

这些都是不喜欢思考,只喜欢死记硬背的最可怕的结果。就是你只能停留在一个层次上面,你不可能去从多个角度和多个层次去融会贯通,所以,我接下来写的一些学习报告就努力多向多层次靠拢。

助工
2015-10-27 23:20 20楼
由于我的不当操作,导致电机被损毁,真的非常的郁闷,不过最近和学校的一些老师联系得知最近许多公司要赞助我们,其中有一个比较好的公司提供了许多型号的电机,我就可以借一个用,最近同时在玩stm32F7的板子,真的感觉到微电子技术的快速发展,昨天看的一本采访集里面才采访到了一些对电脑发展牵了很大头的人物,其中有比尔盖茨,他说当时他在写BASIC语言解释器的时候,对软件硬件都要有非常非常深的理解,他说忙几个月就为可以把程序控制在4k内,想想现在的比较差的微处理器也可以运行比较大的程序了,而这些只是在30年前,30年之后,也就是2045年,Arm M7也许就是今天的51单片机,而且看了一个同学的分享,正在学习使用matlab的硬件控制部分,一直在使用keil,对其他的软件也没有太多的了解。大概1个月前有个大牛告诉我说clion会变成未来的硬件开发的利器,我就去下了一个试了一下,对于这个平台怎么样开发硬件程序不是非常的熟悉,网络上面也没有什么教程,不过它的许多的特性真的是非常的先进,值得大家好好研究一番,而且那个大神说他早就不思用keil这个软件了,他说可以geek eclipse,选择好的研发平台真的是非常的重要,最近获得一个英特尔的内部的硬件开发工具平台,感觉真的是高大上,之前觉得要很麻烦的设置时钟,配置引脚。配置I2C,SPI全部变成了可视化配置,这样如果是小孩的话那么他的学习成本就非常的低了,没错,intel这个工具居然是以教育和快速开发有关的,想到在不远未来的一天有人可以直接通过软件来写控制小车,操作小车的场景,真的是非常期待。
共23条 2/3 1 2 3 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]