# 嵌入式系統總整與實作 Raspberrypi 4 筆記 ## PIN腳 ![image](https://www.raspberrypi.com/documentation/computers/images/GPIO-Pinout-Diagram-2.png) ![image](https://hackmd.io/_uploads/SyfwfJcQR.png) ## GPIO PIN腳注意事項 1. 輸入信號不要超過3.3V 2. 接LED要再接470$\Omega$電阻 3. 若要供電樹莓派,不要大於5V 4. 若不接電供,3.3V的PIN的輸出電流最大只有500mA,接電供最大可以到1.5A 5. 不要用TTL線傳送程式檔案,因為TTL的buffer不夠大 6. **有控制GPIO的狀態的程式執行要加上```sudo```** ## 同時連接2個以上I2C device > reference: https://medium.com/@mileperuma/enable-multiple-i2c-ports-on-raspberry-pi-5a8807471737 1. 修改```/boot/config.txt```檔案: ``` dtparam=i2c_arm=on #add after this line dtoverlay=i2c-gpio,bus=5,i2c_gpio_sda=12,i2c_gpio_scl=13 ``` 每個設定以空白分隔,設定格式: ```dtoverlay=i2c-gpio,bus=<要以哪個bus與此I2C裝置連接,盡量與其他I2C裝置不同?>,i2c_gpio_sda=<I2C裝置要連接的SDA腳位的「GPIO腳位編號」 (非實體編號!!)>,i2c_gpio_scl=<I2C裝置要連接的SDA腳位的「GPIO腳位編號」 (非實體編號!!)>``` 2. 重新啟動raspi: ```sudo reboot -h now``` 3. 此時下指令: ```sudo i2cdetect -y <bus號碼>```應可看到連接的I2C裝置 4. I2C裝置若以python程式```smbus.SMBus(<bus號碼>)```指定要溝通的bus號碼,則記得要設對 ## HC-SR04超音波測距 ### 規格 ![image](https://hackmd.io/_uploads/H1jKUEeCa.png) ### 接法 ![20240314_161940](https://hackmd.io/_uploads/H1K5QVxRp.jpg) :::warning 因為echo的高電位為5V,而樹莓派最高輸入訊號只能為3.3V,故做分壓 ::: 麵包版範例: ![image](https://hackmd.io/_uploads/H17p7VeCa.png) ### 訊號說明 ![image](https://hackmd.io/_uploads/BJMZLElCT.png) ### 範例程式 [HC-SR04測距](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/main/HC_SR04/HC_SR04.py) ## MPU-9250 九軸 加速度(acc) 陀螺儀(gyro) 磁力計(mag) :::info 由於使用I2C協定,使用前可先[安裝及使用相關工具](https://hackmd.io/k8AGFVaZQfKuNsTwuukuFQ#I2C%E7%9B%B8%E9%97%9C%E5%B7%A5%E5%85%B7) ::: ### 規格 ![image](https://hackmd.io/_uploads/BkIkNSx06.png) ![image](https://hackmd.io/_uploads/SJYXP8lRT.png) **xyz方向:** ![image](https://hackmd.io/_uploads/rkdetLg0T.png) register: ![image](https://hackmd.io/_uploads/BkT8UU_C6.png) ### 接法 (只用到VCC、GND、SCL、SDA (I2C協定)) VCC接3.3V、GND接GND、SCL接GPIO3 (SCL1, I2C)、SDA接GPIO2 (SDA1、I2C) ### 範例程式 [讀取加速度、陀螺儀及磁力計的資料](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/main/MPU9250/read9axis.py) ## HMC5883L 磁力計 :::info 由於使用I2C協定,使用前可先[安裝及使用相關工具](https://hackmd.io/k8AGFVaZQfKuNsTwuukuFQ#I2C%E7%9B%B8%E9%97%9C%E5%B7%A5%E5%85%B7) ::: ### 規格 **xyz方向:** ![image](https://hackmd.io/_uploads/SJIZf9Wy0.png) register: ![image](https://hackmd.io/_uploads/BysjZc-yA.png) ### 接法 (只用到VCC、GND、SCL、SDA (I2C協定)) VCC接3.3V、GND接GND、SCL接GPIO3 (SCL1, I2C)、SDA接GPIO2 (SDA1、I2C) ### 範例程式 [讀取磁力計資料](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/main/HMC5883L/magQ.py) ## PI Camera (相機模組) ### 接法 1. ```sudo poweroff```將樹莓派關機 2. 拉起相機卡隼,插入相機排線,推回卡隼 ### 環境建置及範例程式 #### 1. picamera2 在這裡使用bookwarm版debian作範例,先[下載映象檔](https://hackmd.io/@hQYRchWRTgWcNUvP97mutg/SydHnN-lR#%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1%E7%89%88%E6%9C%AC),並[建置基本樹莓派環境](https://hackmd.io/k8AGFVaZQfKuNsTwuukuFQ#%E7%92%B0%E5%A2%83%E5%BB%BA%E7%BD%AE),再[進一步建置環境](https://hackmd.io/@hQYRchWRTgWcNUvP97mutg/SydHnN-lR#%E3%80%8A%E4%BB%8A%E6%97%A5%E7%92%B0%E5%A2%83%E8%A8%AD%E5%AE%9A%E3%80%8B)及[安裝軟體](https://hackmd.io/@hQYRchWRTgWcNUvP97mutg/SydHnN-lR#%E3%80%8A%E4%BB%8A%E6%97%A5%E5%AE%89%E8%A3%9D%E8%BB%9F%E9%AB%94%E3%80%8B) ##### 範例程式 https://github.com/ktpss97094/EmbeddedSystemsCapstone/tree/bookwarmOS :::danger 1. 需在mdp virtual environment中執行程式 2. OpenCV preview視窗及picamera2 preview視窗需在VNC遠端桌面開啟,否則會error ::: #### 2. raspi指令 1. ```raspistill -n -t 3000 -o test.png -e png -w 640 -h 480```拍照 (3秒後拍照、編碼成png格式、長640x寬480、無預覽) 2. ```raspivid -n -t 500'0 -w 640 -h 480 -o video.h264```錄影 (錄5秒的1080p30影片、長640x寬480、無預覽) ## 麥克風&耳機及Speech相關 ### 環境建置 安裝套件: ``` pip install SpeechRecognition pip install gTTS sudo apt install libasound2-dev sudo apt install python3-pyaudio sudo apt install flac ``` 測試: ``` aplay -l # 列出所有可以播放音訊的裝置 arecord -l # 列出所有可以錄製音訊的裝置 # 錄製音訊 arecord -f cd [-d <秒數>] Filename.wav # 播放音訊 1. aplay Filename.wav # 使用內建播放功能,只能播放wav檔 2. sudo apt-get install sox libsox-fmt-all; play Filename.wav # 使用第三方播放軟體 ``` ### 範例程式 :::info 有使用到[pyAudioAnalysis repository](https://github.com/tyiannak/pyAudioAnalysis) ``` git clone https://github.com/tyiannak/pyAudioAnalysis.git cd pyAudioAnalysis pip install -r ./requirements.txt pip install -e . ``` ::: [播放音訊檔](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/bullseyeOS/Speech/1_playwav.py) [音訊檔案轉文字](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/bullseyeOS/Speech/2.stt_file.py) [麥克風語音轉文字](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/bullseyeOS/Speech/2.stt_microphone.py) :::warning **音訊檔案轉文字 及 麥克風語音轉文字 程式** 若遇到```AttributeError: 'Recognizer' object has no attribute 'recognize_google'```則執行指令```pip install SpeechRecognition --upgrade```即可解決 ::: [文字轉語音檔案 (需連網)](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/bullseyeOS/Speech/3.tts_online.py) [文字轉語音檔案 (不需連網)](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/bullseyeOS/Speech/3.tts_offline.py) ## AI相關 ### 環境建置 安裝套件: ``` sudo apt install python3-opencv pip install imutils pip install dlib ``` ### 範例程式 #### Face & Contour Detection [偵測一張圖片的人臉]() [偵測camera的人臉]() [使用OpenCV套件偵測一張圖片的人臉並用dlib套件繪出輪廓]() [使用dlib套件偵測一張圖片的人臉並繪出輪廓]() #### Object Detection ##### 使用Tensorflow :::info 有使用到[TensorFlow Lite Object Detection on Android and Raspberry Pi repository](https://github.com/EdjeElectronics/TensorFlow-Lite-Object-Detection-on-Android-and-Raspberry-Pi) ``` git clone https://github.com/EdjeElectronics/TensorFlow-Lite-Object-Detection-on-Android-and-Raspberry-Pi.git mv TensorFlow-Lite-Object-Detection-on-Android-and-Raspberry-Pi tflite cd tflite/ bash get_pi_requirements.sh wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip unzip coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip -d Sample_TFLite_model ``` ::: [使用Tensorflow做Object Detection (執行: python TFLite_detection_webcam.py --modeldir=Sample_TFLite_model)]() ##### 使用YOLO :::info 環境建置: ``` wget https://github.com/KumaTea/pytorch-arm/releases/download/v1.8.1/torch-1.8.1-cp39-cp39-linux_armv7l.whl wget https://github.com/KumaTea/pytorch-arm/releases/download/v1.8.1/torchvision-0.9.1-cp39-cp39-linux_armv7l.whl pip install torch-1.8.1-cp39-cp39-linux_armv7l.whl pip install torchvision-0.9.1-cp39-cp39-linux_armv7l.whl pip install ultralytics ``` :::danger :::spoiler error 如果在執行```pip install ultralytics```時遇到error:![2024-05-09_220350](https://hackmd.io/_uploads/BkxmZY89MC.png) 則依照[此網頁說明](https://raspberrypi-guide.github.io/programming/install-opencv)安裝opencv,其中執行```pip install opencv-python==<版本號>```時,版本號選擇前述error訊息中黃框處的版本在[opencv有release的詳細版本號](https://github.com/opencv/opencv-python/releases) ::: ## Cross Compile ### 使用64bit Linux cross compile 32bit Linux kernel module for Raspberry Pi 4 1. 如果是使用未使用的SD卡來做,則先依照[建置基本樹莓派環境](https://hackmd.io/k8AGFVaZQfKuNsTwuukuFQ#%E7%92%B0%E5%A2%83%E5%BB%BA%E7%BD%AE)安裝好OS,之後kernel module會基於此OS安裝在上面 1. ```sh sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev # 安裝dependencies sudo apt install crossbuild-essential-armhf # 安裝32bit的toolchain git clone --depth=1 https://github.com/raspberrypi/linux # 取得32bit Linux的kernel source code cd linux KERNEL=kernel7l # 若要使用在Raspberry Pi 4,要把KERNEL設成「kernel7l」 ``` 2. 使用預設kernel config編譯或是自己設定config + 使用預設kernel config ```sh make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig # 指定使用預設kernel config編譯 ``` + 自己設定config ```sh sudo apt install libncurses5-dev # 安裝dependencies make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig # 指定自己設定config # 進入選項視窗 自己設定config,並存檔離開 ``` 3. ```sh make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs # 編譯 # 編譯完後,arch/arm/boot路徑下即會有一「Image」檔案 ``` :::danger :::spoiler error 若在編譯時遇到Error: ``` arm-linux-gnueabihf-ld: drivers/i2c/busses/i2c-designware-master.o: in function `i2c_dw_probe_master': i2c-designware-master.c:(.text+0x14d8): undefined reference to `__aeabi_uldivmod' arm-linux-gnueabihf-ld: i2c-designware-master.c:(.text+0x14fc): undefined reference to `__aeabi_uldivmod' arm-linux-gnueabihf-ld: i2c-designware-master.c:(.text+0x1528): undefined reference to `__aeabi_uldivmod' arm-linux-gnueabihf-ld: i2c-designware-master.c:(.text+0x1544): undefined reference to `__aeabi_uldivmod' make[2]: *** [scripts/Makefile.vmlinux:37: vmlinux] Error 1 make[1]: *** [/home/ktpss97094/linux/Makefile:1165: vmlinux] Error 2 make: *** [Makefile:234: __sub-make] Error 2 ``` 原因為樹莓派為32bit環境,而```i2c-designware-master.c```程式內使用```/``` (除法operator)做64bit除法。解決方法為把drivers/i2c/busses/i2c-designware-master.c內的clock_calc()函式計算```high_cycles```、```extra_high_cycles```、```extra_low_cycles```、```period```的除法改成用div_u64(被除數, 除數)計算 (已經define好的64bit除法函式) ::: 4. 插入SD卡讀卡機,放入SD卡,掛載SD卡。掛載完後輸入指令```df -h```會看到/dev/sd*1及/dev/sd*2有被掛載 (如下範例,掛載點路徑分別為/media/xd/boot及/media/xd/rootfs **(需記得,在下面步驟會用到)**) ![image](https://hackmd.io/_uploads/BkNC8FnQ0.png) :::info 1. 若使用Virtual Box作為Linux且讀卡機為USB連接,則在裝置 -> USB選單內選擇電腦上插入的讀卡機 (例如: ![image](https://hackmd.io/_uploads/H1Ap53TQR.png) ),此時虛擬機會自動掛載SD卡 2. 若使用Virtual Box作為Linux且**SD卡讀卡機使用電腦內建讀卡機** (例如: 裝置管理員 -> 記憶體技術裝置內有「Realtek PCIE CardReader」 (非使用USB連接)),此時再Virtual Box裝置 -> USB會沒有此裝置! (因為非USB設備) ::: 5. 在SD卡內安裝kernel modules ```sh sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PAH=<rootfs的掛載點路徑> modules_install ``` 6. 複製剛剛編譯好的kernel image及device tree至SD卡 ```sh sudo cp <boot的掛載點路徑>/$KERNEL.img <boot的掛載點路徑>/$KERNEL-backup.img # 備份原本的kernel image sudo cp arch/arm/boot/zImage <boot的掛載點路徑>/$KERNEL.img # 複製剛剛編譯好的kernel image至SD卡 # 複製device tree至SD卡 sudo cp arch/arm/boot/dts/broadcom/*.dtb <boot的掛載點路徑>/ sudo cp arch/arm/boot/dts/overlays/*.dtb* <boot的掛載點路徑>/overlays/ sudo cp arch/arm/boot/dts/overlays/README <boot的掛載點路徑>/overlays/ ``` 7. 編輯boot config並安全移除SD卡的掛載 ```sh 在<boot的掛載點路徑>/config.txt內新增一行: kernel=kernel7l.img # 移除SD卡的掛載 sudo umount /dev/sd*1 sudo umount /dev/sd*2 ``` 8. 將SD卡插入樹莓派並開機即完成 :::info 若要切換回原本的kernel,將上一步在config.txt新增的那行移除即可 ::: :::danger 此kernel module沒有wireless介面,不能使用WiFi ::: ### 使用64bit Linux cross compile C程式至32bit Raspberry Pi 4 1. 在64bit Linux上編譯程式並複製到Raspberry Pi ```sh arm-linux-gnueabihf-gcc hello.c -o hello.arm # 編譯 sudo cp hello.arm /media/xd/rootfs/home/pi/ # 複製 ``` 2. 在Raspberry Pi修改執行權限並執行 ```sh chmod +x hello.arm # 修改執行權限 ./hello.arm # 執行 ``` ## 其他範例程式 [外接LED閃爍](https://github.com/ktpss97094/EmbeddedSystemsCapstone/blob/main/LED/LED.py)