步驟1:設備背后的理論
我們生活在空氣的海底。這里的壓力約為1020hPa(百帕斯卡),因為空氣柱在此形成的空間重量約為每平方厘米1千克。
水的密度要高得多,因為1升空氣重約1.2克,1升水1千克,即約800倍。因此,當每8米高度的氣壓下降約1hPa時,水面下每厘米的壓力增益為1hPa。在約10米的深度,壓力為2000hPa,或兩個大氣壓。
此處使用的壓力傳感器的測量范圍介于750和1500 hPa之間,分辨率約為1 hPa。這意味著我們可以在大約1厘米的分辨率下測量高達5米的深度。
該設備將是Boyle Marriotte型深度計。它的組裝非常簡單,將在后面的步驟中介紹。傳感器使用I2C協議,因此micro:bit的邊緣連接器非常方便。最關鍵的部分是防水袋,因為任何濕度都會損壞微型鉆頭,傳感器或電池。由于一些空氣將被困在袋內,增加重量有助于補償浮力。
步驟2:使用設備
腳本,詳細信息如圖所示在后面的步驟中,是我之前為壓力計開發的腳本的變體。要測試設備,您可以使用那里描述的簡單壓力室。
對于潛水目的,它顯示以壓力測量計算的深度,以20 cm步長的條形圖或根據要求以數字顯示。
使用微型按鈕A :位,您將當前壓力設置為參考壓力值。要確認輸入,矩陣會閃爍一次。
您可以使用它來查看潛水的深度,或記錄您潛水的深度。
在第一種情況下,將當前的外部氣壓設置為參考。在第二種情況下,將壓力設置在最深處,作為壓力參考,然后可以顯示當您回到地面時的深度。
按鈕B顯示根據壓差計算的深度,以米為單位的數值。
第3步:所需材料
微觀:位。例如。 Pimoroni UK/DE以13英鎊/16歐元計算。
邊緣連接器(Kitronic或Pimoroni),5英鎊。我使用了Kitronic版本。
BMP/BME280傳感器。我使用Banggood的BMP280傳感器,三個單元4.33歐元。
連接傳感器和邊緣連接器的跳線。
上面邊緣連接器/傳感器組合的一個很好的替代品可能是Pimoroni enviro:bit(現在未經測試,請參見最后一步)。
用于micro:bit的電池組或LiPo。
帶開關的電源線(可選但有幫助) )。
明確的防水袋。我使用硅膠袋作為手機和一個或兩個小拉鏈袋。
確保材料足夠厚,因此邊緣連接器上的針腳不會損壞袋子。
一些重量。我使用了用于釣魚的鉛塊。
Arduino IDE和幾個庫。
第4步:匯編
安裝Arduino IDE和所需的庫。詳細信息在此處描述。
(MakeCode腳本不需要。)
給定使用Kitronik邊緣連接器,將引腳連接到I2C端口19和20.
這不是必需的用于Pimoroni邊緣連接器。
將傳感器的接頭焊接到傳感器上,并使用跨接電纜連接傳感器和邊緣連接器。
將VCC連接到3V,GND連接到0 V,SCL連接到端口19,SDA連接到端口20.
或者將電纜直接焊接到分支。
通過USB電纜將micro:bit連接到我們的計算機。
打開提供的腳本并將其閃存到micro:bit。
使用串行監視器或繪圖儀,檢查傳感器是否提供合理的數據。
從計算機上斷開micro:位。
將電池或LiPo連接到micro:位。
按下按鈕B,讀取值
按下按鈕A.
按下按鈕B,讀取數值。
將設備放在兩層密封袋中,袋中只留下很少的空氣。
如果放置重物以補償浮力。
檢查一切是否都是水密的。
前往游泳池玩游戲。
第5步:MicroPython腳本
腳本只需從中獲取壓力值傳感器,將其與參考值進行比較,然后根據差值計算深度。為了將值顯示為條形圖,采用深度值的整數和余數部分。第一個確定線的高度。其余部分分成五個箱子,它們確定了欄桿的長度。頂層為0 - 1 m,最低4 - 5 m。
如前所述,按下按鈕A設置參考壓力,按鈕B顯示“相對深度”,以米為單位,顯示為數值。到目前為止,負值和正值以相同的方式顯示在LED矩陣上的條形圖。
您可以根據需要隨意優化腳本。您可以取消靜音某些行以在Arduino IDE的串行監視器或繪圖儀上顯示值。要模擬該功能,您可以構建我在之前的instructable中描述的設備。
我沒有寫過讀取傳感器的腳本部分。我不確定來源,但我要感謝autors。歡迎任何更正或優化提示。
#include
#include
Adafruit_Microbit_Matrix microbit;
#define BME280_ADDRESS 0x76
unsigned long int hum_raw,temp_raw,pres_raw;
signed long int t_fine;
uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int8_t dig_H1;
int16_t dig_H2;
int8_t dig_H3;
int16_t dig_H4;
int16_t dig_H5;
int8_t dig_H6;
double press_norm = 1015; // a starting value
double depth; // calculated depth
//--------------------------------------------------------------------------------------------------------------------
void setup()
{
uint8_t osrs_t = 1; //Temperature oversampling x 1
uint8_t osrs_p = 1; //Pressure oversampling x 1
uint8_t osrs_h = 1; //Humidity oversampling x 1
uint8_t mode = 3; //Normal mode
uint8_t t_sb = 5; //Tstandby 1000ms
uint8_t filter = 0; //Filter off
uint8_t spi3w_en = 0; //3-wire SPI Disable
uint8_t ctrl_meas_reg = (osrs_t 《《 5) | (osrs_p 《《 2) | mode;
uint8_t config_reg = (t_sb 《《 5) | (filter 《《 2) | spi3w_en;
uint8_t ctrl_hum_reg = osrs_h;
pinMode(PIN_BUTTON_A, INPUT);
pinMode(PIN_BUTTON_B, INPUT);
Serial.begin(9600); // set serial port speed
Serial.print(“Pressure [hPa] ”); // header for serial output
Wire.begin();
writeReg(0xF2,ctrl_hum_reg);
writeReg(0xF4,ctrl_meas_reg);
writeReg(0xF5,config_reg);
readTrim(); //
microbit.begin();
// microbit.print(“x”);
delay (1000);
}
//---------------------------------------------------------------------------------------------
void loop()
{
double temp_act = 0.0, press_act = 0.0, hum_act=0.0;
signed long int temp_cal;
unsigned long int press_cal, hum_cal;
int N;
int M;
double press_delta; // relative pressure
int depth_m; // depth in meters, integer part
double depth_cm; // remainder in cm
readData();
// temp_cal = calibration_T(temp_raw);
press_cal = calibration_P(pres_raw);
// hum_cal = calibration_H(hum_raw);
// temp_act = (double)temp_cal / 100.0;
press_act = (double)press_cal / 100.0;
// hum_act = (double)hum_cal / 1024.0;
microbit.clear(); //reset LED matrix
// Button A sets actual value as reference (P zero)
// Button B display current value as depth in meters (calculated from pressure difference)
if (! digitalRead(PIN_BUTTON_A)) {
// set normal air pressure as zero
press_norm = press_act;
// microbit.print(“P0: ”);
// microbit.print(press_norm,0);
// microbit.print(“ hPa”);
microbit.fillScreen(LED_ON); // blink once to confirm
delay (100);
}else if (! digitalRead(PIN_BUTTON_B)) {
// display depth in meters
microbit.print(depth,2);
microbit.print(“m”);
// Serial.println(“”);
}else{
// calculate depth from pressure difference
press_delta = (press_act - press_norm); // calculate relative pressure
depth = (press_delta/100); // depth in meters
depth_m = int(abs(depth)); // depth im meters
depth_cm = (abs(depth) - depth_m); // remainder
/* // used for development
Serial.println(depth);
Serial.println(depth_m );
Serial.println(depth_cm);
*/
// Steps for bargraph
if (depth_cm 》 0.8){ // set length of bars
(N=4);
} else if (depth_cm 》 0.6){
(N=3);
} else if (depth_cm 》 0.4){
(N=2);
} else if (depth_cm 》 0.2){
(N=1);
} else {
(N=0);
} if (depth_m == 4){ // set level == meter
(M=4);
} else if (depth_m == 3){
(M=3);
} else if (depth_m == 2){
(M=2);
} else if (depth_m == 1){
(M=1);
} else {
(M=0); // upper row
}
/* // used for development purposes
Serial.print(“m: ”);
Serial.println(depth_m);
Serial.print(“cm: ”);
Serial.println(depth_cm);
Serial.print(“M: ”); Serial.println(M); // for development purposes
Serial.print(“N: ”); Serial.println(N); // for development purposes
delay(500);
*/
// draw bargraph
microbit.drawLine(0, M, N, M, LED_ON);
} // send value to serial port for plotter
Serial.print(press_delta);
// draw indicator lines and fix displayed range
Serial.print(“ ”); Serial.print(0);
Serial.print(“ ”); Serial.print(-500);
Serial.print(“ ”); Serial.println(500);
delay(500); // Measure twice a second
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------
// the following is required for the bmp/bme280 sensor,keep as it is
void readTrim()
{
uint8_t data[32],i=0; // Fix 2014/04/06
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0x88);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,24); // Fix 2014/04/06
while(Wire.available()){
data[i] = Wire.read();
i++;
}
Wire.beginTransmission(BME280_ADDRESS); // Add 2014/04/06
Wire.write(0xA1); // Add 2014/04/06
Wire.endTransmission(); // Add 2014/04/06
Wire.requestFrom(BME280_ADDRESS,1); // Add 2014/04/06
data[i] = Wire.read(); // Add 2014/04/06
i++; // Add 2014/04/06
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xE1);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,7); // Fix 2014/04/06
while(Wire.available()){
data[i] = Wire.read();
i++;
}
dig_T1 = (data[1] 《《 8) | data[0];
dig_P1 = (data[7] 《《 8) | data[6];
dig_P2 = (data[9] 《《 8) | data[8];
dig_P3 = (data[11]《《 8) | data[10];
dig_P4 = (data[13]《《 8) | data[12];
dig_P5 = (data[15]《《 8) | data[14];
dig_P6 = (data[17]《《 8) | data[16];
dig_P7 = (data[19]《《 8) | data[18];
dig_T2 = (data[3] 《《 8) | data[2];
dig_T3 = (data[5] 《《 8) | data[4];
dig_P8 = (data[21]《《 8) | data[20];
dig_P9 = (data[23]《《 8) | data[22];
dig_H1 = data[24];
dig_H2 = (data[26]《《 8) | data[25];
dig_H3 = data[27];
dig_H4 = (data[28]《《 4) | (0x0F & data[29]);
dig_H5 = (data[30] 《《 4) | ((data[29] 》》 4) & 0x0F); // Fix 2014/04/06
dig_H6 = data[31]; // Fix 2014/04/06
}
void writeReg(uint8_t reg_address, uint8_t data)
{
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(reg_address);
Wire.write(data);
Wire.endTransmission();
}
void readData()
{
int i = 0;
uint32_t data[8];
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xF7);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,8);
while(Wire.available()){
data[i] = Wire.read();
i++;
}
pres_raw = (data[0] 《《 12) | (data[1] 《《 4) | (data[2] 》》 4);
temp_raw = (data[3] 《《 12) | (data[4] 《《 4) | (data[5] 》》 4);
hum_raw = (data[6] 《《 8) | data[7];
}
signed long int calibration_T(signed long int adc_T)
{
signed long int var1, var2, T;
var1 = ((((adc_T 》》 3) - ((signed long int)dig_T1《《1))) * ((signed long int)dig_T2)) 》》 11;
var2 = (((((adc_T 》》 4) - ((signed long int)dig_T1)) * ((adc_T》》4) - ((signed long int)dig_T1))) 》》 12) * ((signed long int)dig_T3)) 》》 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) 》》 8;
return T;
}
unsigned long int calibration_P(signed long int adc_P)
{
signed long int var1, var2;
unsigned long int P;
var1 = (((signed long int)t_fine)》》1) - (signed long int)64000;
var2 = (((var1》》2) * (var1》》2)) 》》 11) * ((signed long int)dig_P6);
var2 = var2 + ((var1*((signed long int)dig_P5))《《1);
var2 = (var2》》2)+(((signed long int)dig_P4)《《16);
var1 = (((dig_P3 * (((var1》》2)*(var1》》2)) 》》 13)) 》》3) + ((((signed long int)dig_P2) * var1)》》1))》》18;
var1 = ((((32768+var1))*((signed long int)dig_P1))》》15);
if (var1 == 0)
{
return 0;
}
P = (((unsigned long int)(((signed long int)1048576)-adc_P)-(var2》》12)))*3125;
if(P《0x80000000)
{
P = (P 《《 1) / ((unsigned long int) var1);
}
else
{
P = (P / (unsigned long int)var1) * 2;
}
var1 = (((signed long int)dig_P9) * ((signed long int)(((P》》3) * (P》》3))》》13)))》》12;
var2 = (((signed long int)(P》》2)) * ((signed long int)dig_P8))》》13;
P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) 》》 4));
return P;
}
unsigned long int calibration_H(signed long int adc_H)
{
signed long int v_x1;
v_x1 = (t_fine - ((signed long int)76800));
v_x1 = (((((adc_H 《《 14) -(((signed long int)dig_H4) 《《 20) - (((signed long int)dig_H5) * v_x1)) +
((signed long int)16384)) 》》 15) * (((((((v_x1 * ((signed long int)dig_H6)) 》》 10) *
(((v_x1 * ((signed long int)dig_H3)) 》》 11) + ((signed long int) 32768))) 》》 10) + (( signed long int)2097152)) *
((signed long int) dig_H2) + 8192) 》》 14));
v_x1 = (v_x1 - (((((v_x1 》》 15) * (v_x1 》》 15)) 》》 7) * ((signed long int)dig_H1)) 》》 4));
v_x1 = (v_x1 《 0 ? 0 : v_x1);
v_x1 = (v_x1 》 419430400 ? 419430400 : v_x1);
return (unsigned long int)(v_x1 》》 12);
步驟6:主要簡化:MakeCode/JavaScript代碼
2018年5月,Pimoroni發布了enviro:bit,它帶有BME280壓力/濕度/溫度傳感器,TCS3472光和顏色傳感器以及MEMS麥克風。此外,他們還為MakeCode編輯器提供了一個JavaScript庫,為這些傳感器提供了一個MicroPython庫。
我一直在使用他們的MakeCode庫為我的設備開發腳本。附上你找到相應的十六進制文件,你可以直接復制到你的micro:bit。
下面你會找到相應的JavaScript代碼。池中的測試與早期版本的腳本運行良好,所以我認為它們也可以正常工作。除了基本的條形圖版本外,還有一個十字準線版本(X)和一個L版本,旨在使閱讀更容易,特別是在光線不足的情況下。選擇你喜歡的那個。
let Column = 0
let Meter = 0
let remain = 0
let Row = 0
let Delta = 0
let Ref = 0
let Is = 0
Is = 1012
basic.showLeds(`
# # # # #
# 。 . 。 #
# 。 # 。 #
# 。 . 。 #
# # # # #
`)
Ref = 1180
basic.clearScreen()
basic.forever(() =》 {
basic.clearScreen()
if (input.buttonIsPressed(Button.A)) {
Ref = envirobit.getPressure()
basic.showLeds(`
# 。 # 。 #
。 # 。 # 。
# # # # #
。 # 。 # 。
# 。 # 。 #
`)
basic.pause(1000)
} else if (input.buttonIsPressed(Button.B)) {
basic.showString(“” + Row + “。” + remain + “ m”)
basic.pause(200)
basic.clearScreen()
} else {
Is = envirobit.getPressure()
Delta = Is - Ref
Meter = Math.abs(Delta)
if (Meter 》= 400) {
Row = 4
} else if (Meter 》= 300) {
Row = 3
} else if (Meter 》= 200) {
Row = 2
} else if (Meter 》= 100) {
Row = 1
} else {
Row = 0
}
remain = Meter - Row * 100
if (remain 》= 80) {
Column = 4
} else if (remain 》= 60) {
Column = 3
} else if (remain 》= 40) {
Column = 2
} else if (remain 》= 20) {
Column = 1
} else {
Column = 0
}
for (let ColA = 0; ColA 《= Column; ColA++) {
led.plot(ColA, Row)
}
basic.pause(500)
}
})
第7步:Enviro:位版本
與此同時,我收到了enviro:bit(20 GBP)和power:bit(6 GBP),來自Pimoroni。
如前所述,enviro:bit配有BME280壓力,濕度和溫度傳感器,還有光和顏色傳感器(參見此處的應用)和MEMS麥克風。
power:bit是一個很好的解決方案,可以為micro:bit供電,并帶有一個開/關開關。
最棒的是它只是點擊和使用,沒有焊接,電纜,面包板。
將enviro:bit添加到micro:bit,將代碼加載到micro:bit,使用它。
在這種情況下,我使用micro,power和enviro:bit,將它們放在一個Ziploc包中,放在一個透明的防水塑料袋中,用于手機,準備就緒。一個非常快速和整潔的解決方案。看圖片。開關足夠大,可以通過保護層使用。
它已經在水中進行了測試,運行良好。在約1.8米的深度處,測量值約為1.7米。對于快速廉價的解決方案來說并不算太糟糕,但遠非完美。調整需要一段時間,因此您可能需要在一定深度停留約10-15秒。
步驟8:電纜和傳感器探頭版本
這實際上是第一個想法a。用于微型:位深度計,最后要構建。
在這里,我將BMP280傳感器焊接到5米長的4線電纜上,并在另一端放置了母跳線。
為了保護傳感器免受水的侵害,電纜穿過用過的葡萄酒軟木塞。軟木塞的末端用熱膠密封。在我將兩個切口切入軟木塞之前,兩者都在它周圍。然后我將傳感器裝入海綿球中,在其周圍放置一個氣球,并將氣球的末端固定在軟木塞上(下切口)。然后我將3個40克的鉛塊放入第二個氣球中,將其包裹在第一個氣囊周圍,將重物放在外側,并將氣球的末端固定在第二個凹口處。從第二個氣球中取出空氣,然后用膠帶固定所有東西。查看圖片,可能會有更詳細的圖片。
通過邊緣連接器將跳線連接到micro:bit,打開設備并設置參考壓力。然后將傳感器頭緩慢釋放到水池底部(10米跳塔,深約4.5米)。
結果:
令我驚訝的是,即使使用這根長電纜也能正常工作。另一方面,但毫不奇怪,在較高壓力下測量誤差似乎變得更大,據報道估計深度為4米,約為3米。
潛在的應用程序:
通過一些錯誤修正,該設備可用于測量深度約為4米。
與Arduino或Raspberry Pi配合使用,可用于測量和控制水池或水箱的灌裝點,例如:如果水位高于或低于某些閾值,則發出警告。
-
測量儀
+關注
關注
1文章
664瀏覽量
32955
發布評論請先 登錄
相關推薦
評論