本項(xiàng)目是一個(gè)采用Traffic LED模塊、Arduino Uno/Nano,以及TOF10120飛行時(shí)間傳感器的工業(yè)級(jí)智能停車(chē)系統(tǒng)。項(xiàng)目采用一塊切邊的墊子作為停車(chē)區(qū),先測(cè)量墊子長(zhǎng)度,再根據(jù)這個(gè)數(shù)值定義不同距離的代碼,一個(gè)接一個(gè)的點(diǎn)亮(ON)和熄滅(OFF)這些LEDs,以幫助司機(jī)安全停車(chē):
當(dāng)汽車(chē)即將進(jìn)入停車(chē)區(qū)域時(shí),綠色LED點(diǎn)亮。然后,黃色LED點(diǎn)亮,提醒司機(jī)即將接近目標(biāo)停車(chē)位置,這表明汽車(chē)車(chē)身已經(jīng)有一半位于停車(chē)區(qū)域。
當(dāng)紅色LED開(kāi)始閃爍時(shí),警告司機(jī)緩慢行駛并留意,到達(dá)停車(chē)點(diǎn)后關(guān)閉汽車(chē),或者繼續(xù)移動(dòng)直到紅色LED停止閃爍。
?

?
作為一個(gè)用以理解停車(chē)系統(tǒng)的原型,項(xiàng)目使用的均為廉價(jià)元件。讀者可對(duì)電路進(jìn)行升級(jí),如改變代碼中的測(cè)量距離數(shù)值,甚至替換電路中的傳感器等,使項(xiàng)目更加實(shí)用。
?
ToF10120飛行時(shí)間傳感器
?
tof10120激光模塊最大的優(yōu)勢(shì)在于測(cè)距遠(yuǎn)、操作簡(jiǎn)單,程序中僅僅需要通過(guò)單片機(jī)給模塊串口發(fā)送命令字符串,就可以向單片機(jī)發(fā)送回距離數(shù)據(jù)。如果發(fā)送自動(dòng)測(cè)距的字符串命令,則模塊會(huì)按照一定頻率自動(dòng)回送數(shù)據(jù),相關(guān)物理量都可以通過(guò)命令字符串設(shè)置。傳感器僅需要串口就可以實(shí)現(xiàn)。
?

?
TOF10120基于Sharp低成本標(biāo)準(zhǔn)CMOS工藝和SPAD技術(shù),可為自動(dòng)對(duì)焦(AF)提供精確、可重復(fù)的長(zhǎng)距離測(cè)量,測(cè)量結(jié)果不受物體反射的影響。主要特點(diǎn)包括:
?采用940nm激光;
?小型陶瓷封裝(20×13.2×2.0mm);
? 可在室內(nèi)測(cè)量長(zhǎng)達(dá)1.8m長(zhǎng)度,精度5%;
?測(cè)量距離不受姆堡反射的影響;
?先進(jìn)廣促俄串?dāng)_補(bǔ)償技術(shù);
?30ms高速測(cè)量;
?單電源供電;
?Txd接口用于設(shè)備控制和數(shù)據(jù)傳送;
?無(wú)鉛,符合RoHS指令。
?

?
TOF10120典型測(cè)距范圍為100-1800mm,電源電壓3-5v,消耗電流35mA,兼容Arduino、ESP8266、ESP32等5V和3.3V控制板,適合-20°C to +70°C等室內(nèi)外環(huán)境。
TOF10120支持UART、I2C通訊,1#引腳、2#引腳、3#引腳、4#引腳、5#引腳、6#引腳分別為GND、VDD、RXD、TXD、SDA、SCL。在六個(gè)引腳中,本項(xiàng)目只使用了其中的GND, VDD, SDA, and SCL四個(gè)腳。
根據(jù)數(shù)據(jù)表,TOF10120的I2C地址為0xA4,但尋址采用高7bit即0x52,這相當(dāng)于82。
?
交通LED模塊
?
該模塊為司機(jī)提供指示,本身帶有限流電阻,無(wú)需額外連接電阻器。
?

?
模塊共有4個(gè)公頭,GND引腳鏈接與控制器的GND引腳,或數(shù)字引腳。這樣,5v信號(hào)將熄滅模塊,GND or LOW電平信號(hào)將啟動(dòng)模塊。其中,R標(biāo)號(hào)代表紅色LED, Y標(biāo)號(hào)代表黃色LED,G標(biāo)號(hào)代表綠色LED,高電平信號(hào)時(shí)LED點(diǎn)亮。
?
連接電路
?
首先,按照電路圖,5V電源由LM7805三端穩(wěn)壓器提供給Arduino Nano,后面需要連接一個(gè)470uF的去耦鋁電解電容器。
?

