資料介紹
描述
在科羅拉多州和其他擁有大量野生動(dòng)物種群的州,人類與野生動(dòng)物之間的沖突并不少見(城鎮(zhèn)中的熊和駝鹿、涉及麋鹿的交通事故等)
我決定通過創(chuàng)建一個(gè)檢測運(yùn)動(dòng)、拍照并使用機(jī)器學(xué)習(xí)算法分析它以采取某種行動(dòng)(嚇跑它、點(diǎn)亮標(biāo)志、通知當(dāng)局)。此外,該設(shè)備跟蹤環(huán)境數(shù)據(jù),以幫助研究人員跟蹤可能導(dǎo)致更多野生動(dòng)物遭遇的遷徙模式和條件,它還檢測野火以防止不必要的破壞。
分類
該項(xiàng)目的主要重點(diǎn)是機(jī)器學(xué)習(xí)野生動(dòng)物分類。我通過訓(xùn)練 TensorFlow 來使用來自 Google 圖片的數(shù)據(jù)來識(shí)別四種特定的動(dòng)物物種,從而實(shí)現(xiàn)了這一點(diǎn)。所有的初始訓(xùn)練都是在計(jì)算機(jī)上使用為 TensorFlow 和一千多張野生動(dòng)物圖片預(yù)先配置的 docker 機(jī)器圖像完成的。一旦 TensorFlow 被訓(xùn)練,圖形文件被優(yōu)化以在移動(dòng)設(shè)備上運(yùn)行,然后它可以被用來在 Android Things 設(shè)備上運(yùn)行,方法是拍攝一張圖像,調(diào)整它的大小,然后通過 TensorFlow 運(yùn)行它以確定該圖像是否包含一個(gè)我們預(yù)先訓(xùn)練的分類,以及到什么置信水平。
一旦確定了動(dòng)物,就必須對(duì)這些數(shù)據(jù)進(jìn)行處理。根據(jù)您的情況,您可以使用額外的硬件來閃光、播放聲音或做任何其他事情。對(duì)于這個(gè)原型,我將 Android Things 連接到 Firebase 后端,以便簡單地保存圖像和分類信息。
?
將信息存儲(chǔ)在 Firebase 上后,您可以創(chuàng)建一個(gè)輔助應(yīng)用程序來接收有關(guān)動(dòng)物存在的通知,或者只是存儲(chǔ)該數(shù)據(jù)以用于研究目的。
此外,如果您希望無需檢查 Firebase 即可看到結(jié)果,您可以在此項(xiàng)目中添加 LCD 屏幕。您可以在此處找到 Gautier Mechling為 1601 系列 LCD 屏幕提供的易于使用的驅(qū)動(dòng)程序。
創(chuàng)建 TensorFlow 分類文件
您要做的第一件事是確保 TensorFlow 在您的計(jì)算機(jī)上并且可以正常工作。這可能相當(dāng)復(fù)雜,我發(fā)現(xiàn)在生成訓(xùn)練文件的整個(gè)過程中使其正常工作的最簡單方法是安裝和使用Docker。該程序?qū)⒃试S您在計(jì)算機(jī)上運(yùn)行為 TensorFlow 預(yù)配置的虛擬機(jī)。
一旦你安裝了 Docker 并讓它在你的計(jì)算機(jī)上運(yùn)行,??你應(yīng)該打開它的首選項(xiàng)并為你的虛擬機(jī)設(shè)置內(nèi)存使用。我將我的內(nèi)存設(shè)置為使用 7 GB 內(nèi)存,這可能超出了您的需要,但我花了幾天時(shí)間試圖讓 TensorFlow 正確創(chuàng)建所需的訓(xùn)練圖表而不會(huì)崩潰,然后我才意識(shí)到虛擬機(jī)內(nèi)存不足。
一旦你安裝了 Docker 并在你的機(jī)器上啟動(dòng)它,你需要從終端運(yùn)行它并下載一個(gè)鏡像。對(duì)于此示例,我在 macOS 下運(yùn)行,因此對(duì)于您的平臺(tái),命令可能會(huì)有所不同。
docker run -it -v $HOME/tf_files:/tf_files gcr.io/tensorflow/tensorflow:latest-develcd /tensorflowgit pullgit checkout v1.0.1
當(dāng)一切都完成設(shè)置后,您應(yīng)該在終端中出現(xiàn)如下提示:
root@1643721c503b:/tensorflow#
此時(shí),您需要一組圖像來訓(xùn)練 TensorFlow。我使用Fatkun Batch Download Image Chrome 插件從 Google 搜索中批量下載返回的圖像。安裝插件后,您可以搜索要分類的任何內(nèi)容并開始選擇要保存的圖像。
為了使命名更容易,您可能還需要進(jìn)入“更多選項(xiàng)”部分,讓插件在下載圖像時(shí)重命名它們。
接下來,您需要將正在使用的圖像移動(dòng)到主目錄下的tf_files文件夾中,這是我們?cè)诔跏蓟?docker 機(jī)器時(shí)創(chuàng)建的文件夾。對(duì)于此示例,我的圖像目錄稱為TensorFlowTrainingImages 。每個(gè)可分類項(xiàng)目都應(yīng)該在該目錄中有自己的文件夾,如下所示。
設(shè)置好目錄后,您可以從 Docker 終端使用以下命令開始重新訓(xùn)練:
python tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=/tf_files/bottlenecks \
--how_many_training_steps 3000 \
--model_dir=/tf_files/inception \
--output_graph=/tf_files/graph.pb \
--output_labels=/tf_files/labels.txt \
--image_dir /tf_files/TensorFlowTrainingImages
上面的命令會(huì)生成bottlenecks ,本質(zhì)上是最終分類數(shù)據(jù)傳遞使用的數(shù)據(jù),以及用于分類的圖形和標(biāo)簽文件。
從現(xiàn)在開始,我們使用 TensorFlow 運(yùn)行的操作可能需要幾分鐘到一個(gè)多小時(shí),具體取決于您計(jì)算機(jī)的速度。當(dāng)重新訓(xùn)練命令運(yùn)行時(shí),您應(yīng)該會(huì)在終端中看到很多類似于以下內(nèi)容的輸出:
Step 130: Train accuracy = 95.0%2017-04-12 18:21:28.495779:
Step 130: Cross entropy = 0.2503392017-04-12 18:21:28.748928:
Step 130: Validation accuracy = 92.0% (N=100)
生成瓶頸后,您將擁有一個(gè)graph.pb文件和一個(gè)代表您的數(shù)據(jù)的labels.txt文件。雖然這些格式在您的計(jì)算機(jī)上運(yùn)行分類時(shí)效果很好,但它們?cè)诜湃?Android 應(yīng)用程序時(shí)往往不起作用。您將需要優(yōu)化它們。
首先運(yùn)行/configure
命令。接受所有默認(rèn)值。
配置完成后,運(yùn)行以下命令來設(shè)置優(yōu)化工具。這一步在我的機(jī)器上完成了大約一個(gè)小時(shí)。
bazel build tensorflow/python/tools:optimize_for_inference
構(gòu)建優(yōu)化工具后,您可以使用它通過 bazel 優(yōu)化您的圖形文件。
bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=/tf_files/graph.pb \
--output=/tf_files/optimized_graph.pb \
--input_names=Mul \
--output_names=final_result
現(xiàn)在您的優(yōu)化圖已經(jīng)生成,您可以在您的主目錄的tf_files文件夾中找到它和您的標(biāo)簽。
一旦你有了優(yōu)化的圖表,你就可以將它包含在你的 Android Things 項(xiàng)目中以與之交互。如果您查看該項(xiàng)目的源代碼,您可以看到使用 Camera2 API 獲取圖像并將其傳遞給TensorFlowImageClassifier.java進(jìn)行分類的 Java 代碼。您還可以找到將分類圖像上傳到 Firebase 的代碼,如下所示
private void uploadAnimal(Bitmap bitmap, final Detection detectedAnimal) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
byte[] data = outputStream.toByteArray();
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageReference = storage.getReferenceFromUrl(
FIREBASE_STORAGE_URL).child(System.currentTimeMillis() + ".jpg");
UploadTask uploadTask = storageReference.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
}
}).addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
handleNotificationForImage(taskSnapshot.getDownloadUrl(),
detectedAnimal);
}
});
}
環(huán)境傳感器
雖然能夠識(shí)別野生動(dòng)物很棒,但這里有機(jī)會(huì)做更多的事情。如果這些設(shè)備之一設(shè)置在荒野中,您還可以添加傳感器來保存天氣信息并將其報(bào)告給您的后端。對(duì)于我的原型,我包括了一個(gè)濕度傳感器、溫度和壓力傳感器、一個(gè)火焰探測器(理論上當(dāng)周圍沒有人時(shí)通知某人野火)、一個(gè)空氣質(zhì)量傳感器和一個(gè)紫外線傳感器。其中一些在附加到 Android Things 方面有其獨(dú)特的挑戰(zhàn),我將在下面介紹。
數(shù)字傳感器
連接到野生動(dòng)物探測器的最簡單的傳感器是火焰探測器和運(yùn)動(dòng)探測器。這些傳感器在低電平空閑,但在檢測到火焰或運(yùn)動(dòng)時(shí)切換到高電平。使用 Android Things 的外圍 I/O API,這些傳感器是最容易支持的,因?yàn)樵O(shè)備只需要監(jiān)聽狀態(tài)的變化。
對(duì) HC SR501 和火焰探測器的支持都遵循這個(gè)類的模式
@SuppressWarnings({"unused", "WeakerAccess"})
public class HCSR501 implements AutoCloseable {
public enum State {
STATE_HIGH,
STATE_LOW;
}
public interface OnMotionDetectedEventListener {
void onMotionDetectedEvent(State state);
}
private Gpio mMotionDetectorGpio;
private OnMotionDetectedEventListener mOnMotionDetectedEventListener;
private boolean mLastState;
public HCSR501(String pin) throws IOException {
PeripheralManagerService pioService = new PeripheralManagerService();
Gpio HCSR501Gpio = pioService.openGpio(pin);
try {
connect(HCSR501Gpio);
} catch( IOException | RuntimeException e ) {
close();
throw e;
}
}
private void connect(Gpio HCSR501Gpio) throws IOException {
mMotionDetectorGpio = HCSR501Gpio;
mMotionDetectorGpio.setDirection(Gpio.DIRECTION_IN);
mMotionDetectorGpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
mLastState = mMotionDetectorGpio.getValue();
mMotionDetectorGpio.setActiveType(mLastState ? Gpio.ACTIVE_HIGH : Gpio.ACTIVE_LOW);
mMotionDetectorGpio.registerGpioCallback(mInterruptCallback);
}
private void performMotionEvent(State state) {
if( mOnMotionDetectedEventListener != null ) {
mOnMotionDetectedEventListener.onMotionDetectedEvent(state);
}
}
private GpioCallback mInterruptCallback = new GpioCallback() {
@Override
public boolean onGpioEdge(Gpio gpio) {
try {
if( gpio.getValue() != mLastState ) {
mLastState = gpio.getValue();
performMotionEvent(mLastState ? State.STATE_HIGH : State.STATE_LOW);
}
} catch( IOException e ) {
}
return true;
}
};
public void setOnMotionDetectedEventListener(OnMotionDetectedEventListener listener) {
mOnMotionDetectedEventListener = listener;
}
@Override
public void close() throws IOException {
mOnMotionDetectedEventListener = null;
if (mMotionDetectorGpio != null) {
mMotionDetectorGpio.unregisterGpioCallback(mInterruptCallback);
try {
mMotionDetectorGpio.close();
} finally {
mMotionDetectorGpio = null;
}
}
}
}
模擬傳感器
Android Things 的模擬傳感器有點(diǎn)棘手。雖然設(shè)備可能具有板載模數(shù)轉(zhuǎn)換器 (ADC),但它并未在 Android Things 平臺(tái)上啟用。為了解決這個(gè)問題,我使用了 MCP3008 ADC 芯片來讀取模擬輸入并將其轉(zhuǎn)換為可以在 Android Things 板上讀取的 int。這是通過一種快速而骯臟的“bit banged”方法完成的,因此您可以更改引腳以匹配您可用的任何內(nèi)容。使用 ADC,我能夠添加對(duì)空氣質(zhì)量傳感器和紫外線傳感器的支持。以下代碼是我用于 MCP3008 的代碼,并且在我使用過的多個(gè) Android Things 項(xiàng)目中被證明是有價(jià)值的。
public class MCP3008 {
private final String csPin;
private final String clockPin;
private final String mosiPin;
private final String misoPin;
private Gpio mCsPin;
private Gpio mClockPin;
private Gpio mMosiPin;
private Gpio mMisoPin;
public MCP3008(String csPin, String clockPin, String mosiPin, String misoPin) {
this.csPin = csPin;
this.clockPin = clockPin;
this.mosiPin = mosiPin;
this.misoPin = misoPin;
}
public void register() throws IOException {
PeripheralManagerService service = new PeripheralManagerService();
mClockPin = service.openGpio(clockPin);
mCsPin = service.openGpio(csPin);
mMosiPin = service.openGpio(mosiPin);
mMisoPin = service.openGpio(misoPin);
mClockPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mCsPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mMosiPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mMisoPin.setDirection(Gpio.DIRECTION_IN);
}
public int readAdc(int channel) throws IOException {
if( channel < 0 || channel > 7 ) {
throw new IOException("ADC channel must be between 0 and 7");
}
initReadState();
initChannelSelect(channel);
return getValueFromSelectedChannel();
}
private int getValueFromSelectedChannel() throws IOException {
int value = 0x0;
for( int i = 0; i < 12; i++ ) {
toggleClock();
value <<= 0x1;
if( mMisoPin.getValue() ) {
value |= 0x1;
}
}
mCsPin.setValue(true);
value >>= 0x1; // first bit is 'null', so drop it
return value;
}
private void initReadState() throws IOException {
mCsPin.setValue(true);
mClockPin.setValue(false);
mCsPin.setValue(false);
}
private void initChannelSelect(int channel) throws IOException {
int commandout = channel;
commandout |= 0x18; // start bit + single-ended bit
commandout <<= 0x3; // we only need to send 5 bits
for( int i = 0; i < 5; i++ ) {
if ( ( commandout & 0x80 ) != 0x0 ) {
mMosiPin.setValue(true);
} else {
mMosiPin.setValue(false);
}
commandout <<= 0x1;
toggleClock();
}
}
private void toggleClock() throws IOException {
mClockPin.setValue(true);
mClockPin.setValue(false);
}
public void unregister() {
if( mCsPin != null ) {
try {
mCsPin.close();
} catch( IOException ignore ) {
// do nothing
}
}
if( mClockPin != null ) {
try {
mClockPin.close();
} catch( IOException ignore ) {
// do nothing
}
}
if( mMisoPin != null ) {
try {
mMisoPin.close();
} catch( IOException ignore ) {
// do nothing
}
}
if( mMosiPin != null ) {
try {
mMosiPin.close();
} catch( IOException ignore ) {
// do nothing
}
}
}
}
不支持的硬件
不幸的是,DHT11 濕度傳感器使用以納秒為間隔觸發(fā)的信號(hào)協(xié)議,但 Android 平臺(tái)僅支持低至毫秒。因此,Android Things 無法直接支持 DHT11。但是,有一種解決方法。使用帶有 Arduino 的 ATMega328p,我能夠?qū)⑿畔?DHT11 讀取到 Arduino 芯片,并使用 I2C 將該信息發(fā)送到 Android Things 設(shè)備。
您可以通過在 Android 中打開與該地址的連接來使用自定義地址讀取 I2C
PeripheralManagerService service = new PeripheralManagerService();
mHumidity = service.openI2cDevice(BoardDefaults.getHumidityI2cBus(), 0x08);
在上面的示例中,我們使用的自定義地址是8 。在 ATMega328p 上運(yùn)行的 Arduino 代碼中,您可以將該地址與 Wire 庫一起使用。
#import
#include
dht11 DHT11;
#define DHT11PIN 13
uint8_t humidity;
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
}
void loop() {
int chk = DHT11.read(DHT11PIN);
humidity = DHT11.humidity;
delay(1000);
}
void requestEvent() {
Wire.write(humidity);
}
預(yù)先編寫的驅(qū)動(dòng)程序
雖然添加對(duì)數(shù)字 I/O 的支持很容易,但還有一件事更容易:使用已經(jīng)編寫的代碼。對(duì)于 BMP280,我能夠從 Google 的官方驅(qū)動(dòng)程序庫中引入一個(gè)預(yù)先編寫的驅(qū)動(dòng)程序,讓我無需太多工作或時(shí)間就可以從該環(huán)境傳感器讀取信息。您可以在此處找到 Google 預(yù)先編寫的示例,因?yàn)槠渲杏幸恍┛赡軐?duì)您使用 Android Things 組合在一起的任何項(xiàng)目有用。這些驅(qū)動(dòng)程序很容易進(jìn)入您的項(xiàng)目,就像將它們添加到您的 gradle 依賴項(xiàng)中一樣
dependencies {
compile 'com.google.android.things.contrib:driver-bmx280:0.2'
provided 'com.google.android.things:androidthings:0.4-devpreview'
}
對(duì)于這個(gè)項(xiàng)目,我還使用 GPS 驅(qū)動(dòng)程序?qū)⑽恢脭?shù)據(jù)添加到 Firebase,盡管您可以從您使用的任何網(wǎng)絡(luò)連接中檢索該數(shù)據(jù)。
網(wǎng)絡(luò)連接
在當(dāng)前狀態(tài)下,野生動(dòng)物探測器只是使用無線網(wǎng)絡(luò)連接互聯(lián)網(wǎng)。雖然這不是最實(shí)用的,特別是考慮到它很可能在沒有現(xiàn)成的無線連接的區(qū)域使用,但可以輕松修改它以支持蜂窩連接或任何其他更合適的連接。
相機(jī)
這里的相機(jī)有點(diǎn)棘手。目前 Android Things 不完全支持 USB 攝像頭,但您可以將它們視為 UART 設(shè)備。如果您不想為您的相機(jī)編寫驅(qū)動(dòng)程序,您也可以使用藍(lán)牙相機(jī),因?yàn)?Android Things 確實(shí)支持藍(lán)牙連接。如果您將 Raspberry Pi 與 Android Things 一起使用,則可以使用標(biāo)準(zhǔn)的帶狀電纜攝像頭,使用 Android 的攝像頭 API,無需太多麻煩。
更多細(xì)節(jié)
雖然這個(gè)項(xiàng)目有很多事情要做,但可以在附加的源項(xiàng)目中找到更多詳細(xì)信息。如上所述,一旦您生成了 TensorFlow 圖,您應(yīng)該能夠下載源代碼并將圖文件替換為您嘗試檢測的任何內(nèi)容。對(duì)于 Firebase 支持,您還需要?jiǎng)?chuàng)建自己的免費(fèi)Firebase 項(xiàng)目并將憑據(jù)復(fù)制到項(xiàng)目中。
- 圣誕節(jié)運(yùn)動(dòng)探測器開源項(xiàng)目
- 圣誕老人探測器開源分享
- 野生動(dòng)物驅(qū)蟲劑傳感器開源硬件
- 煙霧和氣體探測器開源項(xiàng)目
- Lane Tech HS PCL RAGE探測器開源分享
- WAiT:野生動(dòng)物追蹤器
- 激光雷達(dá)入侵探測器開源分享
- 瀕臨滅絕鳥類探測器開源分享
- Xiraffe桅桿上的智能野生動(dòng)物觀測站
- 脈沖微處理器金屬探測器開源設(shè)計(jì)
- 555定時(shí)器構(gòu)成的野生動(dòng)物驅(qū)避傳感器
- BT智能手機(jī)探測器開源項(xiàng)目
- 智能金屬探測器MOLE開源項(xiàng)目
- 蓋革探測器開源項(xiàng)目
- 基于GPRS的溫度遠(yuǎn)程監(jiān)測系統(tǒng)設(shè)計(jì) 97次下載
- 金屬探測器電路圖 帶Arduino的金屬探測器設(shè)計(jì) 876次閱讀
- 探索紅外熱成像探測器的基礎(chǔ)原理 549次閱讀
- 金屬探測器電路圖分享 5405次閱讀
- 基于零維材料的光電探測器原子結(jié)構(gòu) 982次閱讀
- 氣體探測器怎么接線 3.1w次閱讀
- 紅外線探測器距離_紅外線探測器安裝 1.3w次閱讀
- 金屬探測器怎么用_金屬探測器的使用方法 6.1w次閱讀
- 半導(dǎo)體探測器的工作原理_半導(dǎo)體探測器應(yīng)用領(lǐng)域 1.4w次閱讀
- 閃爍探測器探測原理_閃爍探測器的結(jié)構(gòu)組成 1.7w次閱讀
- 火焰探測器接線圖_火焰探測器設(shè)置要求 4.5w次閱讀
- 火焰探測器保護(hù)半徑_火焰探測器適用場所 1w次閱讀
- 剩余電流探測器原理_剩余電流探測器的應(yīng)用 9588次閱讀
- 如何制作一個(gè)金屬探測器? 5.1w次閱讀
- 火焰探測器工作原理 5.1w次閱讀
- 自制高頻振蕩金屬探測器 1.4w次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
- 1.06 MB | 532次下載 | 免費(fèi)
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費(fèi)
- 3TC358743XBG評(píng)估板參考手冊(cè)
- 1.36 MB | 330次下載 | 免費(fèi)
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費(fèi)
- 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
- 6.40 MB | 227次下載 | 免費(fèi)
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費(fèi)
- 7元宇宙底層硬件系列報(bào)告
- 13.42 MB | 182次下載 | 免費(fèi)
- 8FP5207XR-G1中文應(yīng)用手冊(cè)
- 1.09 MB | 178次下載 | 免費(fèi)
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費(fèi)
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費(fèi)
- 4開關(guān)電源設(shè)計(jì)實(shí)例指南
- 未知 | 21549次下載 | 免費(fèi)
- 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費(fèi)
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費(fèi)
- 7電子制作實(shí)例集錦 下載
- 未知 | 8113次下載 | 免費(fèi)
- 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
- 0.00 MB | 6656次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費(fèi)
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費(fèi)
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費(fèi)
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費(fèi)
- 6電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191187次下載 | 免費(fèi)
- 7十天學(xué)會(huì)AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183279次下載 | 免費(fèi)
- 8proe5.0野火版下載(中文版免費(fèi)下載)
- 未知 | 138040次下載 | 免費(fèi)
評(píng)論
查看更多