本項目是一個采用Traffic LED模塊、Arduino Uno/Nano,以及TOF10120飛行時間傳感器的工業(yè)級智能停車系統(tǒng)。項目采用一塊切邊的墊子作為停車區(qū),先測量墊子長度,再根據(jù)這個數(shù)值定義不同距離的代碼,一個接一個的點(diǎn)亮(ON)和熄滅(OFF)這些LEDs,以幫助司機(jī)安全停車:
當(dāng)汽車即將進(jìn)入停車區(qū)域時,綠色LED點(diǎn)亮。然后,黃色LED點(diǎn)亮,提醒司機(jī)即將接近目標(biāo)停車位置,這表明汽車車身已經(jīng)有一半位于停車區(qū)域。
當(dāng)紅色LED開始閃爍時,警告司機(jī)緩慢行駛并留意,到達(dá)停車點(diǎn)后關(guān)閉汽車,或者繼續(xù)移動直到紅色LED停止閃爍。
?
?
作為一個用以理解停車系統(tǒng)的原型,項目使用的均為廉價元件。讀者可對電路進(jìn)行升級,如改變代碼中的測量距離數(shù)值,甚至替換電路中的傳感器等,使項目更加實用。
?
ToF10120飛行時間傳感器
?
tof10120激光模塊最大的優(yōu)勢在于測距遠(yuǎn)、操作簡單,程序中僅僅需要通過單片機(jī)給模塊串口發(fā)送命令字符串,就可以向單片機(jī)發(fā)送回距離數(shù)據(jù)。如果發(fā)送自動測距的字符串命令,則模塊會按照一定頻率自動回送數(shù)據(jù),相關(guān)物理量都可以通過命令字符串設(shè)置。傳感器僅需要串口就可以實現(xiàn)。
?
?
TOF10120基于Sharp低成本標(biāo)準(zhǔn)CMOS工藝和SPAD技術(shù),可為自動對焦(AF)提供精確、可重復(fù)的長距離測量,測量結(jié)果不受物體反射的影響。主要特點(diǎn)包括:
?采用940nm激光;
?小型陶瓷封裝(20×13.2×2.0mm);
? 可在室內(nèi)測量長達(dá)1.8m長度,精度5%;
?測量距離不受姆堡反射的影響;
?先進(jìn)廣促俄串?dāng)_補(bǔ)償技術(shù);
?30ms高速測量;
?單電源供電;
?Txd接口用于設(shè)備控制和數(shù)據(jù)傳送;
?無鉛,符合RoHS指令。
?
?
TOF10120典型測距范圍為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。在六個引腳中,本項目只使用了其中的GND, VDD, SDA, and SCL四個腳。
根據(jù)數(shù)據(jù)表,TOF10120的I2C地址為0xA4,但尋址采用高7bit即0x52,這相當(dāng)于82。
?
交通LED模塊
?
該模塊為司機(jī)提供指示,本身帶有限流電阻,無需額外連接電阻器。
?
?
模塊共有4個公頭,GND引腳鏈接與控制器的GND引腳,或數(shù)字引腳。這樣,5v信號將熄滅模塊,GND or LOW電平信號將啟動模塊。其中,R標(biāo)號代表紅色LED, Y標(biāo)號代表黃色LED,G標(biāo)號代表綠色LED,高電平信號時LED點(diǎn)亮。
?
連接電路
?
首先,按照電路圖,5V電源由LM7805三端穩(wěn)壓器提供給Arduino Nano,后面需要連接一個470uF的去耦鋁電解電容器。
?
?
其中,5v穩(wěn)壓連接到Arduino Nano的VIN引腳,TOF10120激光測距模塊的SCL、SDA引腳分別連接于Arduino板子的A5、A4引腳,電源線鏈接于Arduino板子的5V和接地引腳。
信號燈LED模塊的GND引腳鏈接到Arduino板子的5號引腳,紅色LED鏈接到Arduino的4號引腳,黃色LED連接到3號引腳,綠色LED連接到2號引腳。
?
PCB設(shè)計
?
接下來,設(shè)計Arduino Nano PCB開發(fā)板,母頭用于3.3V、12V、5V和接地,左側(cè)作為Vero板用來焊接其他電子元件,Arduino Nano的左右兩側(cè)都設(shè)計母頭來連接跳線,也可連接傳感器和電子元器件,例如TOF10120傳感器和OLED顯示模塊的I2C引腳。
?
?
最后,將Traffic LED模塊連接于Arduino板子的5、4、3、2引腳,再用公頭連來連接TOF10120傳感器的GND、Vdd、SCL、SDA引線。
?
?
做完上述連接后,就使用下述代碼進(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);
}
?
上述代碼上傳完成后,打開serial monitor就會看到TOF10120激光傳感器的I2C地址。按照數(shù)據(jù)手冊,TOF10120模塊的I2C地址為0xA4,由于其尋址采用了高7 bits,這樣就變成了0x52,相當(dāng)于82。
?
?
至此,大家已經(jīng)知道了i2c地址,可以把TOF10120測距傳感器模塊固定到板子上了。該傳感器須固定到適當(dāng)?shù)母叨龋?a target="_blank">檢測車輛和距離。這當(dāng)然不難,你可以豎一個底部帶有螺絲的膠塊,我為了方便站了一個充電器的外殼,只要高度滿足即可。
?
?
下面是本項目的代碼,我是按照裁剪的墊子大小來寫的,這個尺寸正好就是停車區(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 庫文件,代碼中的距離單位為英寸,歡迎實踐和分享。
?
評論
查看更多