以LDC1000電感/數字轉換器為核心,設計并制作了一個可自動根據鐵絲形狀循跡小車。系統的主要功能模塊包括:主控模塊、金屬信號探測模塊、速度檢測模塊,電機驅動模塊及電源模塊。系統主控芯片STC89C52根據檢測到的金屬距離信號,判斷小車是否偏離軌道,從而做出方向調整,使小車能夠在規定的平面跑道自動按一定方向自動循跡。
循軌廣泛應用很于工業自動化及系統,而循跡的方式有很多種,每種都有其缺點。機械鏈條式軌道存在磨損占用地方;光電慢反射檢測式需要軌道為黑色、受環境光影響比較大;攝像頭模式識別式需要很好的識別算法,受環境光影響也比較大。
基于此,本文采用LDC1000對鐵絲進行檢測判斷,實現自動循軌應用。
LDC1000簡介
LDC1000是美國德州儀器公司TI推出的一塊全新的電感數字轉換器(LDC),具有低功耗,小封裝,低成本的優良性質。它的SPI界面可以很方便的連接MCU。LDC1000只需要外接一個PCB線圈或者自制線圈就可以實現非接觸式電感檢測。LDC1000的電感檢測并不是指像Q表那樣測試線圈的電感量,而是可以測試外部金屬物體和LDC1000相連的測試線圈的空間位置關系。
利用LDC1000這個特性配以外部設計的金屬物體即可很方便實現,水平或垂直距離檢測;角度檢測;位移監測;運動檢測;振動檢測;金屬成分檢測;可以廣泛應用在汽車、消費電子、計算機、工業、通信和醫療領域。
stc89c52 與LDC1000接口
mcu與LDC1000接口圖
使用stc89c52的io口模擬spi接口,和從機(LDC1000)進行通訊的時候,應該遵循以下幾個步驟:
片選信號置零;
stc89c52通過模擬SPI線向LDC1000寫入訪問寄存器地址,其中最高位0表示寫入,1表示讀出,其余7位為寄存器的地址;
如果命令在讀寫狀態時,傳輸的數據最高位為1,SDO在線發送來自其他地址寄存器的8位字節;
如果命令在讀寫狀態時,SDI線接收來自stc89c52的8位字節數據寫入相應的寄存器中;
片選信號置高,釋放對該從機的控制。
LDC1000 SPI 讀寫時序圖
stc89c52 驅動程序設計
根據LDC1000的spi接口時序設計如下驅動程序:
// 讀1B數據
unsigned char Ldc_SPIread(void);
//寫1B數據
void Ldc_SPIwrite(unsigned char ch);
//寫寄存器
void LDC1000_WriteReg(unsigned char addr, unsigned char dat);
//讀寄存器
unsigned char LDC1000_ReadReg(unsigned char addr);
//芯片初始化
void LDC1000_Init(void);
//讀取距離參數
?
unsigned int ReadValue(void);
控制邏輯
小車車頭布置感應天線,當小車沿鐵絲向前行車時,由于特殊原因(如路面不平,小車的車輪不對稱等原因)導致車身偏離軌道,出現A,B,C三種情況。(如下圖)。
A,B,C 三種情況的天線下,利用函數ReadValue()得到的數值為Fa,Fb,Fc. 三者間的關系為Fa《Fb, Fc《Fb. 為此,當檢測到數值為Fb時小車直行,否則小車轉彎。左轉與右轉根據轉彎的幅度做調整。 程序流程如下:
根據以上原理制作了系統軌道,實驗小車,并利用串口檢測系統監測的鐵絲數據。鐵絲的直徑0.9mm以上,循軌小車包括控制主板、顯示、光電測速、電機、藍牙收發模塊等。根據車身是否偏離軌道監測到的采樣數據。
總結:
利用PCB線圈或自制線圈可以實現非接觸式電感線圈檢測,通過分析待測金屬物體對電感線圈磁場的影響可以很方便地實現金屬檢測。經實測,通過合理設置模塊寄存器值,可以有效檢測3cm距離的金屬。外界光照條件對本系統沒有太大的影響,而且還必須能夠在一定的距離內快速檢測到金屬并能夠辨別金屬類型。
附:LDC1000驅動程序
#include “reg52.h”
// LDC COMMANDS
#define LDC1000_CMD_REVID 0x00
#define LDC1000_CMD_RPMAX 0x01
#define LDC1000_CMD_RPMIN 0x02
#define LDC1000_CMD_SENSORFREQ 0x03
#define LDC1000_CMD_LDCCONFIG 0x04
#define LDC1000_CMD_CLKCONFIG 0x05
#define LDC1000_CMD_THRESHILSB 0x06
#define LDC1000_CMD_THRESHIMSB 0x07
#define LDC1000_CMD_THRESLOLSB 0x08
#define LDC1000_CMD_THRESLOMSB 0x09
#define LDC1000_CMD_INTCONFIG 0x0A
#define LDC1000_CMD_PWRCONFIG 0x0B
#define LDC1000_CMD_STATUS 0x20
#define LDC1000_CMD_PROXLSB 0x21
#define LDC1000_CMD_PROXMSB 0x22
#define LDC1000_CMD_FREQCTRLSB 0x23
#define LDC1000_CMD_FREQCTRMID 0x24
#define LDC1000_CMD_FREQCTRMSB 0x25
sbit PIN_LDC_CS=P1^0;
sbit PIN_LDC_SO=P1^1;
sbit PIN_LDC_SCK=P1^2;
sbit PIN_LDC_SI=P1^3;
#define SET_PIN_LDC_SI(bValue) PIN_LDC_SI=bValue
#define GET_PIN_LDC_SO() PIN_LDC_SO
#define SET_PIN_LDC_SCK(bValue) PIN_LDC_SCK=bValue
#define SET_PIN_LDC_CS(bValue) PIN_LDC_CS=bValue
/*--------------------------------------------------------------- 功能: 讀1B數據 輸入: 無 輸出: 1B數據----------------------------------------------------------------*/
unsigned char Ldc_SPIread(void)
{
unsigned char i = 0;
ch = 0;
for(i = 0; i 《 8; i ++)
{
SET_PIN_LDC_SCK(0);
ch 《《= 1;
SET_PIN_LDC_SCK(1);
if(GET_PIN_LDC_SO())ch = ch | 0x01;
}
SET_PIN_LDC_SCK(0);
return (ch);
}
/*--------------------------------------------------------------- 功能: 寫1B數據 輸入: ch--1B數據 輸出: 無 ----------------------------------------------------------------*/
void Ldc_SPIwrite(unsigned char ch)
{
unsigned char i = 0;
for(i = 0;i 《 8;i ++)
{
SET_PIN_LDC_SCK(0);
if(ch & 0x80) SET_PIN_LDC_SI(1);
else SET_PIN_LDC_SI(0);
SET_PIN_LDC_SCK(1) ch 《《= 1;
}
SET_PIN_LDC_SCK(0)
}
//寫寄存器
void LDC1000_WriteReg(unsigned char addr, unsigned char dat)
{
addr = addr & 0x7F;
SET_PIN_LDC_CS (0);
Ldc_SPIwrite( addr);
Ldc_SPIwrite( dat);
SET_PIN_LDC_CS (1);
}
//讀寄存器
unsigned char LDC1000_ReadReg(unsigned char addr)
{
unsigned char temp;
addr = addr | 0x80;
SET_PIN_LDC_CS (0);
Ldc_SPIwrite( addr);
temp = (UINT8)Ldc_SPIread();
SET_PIN_LDC_CS (1);
return temp;
}
//芯片初始化
void LDC1000_Init(void)
{
LDC1000_WriteReg(LDC1000_CMD_RPMAX, 0x13);
LDC1000_WriteReg(LDC1000_CMD_RPMIN, 0x3A);
LDC1000_WriteReg(LDC1000_CMD_SENSORFREQ, 0x94);
LDC1000_WriteReg(LDC1000_CMD_LDCCONFIG, 0x17);
LDC1000_WriteReg(LDC1000_CMD_CLKCONFIG, 0x02);
LDC1000_WriteReg(LDC1000_CMD_INTCONFIG, 0x02);
LDC1000_WriteReg(LDC1000_CMD_THRESHILSB, 0x50);
LDC1000_WriteReg(LDC1000_CMD_THRESHIMSB, 0x14);
LDC1000_WriteReg(LDC1000_CMD_THRESLOLSB, 0xC0);
LDC1000_WriteReg(LDC1000_CMD_THRESLOMSB, 0x12);
LDC1000_WriteReg(LDC1000_CMD_PWRCONFIG, 0x01);
}
//讀取距離參數
unsigned int ReadValue(void)
{
unsigned int iTemp;
iTemp= LDC1000_ReadReg(LDC1000_CMD_PROXMSB);
iTemp《《=8;
iTemp+= LDC1000_ReadReg(LDC1000_CMD_PROXLSB);
return iTemp;
}
評論
查看更多