?
其中,5v穩(wěn)壓連接到Arduino Nano的VIN引腳,TOF10120激光測(cè)距模塊的SCL、SDA引腳分別連接于A(yíng)rduino板子的A5、A4引腳,電源線(xiàn)鏈接于A(yíng)rduino板子的5V和接地引腳。
信號(hào)燈LED模塊的GND引腳鏈接到Arduino板子的5號(hào)引腳,紅色LED鏈接到Arduino的4號(hào)引腳,黃色LED連接到3號(hào)引腳,綠色LED連接到2號(hào)引腳。
?
PCB設(shè)計(jì)
?
接下來(lái),設(shè)計(jì)Arduino Nano PCB開(kāi)發(fā)板,母頭用于3.3V、12V、5V和接地,左側(cè)作為Vero板用來(lái)焊接其他電子元件,Arduino Nano的左右兩側(cè)都設(shè)計(jì)母頭來(lái)連接跳線(xiàn),也可連接傳感器和電子元器件,例如TOF10120傳感器和OLED顯示模塊的I2C引腳。
?

?
最后,將Traffic LED模塊連接于A(yíng)rduino板子的5、4、3、2引腳,再用公頭連來(lái)連接TOF10120傳感器的GND、Vdd、SCL、SDA引線(xiàn)。
?

?
做完上述連接后,就使用下述代碼進(jìn)行I2C尋址:
?
#include
void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 0; address <= 127; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknow error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(30000);
}
?
#include
void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 0; address <= 127; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknow error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(30000);
}
?
上述代碼上傳完成后,打開(kāi)serial monitor就會(huì)看到TOF10120激光傳感器的I2C地址。按照數(shù)據(jù)手冊(cè),TOF10120模塊的I2C地址為0xA4,由于其尋址采用了高7 bits,這樣就變成了0x52,相當(dāng)于82。
?

?
至此,大家已經(jīng)知道了i2c地址,可以把TOF10120測(cè)距傳感器模塊固定到板子上了。該傳感器須固定到適當(dāng)?shù)母叨?,?a target="_blank">檢測(cè)車(chē)輛和距離。這當(dāng)然不難,你可以豎一個(gè)底部帶有螺絲的膠塊,我為了方便站了一個(gè)充電器的外殼,只要高度滿(mǎn)足即可。
?

