├── .editorconfig ├── .gitignore ├── Assets ├── PuTTY_SSH.png ├── Putty.png ├── RPi3_GPIO.png ├── login.png └── ss_error.png ├── LICENSE ├── README.md ├── README_CN.md └── TFmini_RPi ├── tfmini.py ├── tfmini_23.py └── tfmini_ss.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # all files 5 | [*] 6 | indent_style = tab 7 | indent_size = 4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /Assets/PuTTY_SSH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TFmini/TFmini-RaspberryPi/efbeb7061da8cdee05c9fb1711fdad971b0f822e/Assets/PuTTY_SSH.png -------------------------------------------------------------------------------- /Assets/Putty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TFmini/TFmini-RaspberryPi/efbeb7061da8cdee05c9fb1711fdad971b0f822e/Assets/Putty.png -------------------------------------------------------------------------------- /Assets/RPi3_GPIO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TFmini/TFmini-RaspberryPi/efbeb7061da8cdee05c9fb1711fdad971b0f822e/Assets/RPi3_GPIO.png -------------------------------------------------------------------------------- /Assets/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TFmini/TFmini-RaspberryPi/efbeb7061da8cdee05c9fb1711fdad971b0f822e/Assets/login.png -------------------------------------------------------------------------------- /Assets/ss_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TFmini/TFmini-RaspberryPi/efbeb7061da8cdee05c9fb1711fdad971b0f822e/Assets/ss_error.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 TFmini 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TFmini-RaspberryPi 2 | **Note: also suitable for TFmini Plus** 3 | 4 | The example of using TFmini on Raspberry Pi 3. 中文版参考 [README_CN.md](/README_CN.md). 5 | 6 | Raspberry Pi has serial port, IO port and USB, so there are a lot of way to connect it with TFmini: 7 | 8 | - connection via serial port (RXD0 and TXD0) 9 | - connection via USB-serial adaptor (CP2102, CH341, etc.) 10 | - connection via simulative serial port from IO port (via pigpio, etc.) 11 | 12 | Run console command `ls /dev` , Raspberry Pi 3 has the following identified serial ports (may be different on different devices): 13 | 14 | 15 | Peripherals | Raspberry Pi(/dev/) 16 | ---------|---------- 17 | Hardware serial port | ttyAMA0 18 | Software serial port | ttyS0 19 | Arduino | ttyACM0, ttyACM1... 20 | USB-serial adaptor(CP2102, CH341...) | ttyUSB0, ttyUSB1... 21 | 22 | Raspberry Pi 3 has own hardware serial port (PL011) and software serial port (mini UART). The hardware serial port is connected to bluetooth BT by default, and pins (RXD0 and TXD0) are also closed by default. The configurable hardware serial port is not connected to bluetooth and the pins can be configured to connect to hardware or software serial port. 23 | 24 | **Hardware serial port** has high precision as well as completed configuration, and even could read data from TFmini without verification. **Software serial port** should not skip verification while reading data from TFmini. **Simulative serial port** could have lower precision, so, except verification, it is better to add threshold detection to ensure data's correctness. 25 | 26 | When choosing the programming language, according to [RPi GPIO Code Samples](https://elinux.org/RPi_GPIO_Code_Samples#pigpio_2) , C, C#, Ruby, Python, Java ... all kinds of languages can be used. Here we use Python as example, and any other requirements can be submitted in issues. 27 | 28 | ## Install and Configure Raspbian 29 | This section can be skipped if the RaspberrtPi system has been installed and configured. 30 | 31 | Download operaing system image: [Raspbian](https://www.raspberrypi.org/downloads/raspbian/). We choose RASPBIAN STRETCH WITH DESKTOP and, normally, the download should be completed quickly. What we download is a .zip file, thus decompress it to get the .img file. 32 | 33 | Download [Etcher](https://etcher.io/). It is used to burn the operating system image to SD/TF card and is the offical document [INSTALLING OPERATING SYSTEM IMAGES](https://www.raspberrypi.org/documentation/installation/installing-images/README.md)'s recommanded burning method. We use a Class 10, 32GB TF card, connect the card to PC via card reader, open Etcher, choose the .img file decompressed at the step above and then choose the TF card, finally start burning. The burning should take several minutes and we connect the TF card to Raspberry Pi after it is done. 34 | 35 | Connect the Raspberry Pi to monitor, mouse and keyboard. Power up and then enter operating system. 36 | 37 | It is recommanded to close bluetooth by click the bluetooth icon in taskbar. 38 | 39 | Connect Raspberry Pi to a WiFi network, open the console and enter: 40 | 41 | ``` 42 | sudo raspi-config 43 | ``` 44 | 45 | Choose 5. Interfacing-Options -> P2 SSH -> Yes, to enable SSH. 46 | 47 | Choose 5. Interfacing-Options -> P3 VNC -> Yes, to enable VNC, so that we can use remote graphic interface. 48 | 49 | Choose 5. Interfacing-Options -> P6 Serial -> Yes, to enable serial port. 50 | 51 | Then we can connect our PC to Raspberry Pi 3 via SSH, VNC or serial port. We choose SSH as example, so we should keep the Raspberry Pi within the WiFi range and get Raspberry Pi's IP address. 52 | 53 | Log in to router(it should have a default IP address), or use [Angry IP Scanner](http://angryip.org/download/), to search Raspberry Pi's IP address. It should be at the range of 192.168.1.1~192.168.1.255 by default. Mine is 192.168.1.231. 54 | 55 | Open [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/), use SSH connection, enter IP address and port 22, press open. It will prompt that PuTTY Security Alert at the first time, choose Yes. Username is pi, and password is raspberry by default: 56 | 57 | ![login](/Assets/login.png) 58 | 59 | Update first: 60 | 61 | ``` 62 | sudo apt-get update && sudo apt-get upgrade -y 63 | sudo rpi-update 64 | sudo reboot 65 | ``` 66 | 67 | Reconnect to the Raspberry Pi via SSH after reboot (IP address may change). 68 | 69 | If connect PC to Raspberry Pi via serial port, following information may be printed on the console: 70 | 71 | ``` 72 | Raspbian GNU/Linux 9 raspberrypi ttyS0 73 | raspberrypi login: 74 | ``` 75 | 76 | It indicate that the serial port is used to output console information. It is not what we intend to (console is linked to serial0 by default, baud rate 115200), we want to use it connect to peripheral device, so it is need to disable console: 77 | 78 | ``` 79 | sudo nano /boot/cmdline.txt 80 | 81 | dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait 82 | 83 | sudo reboot 84 | ``` 85 | 86 | For Raspberry Pi 3, although the serial port is freed, but it is an unreliable mini UART. PL011 hardware serial port is a better choose, so let us check the mapping: 87 | 88 | ``` 89 | ls -l /dev 90 | #serial0 -> ttyS0 91 | #serial1 -> ttyAMA0 92 | ``` 93 | 94 | Change the mapping: 95 | 96 | ``` 97 | sudo nano /boot/config.txt 98 | ``` 99 | 100 | Add a line: 101 | 102 | ``` 103 | dtoverlay=pi3-miniuart-bt 104 | ``` 105 | 106 | Reboot: 107 | 108 | ``` 109 | sudo reboot 110 | ``` 111 | 112 | Check the mapping again: 113 | 114 | ``` 115 | ls -l /dev 116 | #serial0 -> ttyAMA0 117 | #serial1 -> ttyS0 118 | ``` 119 | 120 | In brief, we close the console linked to serial port, and then map the hardware serial port to TXD0, RXD0. Now we can use serial port via /dev/ttyAMA0. 121 | 122 | Raspberry Pi is connected to PC via WiFi in the same LAN. We use SSH command for connection, VNC for graphic interface, Filezilla for files transmission (sftp://[Raspberry Pi's IP address], username is pi, password is raspberry). If we configure Samba well, we can edit the code on Raspberry Pi as editing local files on PC, and VS Code is a very convenient editor. You can search for more information if you are intereted in, we won't introduce them here due to limited space (and time). 123 | 124 | 125 | ## Connect TFmini to Raspberry Pi's Serial Port 126 | 127 | Let's check Raspberry Pi's GPIO first: 128 | 129 | ![Rpi3_GPIO](/Assets/RPi3_GPIO.png) 130 | 131 | Connection is as follow: 132 | 133 | Raspberry Pi 3 | TFmini 134 | ---------|---------- 135 | +5V | 5V(RED) 136 | GND | GND(BLACK) 137 | TXD0 | RX(WHITE) 138 | RXD0 | TX(GREEN) 139 | 140 | In fact, we don't need to send command to TFmini, we only need to receive data from TFmini, so TXD0 can be vacant or connected to another device. 141 | 142 | tfmini.py code: 143 | 144 | ```Python 145 | # -*- coding: utf-8 -* 146 | import serial 147 | 148 | ser = serial.Serial("/dev/ttyAMA0", 115200) 149 | 150 | def getTFminiData(): 151 | while True: 152 | count = ser.in_waiting 153 | if count > 8: 154 | recv = ser.read(9) 155 | ser.reset_input_buffer() 156 | if recv[0] == 'Y' and recv[1] == 'Y': # 0x59 is 'Y' 157 | low = int(recv[2].encode('hex'), 16) 158 | high = int(recv[3].encode('hex'), 16) 159 | distance = low + high * 256 160 | print(distance) 161 | 162 | 163 | 164 | if __name__ == '__main__': 165 | try: 166 | if ser.is_open == False: 167 | ser.open() 168 | getTFminiData() 169 | except KeyboardInterrupt: # Ctrl+C 170 | if ser != None: 171 | ser.close() 172 | 173 | ``` 174 | 175 | Enter `python tfmini.py` to run and we can see the results. Note that it won't work with python3. 176 | 177 | tfmini_23.py code: 178 | 179 | ```Python 180 | # -*- coding: utf-8 -* 181 | import serial 182 | import time 183 | 184 | ser = serial.Serial("COM12", 115200) 185 | 186 | def getTFminiData(): 187 | while True: 188 | #time.sleep(0.1) 189 | count = ser.in_waiting 190 | if count > 8: 191 | recv = ser.read(9) 192 | ser.reset_input_buffer() 193 | # type(recv), 'str' in python2(recv[0] = 'Y'), 'bytes' in python3(recv[0] = 89) 194 | # type(recv[0]), 'str' in python2, 'int' in python3 195 | 196 | if recv[0] == 0x59 and recv[1] == 0x59: #python3 197 | distance = recv[2] + recv[3] * 256 198 | strength = recv[4] + recv[5] * 256 199 | print('(', distance, ',', strength, ')') 200 | ser.reset_input_buffer() 201 | 202 | if recv[0] == 'Y' and recv[1] == 'Y': #python2 203 | lowD = int(recv[2].encode('hex'), 16) 204 | highD = int(recv[3].encode('hex'), 16) 205 | lowS = int(recv[4].encode('hex'), 16) 206 | highS = int(recv[5].encode('hex'), 16) 207 | distance = lowD + highD * 256 208 | strength = lowS + highS * 256 209 | print(distance, strength) 210 | 211 | # you can also distinguish python2 and python3: 212 | #import sys 213 | #sys.version[0] == '2' #True, python2 214 | #sys.version[0] == '3' #True, python3 215 | 216 | 217 | if __name__ == '__main__': 218 | try: 219 | if ser.is_open == False: 220 | ser.open() 221 | getTFminiData() 222 | except KeyboardInterrupt: # Ctrl+C 223 | if ser != None: 224 | ser.close() 225 | ``` 226 | 227 | This works with python2 and python3. 228 | 229 | ## Connect TFmini to Raspberry Pi's Other IO Ports 230 | 231 | According to the GPIO image of the section above, we connect TX(GREEN) to GPIO23, while RX(WHITE) is not necessary and can be vacant. Using simulative serial port to receive data is not reliable, so we add verification of checksum and threshold filter in the code to avoid data error. 232 | 233 | tfmini_ss.py code: 234 | 235 | ```Python 236 | # -*- coding: utf-8 -* 237 | import pigpio 238 | import time 239 | 240 | RX = 23 241 | 242 | pi = pigpio.pi() 243 | pi.set_mode(RX, pigpio.INPUT) 244 | pi.bb_serial_read_open(RX, 115200) 245 | 246 | def getTFminiData(): 247 | while True: 248 | #print("#############") 249 | time.sleep(0.05) #change the value if needed 250 | (count, recv) = pi.bb_serial_read(RX) 251 | if count > 8: 252 | for i in range(0, count-9): 253 | if recv[i] == 89 and recv[i+1] == 89: # 0x59 is 89 254 | checksum = 0 255 | for j in range(0, 8): 256 | checksum = checksum + recv[i+j] 257 | checksum = checksum % 256 258 | if checksum == recv[i+8]: 259 | distance = recv[i+2] + recv[i+3] * 256 260 | strength = recv[i+4] + recv[i+5] * 256 261 | if distance <= 1200 and strength < 2000: 262 | print(distance, strength) 263 | #else: 264 | # raise ValueError('distance error: %d' % distance) 265 | #i = i + 9 266 | 267 | if __name__ == '__main__': 268 | try: 269 | getTFminiData() 270 | except: 271 | pi.bb_serial_read_close(RX) 272 | pi.stop() 273 | 274 | ``` 275 | 276 | Run: 277 | 278 | ```Shell 279 | # pigpio scripts require that the pigpio daemon be running. 280 | sudo pigpiod 281 | python tfmini_ss.py 282 | ``` 283 | 284 | Although simulative serial port is not reliable, but we have to use this method in some cases. For example, the only serial port of Raspberry Pi could be used to connect to another device except TFmini, so we can use any other IO to connect to TFmini. Moreover, in theory, every IO can be used to connect to TFmini, thus we can connect multiple TFmini to one Raspberry Pi to satisfy some applications' needs. 285 |   286 | Using Raspberry Pi's USB is another way. We can connect multiple TFmini to Raspberry Pi via USB-serial adaptor and USB Hub. 287 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # TFmini-RaspberryPi 2 | TFmini在树莓派3上的例子. English version [README.md](/README.md). 3 | 4 | 树莓派既有引出串口, IO口, 又有USB, 所以可以有很多种方法连接TFmini: 5 | 6 | - 树莓派引出串口(RXD0和TXD0) 7 | - USB转串口(CP2102, CH341...) 8 | - 其他引出IO口模拟串口(通过pigpio等) 9 | 10 | 终端输入 `ls /dev` ,树莓派3串口的识别关系如下(可能有出入?): 11 | 12 | 13 | 外设 | 树莓派(/dev/) 14 | ---------|---------- 15 | 硬件串口 | ttyAMA0 16 | 软件串口 | ttyS0 17 | Arduino | ttyACM0, ttyACM1... 18 | USB转串口(CP2102, CH341...) | ttyUSB0, ttyUSB1... 19 | 20 | 树莓派3自带硬件串口(PL011)和软件串口(mini UART), 硬件串口默认连接蓝牙BT, 引出串口(RXD0和TXD0)默认也是关闭的, 可软件配置硬件串口不和蓝牙相连, 引出串口可配置连接硬件串口还是软件串口. 21 | 22 | **硬件串口**精度高, 配置全, 连接TFmini甚至可能不需要校验. **软件串口**连接TFmini校验不能少. **模拟串口**精度可能更差, 除了校验, 最好加上阈值判定来保证数值正确性. 23 | 24 | 编程语言上, 参考 [RPi GPIO Code Samples](https://elinux.org/RPi_GPIO_Code_Samples#pigpio_2) 来看, C, C#, Ruby, Python, Java...各种语言应该都是可以的. 这里我们选择Python作为例子. 有其他需求可以在issues里面提. 25 | 26 | ## 安装和配置Raspbian 27 | 已经安装和配置好树莓派系统的略过本节. 28 | 29 | 下载树莓派的系统: [Raspbian](https://www.raspberrypi.org/downloads/raspbian/), 这里选的是 RASPBIAN STRETCH WITH DESKTOP, 下载Torrent, 然后用百度云离线下载, 一般会瞬间完成, 然后在开始下载, 非会员的可以用每天的免费加速, 一般很快就可以下完. 下完后是.zip, 解压出里面的.img文件. 30 | 31 | 下载 [Etcher](https://etcher.io/), 用于把上面下载的系统烧录到SD/TF卡, 这是官方文档 [INSTALLING OPERATING SYSTEM IMAGES](https://www.raspberrypi.org/documentation/installation/installing-images/README.md)推荐的烧录方式. 这里选的是Class 10, 32GB的TF卡, 用读卡器连到电脑上, 打开Etcher, 选择上面的 .img文件, 然后选择TF卡, 最后烧录, 几分钟后就完成了, 完成后插到树莓派上即可. 32 | 33 | 新系统坑的一匹, SSH默认关闭, 硬件串口默认连接BT, 调试串口默认关闭?(默认不会通过引出串口输出Linux调试信息?), 不连显示器还真不知道怎么搞了... 34 | 35 | 接上显示器, 鼠标, 键盘. 上电, 进入系统. 36 | 37 | ~~点击上面任务栏的蓝牙图标, 关闭蓝牙.~~ 38 | 39 | 连上WiFi, 打开终端, 输入: 40 | 41 | ``` 42 | sudo raspi-config 43 | ``` 44 | 45 | 选择 5. Interfacing-Options -> P2 SSH -> Yes, 使能SSH. 46 | 47 | 选择 5. Interfacing-Options -> P3 VNC -> Yes, 使能VNC, 这个可以远程图形界面. 48 | 49 | 选择 5. Interfacing-Options -> P6 Serial -> Yes, 使能串口. 50 | 51 | 这样就可以把 借来的读卡器/网线/鼠标/键盘/显示器/HDMI线一大堆东西还回去了. 至于树莓派, 放到小车上, 飞行器上, 办公室/实验室其他地方都是可以的, 只要同一个局域网的WiFi覆盖到就可以. 52 | 53 | 然后我们就可以在电脑上通过 SSH/VNC/串口 的任意一种连接树莓派3了, 这里我们选择SSH, 所以首先要获取树莓派的IP地址. 54 | 55 | 登录路由器(默认192.168.1.1), 或者使用 [Angry IP Scanner](http://angryip.org/download/), 查找 raspberrypi 的IP, 默认应该在 192.168.1.1~192.168.1.255 之间. 我这里是192.168.1.231. 56 | 57 | 打开 [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/), 使用SSH连接, 输入IP, 端口22, open, 第一次会弹出PuTTY Security Alert, 根据提示选择Yes. 用户名 pi, 密码 raspberry: 58 | 59 | ![login](/Assets/login.png) 60 | 61 | 先更新/升级点东西: 62 | 63 | ``` 64 | sudo apt-get update && sudo apt-get upgrade -y 65 | sudo rpi-update 66 | sudo reboot 67 | ``` 68 | 69 | 重启后重新连接SSH(IP地址可能会变). 70 | 71 | 如果连接串口的话, 可能就会看到引出串口打印一些类似下面的信息: 72 | 73 | ``` 74 | Raspbian GNU/Linux 9 raspberrypi ttyS0 75 | raspberrypi login: 76 | ``` 77 | 78 | 表明这个时候的串口用作 console(控制台) 了, 这不是我们想要的(console默认连接的是serial0, 115200), 我们只是想连接外设用, 所以需要disable console: 79 | 80 | ``` 81 | sudo nano /boot/cmdline.txt 82 | 83 | dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait 84 | 85 | sudo reboot 86 | ``` 87 | 88 | 对于树莓派3而言, 虽然串口已经解放出来了, 但使用的是不稳定的mini UART, 我们用 PL011 硬件串口更好, 先看一下映射关系: 89 | 90 | ``` 91 | ls -l /dev 92 | #serial0 -> ttyS0 93 | #serial1 -> ttyAMA0 94 | ``` 95 | 96 | 改变映射关系: 97 | 98 | ``` 99 | sudo nano /boot/config.txt 100 | ``` 101 | 102 | 增加一行: 103 | 104 | ``` 105 | dtoverlay=pi3-miniuart-bt 106 | ``` 107 | 108 | 重启: 109 | 110 | ``` 111 | sudo reboot 112 | ``` 113 | 114 | 看一下映射关系: 115 | 116 | ``` 117 | ls -l /dev 118 | #serial0 -> ttyAMA0 119 | #serial1 -> ttyS0 120 | ``` 121 | 122 | 简言之, 我们关闭了串口的console, 然后把硬件串口映射到TXD0, RXD0. 使用的时候引出串口是 /dev/ttyAMA0. 123 | 124 | 树莓派通过WiFi和PC在同一个局域网中, 连接方式上, 命令行用SSH, 图形界面用VNC, 文件传输可以使用Filezilla(sftp://树莓派IP, 用户名pi, 密码raspberry). 如果我们配置Samba, 在电脑上就可以像编辑本地文件一样编辑树莓派的代码, 用VS Code之类的编辑器就非常方便了, 感兴趣的可以自己搜索, 这里限于篇幅就略了. 125 | 126 | 127 | ## 连接TFmini 到树莓派引出串口 128 | 129 | 先看下树莓派的IO: 130 | 131 | ![Rpi3_GPIO](/Assets/RPi3_GPIO.png) 132 | 133 | 连接关系如下: 134 | 135 | Raspberry Pi 3 | TFmini 136 | ---------|---------- 137 | +5V | 5V(红) 138 | GND | GND(黑) 139 | TXD0 | RX(白) 140 | RXD0 | TX(绿) 141 | 142 | 实际上, 我们这里没有给TFmini发命令, 只用接收TFmini发来的数据即可, 所以, TXD0可以不接或者连接其他外设. 143 | 144 | tfmini.py 文件如下: 145 | 146 | ```Python 147 | # -*- coding: utf-8 -* 148 | import serial 149 | 150 | ser = serial.Serial("/dev/ttyAMA0", 115200) 151 | 152 | def getTFminiData(): 153 | while True: 154 | count = ser.in_waiting 155 | if count > 8: 156 | recv = ser.read(9) 157 | ser.reset_input_buffer() 158 | if recv[0] == 'Y' and recv[1] == 'Y': # 0x59 is 'Y' 159 | low = int(recv[2].encode('hex'), 16) 160 | high = int(recv[3].encode('hex'), 16) 161 | distance = low + high * 256 162 | print(distance) 163 | 164 | 165 | 166 | if __name__ == '__main__': 167 | try: 168 | if ser.is_open == False: 169 | ser.open() 170 | getTFminiData() 171 | except KeyboardInterrupt: # Ctrl+C 172 | if ser != None: 173 | ser.close() 174 | 175 | ``` 176 | 177 | `python tfmini.py` 运行, 即可看到结果, 注意这里用python3不会工作. 178 | 179 | tfmini_23.py文件如下: 180 | 181 | ```Python 182 | # -*- coding: utf-8 -* 183 | import serial 184 | import time 185 | 186 | ser = serial.Serial("COM12", 115200) 187 | 188 | def getTFminiData(): 189 | while True: 190 | #time.sleep(0.1) 191 | count = ser.in_waiting 192 | if count > 8: 193 | recv = ser.read(9) 194 | ser.reset_input_buffer() 195 | # type(recv), 'str' in python2(recv[0] = 'Y'), 'bytes' in python3(recv[0] = 89) 196 | # type(recv[0]), 'str' in python2, 'int' in python3 197 | 198 | if recv[0] == 0x59 and recv[1] == 0x59: #python3 199 | distance = recv[2] + recv[3] * 256 200 | strength = recv[4] + recv[5] * 256 201 | print('(', distance, ',', strength, ')') 202 | ser.reset_input_buffer() 203 | 204 | if recv[0] == 'Y' and recv[1] == 'Y': #python2 205 | lowD = int(recv[2].encode('hex'), 16) 206 | highD = int(recv[3].encode('hex'), 16) 207 | lowS = int(recv[4].encode('hex'), 16) 208 | highS = int(recv[5].encode('hex'), 16) 209 | distance = lowD + highD * 256 210 | strength = lowS + highS * 256 211 | print(distance, strength) 212 | 213 | # you can also distinguish python2 and python3: 214 | #import sys 215 | #sys.version[0] == '2' #True, python2 216 | #sys.version[0] == '3' #True, python3 217 | 218 | 219 | if __name__ == '__main__': 220 | try: 221 | if ser.is_open == False: 222 | ser.open() 223 | getTFminiData() 224 | except KeyboardInterrupt: # Ctrl+C 225 | if ser != None: 226 | ser.close() 227 | ``` 228 | 229 | 这个对于python2和python3都是可以用的. 230 | 231 | ## 连接TFmini 到树莓派其他IO口 232 | 233 | 参考上节中树莓派的IO口图, 我们把 TX(绿) 连到GPIO23上, RX(白)这里没有用上, 可以悬空. 模拟串口数据接收不太稳定, 所以我们代码中加上了校验checksum和阈值筛选, 尽量避免数据错误. 234 | 235 | tfmini_ss.py 代码如下: 236 | 237 | ```Python 238 | # -*- coding: utf-8 -* 239 | import pigpio 240 | import time 241 | 242 | RX = 23 243 | 244 | pi = pigpio.pi() 245 | pi.set_mode(RX, pigpio.INPUT) 246 | pi.bb_serial_read_open(RX, 115200) 247 | 248 | def getTFminiData(): 249 | while True: 250 | #print("#############") 251 | time.sleep(0.05) #change the value if needed 252 | (count, recv) = pi.bb_serial_read(RX) 253 | if count > 8: 254 | for i in range(0, count-9): 255 | if recv[i] == 89 and recv[i+1] == 89: # 0x59 is 89 256 | checksum = 0 257 | for j in range(0, 8): 258 | checksum = checksum + recv[i+j] 259 | checksum = checksum % 256 260 | if checksum == recv[i+8]: 261 | distance = recv[i+2] + recv[i+3] * 256 262 | strength = recv[i+4] + recv[i+5] * 256 263 | if distance <= 1200 and strength < 2000: 264 | print(distance, strength) 265 | #else: 266 | # raise ValueError('distance error: %d' % distance) 267 | #i = i + 9 268 | 269 | if __name__ == '__main__': 270 | try: 271 | getTFminiData() 272 | except: 273 | pi.bb_serial_read_close(RX) 274 | pi.stop() 275 | 276 | ``` 277 | 278 | 运行: 279 | 280 | ```Shell 281 | # pigpio scripts require that the pigpio daemon be running. 282 | sudo pigpiod 283 | python tfmini_ss.py 284 | ``` 285 | 286 | 模拟串口尽管精度较差, 但好处太多, 比如树莓派只有一个引出串口, 可能轮不到连接TFmini, 用模拟串口就可以随意找一个IO连接TFmini的TX, 这样就留出了宝贵的IO口, 而且, 有了模拟串口, 每个IO口都可以连接一个TFmini, 同时连接多个TFmini, 再也不用担心串口不够用的问题.   287 | 288 | 当然树莓派的USB毕竟也不是摆设, 连接多个TFmini也可以用通过USB转串口(CP2102, CH341等)插到USB上去, 再多还有USB Hub可以用. 289 | -------------------------------------------------------------------------------- /TFmini_RPi/tfmini.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import serial 3 | 4 | ser = serial.Serial("/dev/ttyAMA0", 115200) 5 | 6 | def getTFminiData(): 7 | while True: 8 | count = ser.in_waiting 9 | if count > 8: 10 | recv = ser.read(9) 11 | ser.reset_input_buffer() 12 | if recv[0] == 'Y' and recv[1] == 'Y': # 0x59 is 'Y' 13 | low = int(recv[2].encode('hex'), 16) 14 | high = int(recv[3].encode('hex'), 16) 15 | distance = low + high * 256 16 | print(distance) 17 | 18 | 19 | 20 | if __name__ == '__main__': 21 | try: 22 | if ser.is_open == False: 23 | ser.open() 24 | getTFminiData() 25 | except KeyboardInterrupt: # Ctrl+C 26 | if ser != None: 27 | ser.close() 28 | -------------------------------------------------------------------------------- /TFmini_RPi/tfmini_23.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import serial 3 | import time 4 | 5 | ser = serial.Serial("COM12", 115200) 6 | 7 | def getTFminiData(): 8 | while True: 9 | #time.sleep(0.1) 10 | count = ser.in_waiting 11 | if count > 8: 12 | recv = ser.read(9) 13 | ser.reset_input_buffer() 14 | # type(recv), 'str' in python2(recv[0] = 'Y'), 'bytes' in python3(recv[0] = 89) 15 | # type(recv[0]), 'str' in python2, 'int' in python3 16 | 17 | if recv[0] == 0x59 and recv[1] == 0x59: #python3 18 | distance = recv[2] + recv[3] * 256 19 | strength = recv[4] + recv[5] * 256 20 | print('(', distance, ',', strength, ')') 21 | ser.reset_input_buffer() 22 | 23 | if recv[0] == 'Y' and recv[1] == 'Y': #python2 24 | lowD = int(recv[2].encode('hex'), 16) 25 | highD = int(recv[3].encode('hex'), 16) 26 | lowS = int(recv[4].encode('hex'), 16) 27 | highS = int(recv[5].encode('hex'), 16) 28 | distance = lowD + highD * 256 29 | strength = lowS + highS * 256 30 | print(distance, strength) 31 | 32 | 33 | # you can also distinguish python2 and python3: 34 | #import sys 35 | #sys.version[0] == '2' #True, python2 36 | #sys.version[0] == '3' #True, python3 37 | 38 | 39 | if __name__ == '__main__': 40 | try: 41 | if ser.is_open == False: 42 | ser.open() 43 | getTFminiData() 44 | except KeyboardInterrupt: # Ctrl+C 45 | if ser != None: 46 | ser.close() -------------------------------------------------------------------------------- /TFmini_RPi/tfmini_ss.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import pigpio 3 | import time 4 | 5 | RX = 23 6 | 7 | pi = pigpio.pi() 8 | pi.set_mode(RX, pigpio.INPUT) 9 | pi.bb_serial_read_open(RX, 115200) 10 | 11 | def getTFminiData(): 12 | while True: 13 | #print("#############") 14 | time.sleep(0.05) #change the value if needed 15 | (count, recv) = pi.bb_serial_read(RX) 16 | if count > 8: 17 | for i in range(0, count-9): 18 | if recv[i] == 89 and recv[i+1] == 89: # 0x59 is 89 19 | checksum = 0 20 | for j in range(0, 8): 21 | checksum = checksum + recv[i+j] 22 | checksum = checksum % 256 23 | if checksum == recv[i+8]: 24 | distance = recv[i+2] + recv[i+3] * 256 25 | strength = recv[i+4] + recv[i+5] * 256 26 | if distance <= 1200 and strength < 2000: 27 | print(distance, strength) 28 | #else: 29 | # raise ValueError('distance error: %d' % distance) 30 | #i = i + 9 31 | 32 | if __name__ == '__main__': 33 | try: 34 | getTFminiData() 35 | except: 36 | pi.bb_serial_read_close(RX) 37 | pi.stop() 38 | --------------------------------------------------------------------------------