本帖最后由 1五湖四海1 于 2015-4-18 10:49 編輯
% D) u3 J! q% Z. G% p/ Y
! Y+ J0 ? `! o4 I; V$ |6 G, o 我這小項(xiàng)目是為了解決運(yùn)動(dòng)的活塞是否被卡住而設(shè)計(jì)的,。在實(shí)際中汽車剎車系統(tǒng)出現(xiàn)故障容易造成重大事故發(fā)生,。我們的礦車有兩個(gè)加力器,如果一個(gè)加力器出現(xiàn)問題能及時(shí)發(fā)現(xiàn)是可以避免事故的發(fā)生,。所以制作這個(gè)運(yùn)動(dòng)部件卡住報(bào)警器對(duì)安全是很有必要的,。 實(shí)現(xiàn)原理上用一個(gè)能夠檢測距離的模擬量傳感器�,?刂破飨扰袛噙\(yùn)動(dòng)部件是否受人為控制開始運(yùn)動(dòng),,如果部件開始運(yùn)動(dòng),控制器的模數(shù)轉(zhuǎn)換器每隔一段時(shí)間采集一次距離,,控制器計(jì)算前后兩次采集距離值是否一樣,,就可以判斷運(yùn)動(dòng)部件是否被卡住不動(dòng)了。下面介紹下用到的器件和具體設(shè)計(jì)細(xì)節(jié),。 距離傳感器用的是光電模擬量輸出傳感器,,檢測范圍在10mm——100mm。如下圖中兩個(gè)圓柱形的便是距離傳感器,。 控制器用的是ARM cortek M3 STM32f103,,有人會(huì)問為什么要用這個(gè)高性能的處理器呢?我認(rèn)為現(xiàn)在已經(jīng)不是51單片機(jī)是世界了,,51單片機(jī)沒有AD轉(zhuǎn)換器,,需要外接AD轉(zhuǎn)換器,代碼需要從零開始寫,。而ARM cortek M3 里面有10bit AD轉(zhuǎn)換器,,有大量的寫好的庫函數(shù)可以調(diào)用,可以縮短開發(fā)時(shí)間,。他們的價(jià)格差不多為什么不選STM32f10,。這次用的是現(xiàn)成的STM32f103最小系統(tǒng)板。如上圖 代碼設(shè)計(jì)上用到了兩個(gè)定時(shí)器中斷,,一個(gè)定時(shí)器每隔200ms采集一次距離值,,另一個(gè)發(fā)生故障時(shí)每隔500ms報(bào)警一次,用到的算法有AD軟件濾波,,采集500次距離值后,,用冒泡排序法去掉最大值和最小值后,再求平均數(shù)算出距離值,,這時(shí)采集的距離值很準(zhǔn),。剩下的就是用if else編寫的邏輯判斷了。調(diào)試時(shí)用到了printf()庫函數(shù),,結(jié)合電腦串口調(diào)試助手調(diào)試代碼,。調(diào)試代碼如下圖,部分程序代碼在最下面 完成的控制器如上圖,正常工作時(shí)指示燈和蜂鳴器不亮也不響,,如果活塞被卡住時(shí)聲光報(bào)警,。 上圖是加力器,它是用氣頂動(dòng)油完成輸出二倍力的器件,。如果活塞卡死這個(gè)報(bào)警就會(huì)報(bào)警提示故障,。 下面是代碼是主函數(shù)代碼 最下面有全部代碼如果有問題可以和我交流,QQ:835358518 微信:hm15041303104 1 a' m& a, s. A! J& N4 d
#include <stm32f10x_lib.h> #include "sys.h" #include "usart.h" #include "delay.h" #include "led.h" #include "key.h" #include "exti.h" #include "wdg.h" #include "timer.h" #include "adc.h" #include "alarm.h" # t* Q! _1 ?# S& {2 V4 j
#define LIM 5 //卡住判斷參數(shù) #define TREAD 2 //踩剎車 #define LOOSEN 1 //松剎車 #define CLEAR 3 //清除 #define DIFFERENCE 50 //回差
5 _3 t6 \5 G% j: P0 \5 p- U- I- `3 j7 f; c& x+ ~. s* N
u16 lim_value = 1800; //極限報(bào)警值 u16 max_value_l = 1000, max_value_r = 1000; //踩剎車標(biāo)志值 u16 min_value_l = 3000, min_value_r = 3000; //松剎車標(biāo)志值
) O, t9 w7 T L" L F+ {u8 count = 0; //設(shè)置剎車標(biāo)志防干擾計(jì)數(shù) u8 lock_count; //卡住時(shí)計(jì)數(shù)防干擾處理 2 B' C. @+ s( i( D! [
u16 distance_l[2] = {0,0}; //卡住比較數(shù)組 u16 distance_r[2] = {0,0}; u8 i = 0; //采集數(shù)據(jù)計(jì)數(shù)變量 ' S/ e( a& B( J# a" Z
bool brake_state_l, brake_state_r; //剎車狀態(tài)標(biāo)志位 bool lock_alarm_l, lock_alarm_r, lock_alarm; //卡住報(bào)警標(biāo)志位 ! {: x* l B& o6 r' L
u16 value_buf[N]; //濾波求平均緩存 u32 sum; //濾波求平均總和緩存 u16 temp; //濾波求排序緩存
2 R6 [2 V! w7 L. ] //判斷是否活塞卡住 bool is_stuck(u16 distance_zero, u16 distance_one, bool brake_state, u16 *max_value, u16 *min_value); void data_collection(void); //數(shù)據(jù)采集 /** 主函數(shù) */ int main(void) { bool lim_alarm_l, lim_alarm_r; //超限警報(bào)標(biāo)志位 / Q0 W& R+ u2 `6 n
Stm32_Clock_Init(9); //系統(tǒng)時(shí)鐘設(shè)置 delay_init(72); //延時(shí)初始化 uart_init(72,9600); //串口1初始化 LED_Init(); Adc_Init(); Timer2_Init(5000,7199); //定時(shí)報(bào)警 Timer3_Init(2000,7199); //定時(shí)采集ADC // Timer4_Init(5000,7199); //定時(shí)打印 4 q/ L. U1 M7 w" y# f0 L9 ^
while(1) { lim_alarm_l = isOverrun(distance_l[0]); //返回超限標(biāo)志 lim_alarm_r = isOverrun(distance_r[0]); //返回剎車中標(biāo)志 brake_state_l = isBrake_state(distance_l[0], max_value_l, min_value_l); brake_state_r = isBrake_state(distance_r[0], max_value_r, min_value_r); //報(bào)警處理函數(shù) Alarm_dispose(lim_alarm_l, lim_alarm_r, lock_alarm); } } /** 定時(shí)器2中斷服務(wù)程序 功能:發(fā)生定時(shí)中斷控制蜂鳴器報(bào)警 */ void TIM2_IRQHandler(void) { 4 z6 d/ O6 k' C, f, u
if(TIM2->SR&0X0001) //溢出中斷 { BUZZER = 0; delay_ms(100); BUZZER = 1; } TIM2->SR&=~(1<<0); //清除中斷標(biāo)志位 } /** 定時(shí)器3中斷服務(wù)程序 功能:發(fā)生定時(shí)中斷時(shí)采集ADC數(shù)據(jù),,并根據(jù)判斷活塞是否卡住 */ void TIM3_IRQHandler(void) { if(TIM3->SR&0X0001)//溢出中斷 { if( ( lock_alarm_l && brake_state_l) || ( lock_alarm_r && brake_state_r) ) lock_alarm = 1; else lock_alarm = 0;
& T7 X& \3 E! n6 b data_collection(); //數(shù)據(jù)采集后判斷是否活塞卡住
, G4 }+ [7 k# |1 T5 z+ L9 k3 r } TIM3->SR&=~(1<<0); //清除中斷標(biāo)志位 } /** 功能:1.判斷左活塞是否卡住 2.設(shè)置剎車標(biāo)志 */ bool is_stuck(u16 distance_zero, u16 distance_one, bool brake_state, u16 *max_value, u16 *min_value) { u8 motion; ' a% D4 k$ q( c# {' `+ p. A$ U
if( (distance_one-distance_zero) > 5) //松剎車標(biāo)志 motion = LOOSEN;
& ^' ]. T1 W5 R5 ?* w' S if( (distance_one-distance_zero) < -5) //踩剎車標(biāo)志 motion = TREAD; , f$ {" K: V+ b. p; ]
if( ( (distance_one-distance_zero) < LIM) && ( (distance_zero-distance_one) < LIM) ) { /* 踩剎車時(shí)動(dòng)態(tài)設(shè)置最小值剎車標(biāo)志*/ if(motion == TREAD) /* 如果這次值比上次設(shè)置的標(biāo)志值小說明上次是卡住值,,更新最小值標(biāo)志*/ if(distance_zero+DIFFERENCE < *min_value ) *min_value = distance_zero+DIFFERENCE;
; C. P) Y. D6 Z/* 松剎車時(shí)動(dòng)態(tài)設(shè)置最大值剎車標(biāo)志*/ if(motion == LOOSEN) /* 如果這次值比上次設(shè)置的標(biāo)志值大說明上次是卡住值,更新新的標(biāo)志*/ if(distance_zero-DIFFERENCE > *max_value ) count++; //防干擾計(jì)數(shù) if(count > 1) { *max_value = distance_zero-DIFFERENCE; count = 0; }
, n& I9 k' `% n+ H. X* C motion = CLEAR; //清除剎車標(biāo)志 , ^8 Y6 X0 n# A3 J' I
if( brake_state ) //剎車時(shí)如果卡住開始計(jì)數(shù) lock_count++; 6 q7 r4 ~0 o- ^; o3 N3 s. z
if( lock_count >= 5 ) //計(jì)數(shù)五次后報(bào)警位置位 { lock_count = 5; return TRUE; } } else { // lock_alarm = 0; lock_count = 0; return FALSE; } } /** 功能:判斷活塞是否卡住數(shù)據(jù)采集函數(shù) */ void data_collection(void) {
* y1 w: a$ P0 z0 V* M u16 distance_zero, distance_one; % v# o) l7 J- \
filter(ADC_CH0); distance_l = sum;
/ ?# a" B9 K; R% e8 [; ^9 w4 i3 E delay_ms(20); - s% S8 r. H! \) s/ a1 J
filter(ADC_CH1); distance_r = sum; i++; if(i > 1) //采集了兩組數(shù)據(jù)后判斷一次是否卡住 { i = 0; distance_zero = distance_l[0]; distance_one = distance_l[1]; lock_alarm_l = is_stuck(distance_zero, distance_one, brake_state_l, &max_value_l, &min_value_l); distance_zero = distance_r[0]; distance_one = distance_r[1]; lock_alarm_r = is_stuck(distance_zero, distance_one, brake_state_r, &max_value_r, &min_value_r); // d_value = distance_l[1]-distance_l[0]; // printf("%d,%d\n", motion_l, motion_r); printf("%d,%d,%d,%d\n",max_value_l,min_value_l,max_value_r,min_value_r); // printf("%d,%d,%d,%d\n",lock_alarm_l, lock_alarm_r ,lock_count_l, lock_count_r); // printf("%d,%d,%d,%d\n",distance_l[0],distance_l[1],distance_r[0],distance_r[1]); // printf("%d,%d\n",distance_l[1]-distance_l[0],distance_r[1]-distance_r[0]); // printf("%d\n",distance_r[1]-distance_r[0]); } }
$ ~% A% h8 f& [5 T1 w $ U7 ^5 q- u9 i+ K. J9 s' Y X# P
( @7 u- S$ g" y* S7 e1 S! s
1 w; j( [1 a0 R1 t* {/ T$ W, w' P
! T% p. O3 {& J- @# y5 a
0 F5 i. O; S- S. r7 y
" `& Y4 D& T+ V/ _. ^
4 h0 S' U; B" I; r' E
2 r- G4 P" f% C. [" r3 U; i V: t( u$ A9 M
5 i7 e6 t; s5 D; B. K
. g( w+ |% [. ?! g! E" O$ C! F2 g* {4 g+ n9 Q) |
6 f7 _5 @9 _$ X5 |+ x: y& Q
: s+ t: Y! Z1 Q x7 H# G8 t; ]8 _6 F& s# a! o w0 V
# K$ X/ L' w* f* F4 B% J8 t! \
' C0 o2 P/ m' i9 c( N4 n8 l
3 ~ G. @3 a5 {) f/ O4 c4 Q
+ K- {+ s: V6 c6 X, m) N4 P# q
! s) g; p" M5 }' g4 Y y, ~: i |