?
下面是本項(xiàng)目的代碼,我是按照裁剪的墊子大小來(lái)寫(xiě)的,這個(gè)尺寸正好就是停車(chē)區(qū)域的大小。
?
/* Smart Car Parking system Code
* In this project the TOF10120 Laser Distance Sensor is used for measuring the distance.
*/
?
#include
?
// Traffic LED Module interfacing with Arduino Uno or Arduino Nano
int GND_PIN = 5;
int RED_PIN = 4;
int YELLOW_PIN = 3;
int GREEN_PIN = 2;
?
unsigned char ok_flag;
unsigned char fail_flag;
?
unsigned short lenth_val = 0;
unsigned char i2c_rx_buf[16];
unsigned char dirsend_flag=0;
?
int x_mm; // distance in millimeters
float y_inches; // distance in inches
?
void setup() {
Wire.begin();
Serial.begin(9600,SERIAL_8N1);
printf_begin();
pinMode(GND_PIN, OUTPUT);
pinMode(RED_PIN, OUTPUT);
pinMode(YELLOW_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
?
digitalWrite(GND_PIN, LOW);
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
?
}
?
void loop() {
?
x_mm = ReadDistance();
// Serial.print(x_mm);
// Serial.println(" mm");
?
// You can convert millimeters to inches in one of two ways: divide the number of millimeters by 25.4, or multiply the number of millimeters by 0.0394
y_inches = x_mm * 0.0394;
// Serial.print(y_inches);
// Serial.println(" inches");
?
if ( (y_inches > 0) && (y_inches <= 3) )
{
digitalWrite(RED_PIN, HIGH);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
?
if ( (y_inches > 3) && (y_inches <= 6) )
{
digitalWrite(RED_PIN, HIGH);
delay(200);
digitalWrite(RED_PIN, LOW);
delay(200);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
?
?
if ( (y_inches > 6) && (y_inches <= 10) )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, HIGH);
digitalWrite(GREEN_PIN, LOW);
}
?
if ( (y_inches > 10) && (y_inches <= 20) )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, HIGH);
}
?
if ( y_inches > 20 )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
?
if ( y_inches < 0 )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
}
?
int serial_putc( char c, struct __file * )
{
Serial.write( c );
return c;
}
?
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
?
?
void SensorRead(unsigned char addr,unsigned char* datbuf,unsigned char cnt)
{
unsigned short result=0;
// step 1: instruct sensor to read echoes
Wire.beginTransmission(82); // transmit to device #82 (0x52), you can also find this address using the i2c_scanner code, which is available on electroniclinic.com
// the address specified in the datasheet is 164 (0xa4)
// but i2c adressing uses the high 7 bits so it's 82
Wire.write(byte(addr)); // sets distance data address (addr)
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(1); // datasheet suggests at least 30uS
// step 3: request reading from sensor
Wire.requestFrom(82, cnt); // request cnt bytes from slave device #82 (0x52)
// step 5: receive reading from sensor
if (cnt <= Wire.available()) { // if two bytes were received
*datbuf++ = Wire.read(); // receive high byte (overwrites previous reading)
*datbuf++ = Wire.read(); // receive low byte as lower 8 bits
}
}
?
int ReadDistance(){
SensorRead(0x00,i2c_rx_buf,2);
lenth_val=i2c_rx_buf[0];
lenth_val=lenth_val<<8;
lenth_val|=i2c_rx_buf[1];
delay(300);
return lenth_val;
}
?
/* Smart Car Parking system Code
* In this project the TOF10120 Laser Distance Sensor is used for measuring the distance.
*/
#include
// Traffic LED Module interfacing with Arduino Uno or Arduino Nano
int GND_PIN = 5;
int RED_PIN = 4;
int YELLOW_PIN = 3;
int GREEN_PIN = 2;
unsigned char ok_flag;
unsigned char fail_flag;
unsigned short lenth_val = 0;
unsigned char i2c_rx_buf[16];
unsigned char dirsend_flag=0;
int x_mm; // distance in millimeters
float y_inches; // distance in inches
void setup() {
Wire.begin();
Serial.begin(9600,SERIAL_8N1);
printf_begin();
pinMode(GND_PIN, OUTPUT);
pinMode(RED_PIN, OUTPUT);
pinMode(YELLOW_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
digitalWrite(GND_PIN, LOW);
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
void loop() {
x_mm = ReadDistance();
// Serial.print(x_mm);
// Serial.println(" mm");
// You can convert millimeters to inches in one of two ways: divide the number of millimeters by 25.4, or multiply the number of millimeters by 0.0394
y_inches = x_mm * 0.0394;
// Serial.print(y_inches);
// Serial.println(" inches");
if ( (y_inches > 0) && (y_inches <= 3) )
{
digitalWrite(RED_PIN, HIGH);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
if ( (y_inches > 3) && (y_inches <= 6) )
{
digitalWrite(RED_PIN, HIGH);
delay(200);
digitalWrite(RED_PIN, LOW);
delay(200);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
if ( (y_inches > 6) && (y_inches <= 10) )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, HIGH);
digitalWrite(GREEN_PIN, LOW);
}
if ( (y_inches > 10) && (y_inches <= 20) )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, HIGH);
}
if ( y_inches > 20 )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
if ( y_inches < 0 )
{
digitalWrite(RED_PIN, LOW);
digitalWrite(YELLOW_PIN, LOW);
digitalWrite(GREEN_PIN, LOW);
}
}
int serial_putc( char c, struct __file * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
void SensorRead(unsigned char addr,unsigned char* datbuf,unsigned char cnt)
{
unsigned short result=0;
// step 1: instruct sensor to read echoes
Wire.beginTransmission(82); // transmit to device #82 (0x52), you can also find this address using the i2c_scanner code, which is available on electroniclinic.com
// the address specified in the datasheet is 164 (0xa4)
// but i2c adressing uses the high 7 bits so it's 82
Wire.write(byte(addr)); // sets distance data address (addr)
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(1); // datasheet suggests at least 30uS
// step 3: request reading from sensor
Wire.requestFrom(82, cnt); // request cnt bytes from slave device #82 (0x52)
// step 5: receive reading from sensor
if (cnt <= Wire.available()) { // if two bytes were received
*datbuf++ = Wire.read(); // receive high byte (overwrites previous reading)
*datbuf++ = Wire.read(); // receive low byte as lower 8 bits
}
}
int ReadDistance(){
SensorRead(0x00,i2c_rx_buf,2);
lenth_val=i2c_rx_buf[0];
lenth_val=lenth_val<<8;
lenth_val|=i2c_rx_buf[1];
delay(300);
return lenth_val;
}
?
上面是編程代碼,前提是已經(jīng)下載了 Wire.h 庫(kù)文件,代碼中的距離單位為英寸,歡迎實(shí)踐和分享。
?
電子發(fā)燒友App







評(píng)論