--- tags: setup, PYNQ, 創創 --- # 創創PYNQ Setup ## Hardware 使用12V變壓器以及wifi網卡,IO: > PYNQ Z2: AR0 <----> TRIG of HC-SR04 > PYNQ Z2: AR1 <----> ECHO of HC-SR04 > PYNQ Z2: GND <----> GND of HC-SR04 > PYNQ Z2: 5V <----> VCC of HC-SR04 > Connect HDMI out to an Monitor > 如果無誤,開機完成後會閃爍綠燈數次。 ## Connectivity 參考[我寫的](https://hackmd.io/u9v46niKQLq7E50d7Z_zdg)與[官方](https://pynq.readthedocs.io/en/latest/getting_started/pynq_z2_setup.html)的教學資料。 目前插上[usb wifi](https://www.ruten.com.tw/item/show?21822097904925)網卡,重開機(軟體重開機,參考前面兩個連結進到板子的terminal)後會自動連上`SSID=4a0c` `password=10000111`的wifi AP,跑圖片的PC/laptop要連到同一個wifi AP。如果懶得去改pynq的wifi設定,可以直接把手機熱點的SSID跟密碼改成跟上述一樣就好,記得手機熱點設定藥可供搜尋,若連上了,手機熱點*已連線的裝置* 中會有pynq。如果斷線了板子連不上,那就重開機。 ## Python runtime and the script 主要功能的程式已經config成服務,開機後就會自動執行,相關指令: ```bash systemctl status hdmi-hcsr04.service # 查看狀態 systemctl restart hdmi-hcsr04.service systemctl start hdmi-hcsr04.service systemctl stop hdmi-hcsr04.service systemctl enable hdmi-hcsr04.service # 開機自動啟動 systemctl disable hdmi-hcsr04.service # 取消開機自動啟動 systemctl show hdmi-hcsr04.service # 顯示service設定 journalctl -xeu hdmi-hcsr04.service # 查log ``` 服務設定檔路徑: > `/etc/systemd/system/hdmi-hcsr04.service` 修改服務設定檔,要立即生效的話要重新載入系統服務:   `systemctl daemon-reload` py檔路徑: > `/home/xilinx/jupyter_notebooks/StupidMirror/Distance_Detection_http_get_3_picture/hdmi_hcsr04_service.py` 修改py檔,需要重啟服務:   `systemctl restart hdmi-hcsr04.service` ## Code Setup 在`/home/xilinx/jupyter_notebooks/StupidMirror/Distance_Detection_http_get_3_picture/hdmi_hcsr04_service.py`中,修改以下幾個變數以符合要求 ```python=1 DISTANCE_THRES = 50 # if the distance if under this, LED_NEXT_PAGE toggles. unit: cm DISTANCE_READ_WINDOW = 0.2 # sleep for how long after DISTANCE_THRES detected IMAGE_UPDATE = 15 # seconds to GET images from url IMAGE_TIMEOUT = 0.7 # seconds timeout for one requests urls=['http://192.168.43.209:8000/mainpage/mainpage.jpg', 'http://192.168.43.209:8000/history/history.jpg', 'http://192.168.43.209:8000/detect/detect.jpg'] ``` 看到綠燈閃爍數次代表程式已經開始運行,如果第一次下載圖片失敗,程式將自動重啟,綠燈會再次閃爍。 如果要手動重啟程式,撥動SW0程式就會停止運作,systemctl會自動把他重啟。 如果發現HDMI out輸出畫面有偏移或是色偏,代表該程式被強制停止或是有exception沒處理到,需要重開機。 ```shell sudo shutdown ``` ## Indicator Lights 1. 程式重啟初始化完成會閃爍綠燈數次,若此時http server未開啟,程式將重啟,綠燈再次閃爍。 2. 下載(抓取)圖片時,`LD0`會亮(或暗)(狀態反向啦乾) 3. 抓取圖片時`LD1`會閃爍黃燈 ## Code backup - /home/xilinx/jupyter_notebooks/StupidMirror/Distance_Detection_http_get_3_picture/hdmi_hcsr04_service.py ```python= # Using Arduino IO pins on PYNQ Z2 to interact with HC-SR04 # PYNQ Z2: AR0 <----> TRIG of HC-SR04 # PYNQ Z2: AR1 <----> ECHO of HC-SR04 # Connect HDMI out to an Monitor SW_OFF_DETECT = 0 # which switch(SW0 or SW1) to toggle to exit this program LED_NEXT_PAGE = 0 # toggle which led(LD0~3) when gesture detected. LED_DOWNLOAD = 1 # turn on which led(LD0~3) to indicating if downloading DISTANCE_THRES = 50 # if the distance if under this, LED_NEXT_PAGE toggles. unit: cmd DISTANCE_READ_WINDOW = 0.2 # sleep for how long after IMAGE_UPDATE = 15 # seconds to GET images from url IMAGE_TIMEOUT = 0.7 # seconds timeout for one requests urls=['http://192.168.43.238:8000/mainpage/mainpage.jpg', 'http://192.168.43.238:8000/history/history.jpg', 'http://192.168.43.238:8000/detect/detect.jpg'] #'http://192.168.137.1:8000/RGB_test.png'] """urls=['http://192.168.43.209:8000/IMG_2900.JPG', 'http://192.168.43.209:8000/IMG_3043.JPG', 'http://192.168.43.209:8000/IMG_4127.JPG', 'http://192.168.43.209:8000/BGR_test.jpg'] #'http://192.168.137.1:8000/RGB_test.png']""" print("[INFO]Importing libraries...", end='\r') from pynq.overlays.base import BaseOverlay from pynq.lib.video import * from pynq.lib.arduino import Arduino_DevMode from pynq.lib.arduino import ARDUINO_SWCFG_DIOALL from pynq.lib.arduino import ARDUINO_DIO_BASEADDR from pynq.lib.arduino import ARDUINO_DIO_TRI_OFFSET from pynq.lib.arduino import ARDUINO_DIO_DATA_OFFSET from pynq.lib.arduino import ARDUINO_CFG_DIO_ALLINPUT from pynq.lib.arduino import ARDUINO_CFG_DIO_ALLOUTPUT from pynq.lib.arduino import ARDUINO_NUM_ANALOG_PINS from pynq.lib.arduino import ARDUINO_NUM_DIGITAL_PINS from pynq.overlays.base import BaseOverlay from pynq.lib.arduino.arduino_io import Arduino_IO from pynq.lib.arduino.arduino_analog import Arduino_Analog from urllib.request import urlopen import time, sys, cv2 import numpy as np print("[INFO]Libraries imported.", end='\n') print("[INFO]Initializing HDMI Out...", end='\r') from pynq.overlays.base import BaseOverlay from pynq.lib.video import * base = BaseOverlay("base.bit") # monitor configuration: 1920*1080 @ (8 bits)*(BGR)=24, 60Hz Mode = VideoMode(width=1920,height=1080,bits_per_pixel=24,fps=60) hdmi_out = base.video.hdmi_out hdmi_out.stop() hdmi_out.close() hdmi_out.configure(Mode,PIXEL_BGR) # OpenCV default color space is BGR try: hdmi_out.start() except: print("[Error]HDMI Out failed to initialize. ") hdmi_out.close() else: print("[INFO]HDMI out initialized. ") def hdmi_show(hdmi_stream, img): outframe = hdmi_stream.newframe() outframe[:] = img hdmi_stream.writeframe(outframe) def url_to_image(url,timeout): # download the image, convert it to a NumPy array, and then read # it into OpenCV format resp = urlopen(url=url,timeout=timeout) image = np.asarray(bytearray(resp.read()), dtype="uint8") image = cv2.imdecode(image, cv2.IMREAD_COLOR) # return the image return image def get_imgs(urls,timeout): global base base.leds[LED_DOWNLOAD].on() imgs=[] for url in urls: try: img = url_to_image(url=url, timeout=timeout) if img is None: print("[ERROR]Failed to download image from %s" % url) imgs.append(img) #(cv2.cvtColor(img,4)) except: print("[ERROR]Failed to download images with error message:%s" % sys.exc_info()[0]) print("[ERROR]Failed to download image from %s" % url) if imgs is not None and len(imgs) == len(urls): print("[INFO]All images downloaded. ") base.leds[LED_DOWNLOAD].off() return imgs else: print("[ERROR]Given %d urls of images but only %d images accquired." % (len(urls), len(imgs))) base.leds[LED_DOWNLOAD].off() print("[INFO]Initializing HC-SR04 distance reader...", end='\r') PT=Arduino_IO(base.ARDUINO,0,'in') # being careful, set all digital IO as input Arduino_IO.write_cmd(PT,ARDUINO_DIO_BASEADDR + ARDUINO_DIO_TRI_OFFSET, ARDUINO_CFG_DIO_ALLINPUT) """ parameters: pin: int, 0~13 corresponding pin AR0~AR13 on the board value: int/boolean, the output state return: None """ def io_write(pin, value): if pin in range(ARDUINO_NUM_ANALOG_PINS + ARDUINO_NUM_DIGITAL_PINS): if value: cur_val = Arduino_IO.read_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET) new_val = cur_val | (0x1 << pin) Arduino_IO.write_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET, new_val) else: cur_val = Arduino_IO.read_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET) new_val = cur_val & (0xffffffff ^ (0x1 << pin)) Arduino_IO.write_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET, new_val) """ parameters: pin: int, 0~13 corresponding pin AR0~AR13 on the board return: int/boolean, the state read from the pin """ def io_read(pin): if pin in range(ARDUINO_NUM_ANALOG_PINS + ARDUINO_NUM_DIGITAL_PINS): raw_value = Arduino_IO.read_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET) return (raw_value >> pin) & 0x1 """ return: floaot, distance read from HC-SR04 """ def read_distance(): Arduino_IO.write_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET, 0b0000) # io_write(PIN_TRIG,0) time.sleep(0.05) # send trigger signal Arduino_IO.write_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET, 0b0001) # io_write(PIN_TRIG,1) Arduino_IO.write_cmd(PT, ARDUINO_DIO_BASEADDR + ARDUINO_DIO_DATA_OFFSET, 0b0000) # io_write(PIN_TRIG,0) while io_read(PIN_ECHO) == 0: pass start_time = time.time() while io_read(PIN_ECHO) == 1: pass end_time = time.time() return 17150 * (end_time - start_time) # these just tell you where the pins located, changing value of these two var may not change anything PIN_TRIG = 0 # AR0, output PIN_ECHO = 1 # AR1, input # set pin0(labeled AR0 on the board) as output and the rest as input Arduino_IO.write_cmd(PT,ARDUINO_DIO_BASEADDR + ARDUINO_DIO_TRI_OFFSET, 0b1111_1111_1111_1111_1111_1111_1111_1110) rgbleds = [base.rgbleds[i] for i in range(4, 6)] # Toggle board LEDs leaving small LEDs lit for i in range(8): [rgbled.off() for rgbled in rgbleds] time.sleep(.2) [rgbled.on(2) for rgbled in rgbleds] time.sleep(.2) [rgbled.off() for rgbled in rgbleds] print("[INFO]HC-SR04 distance reader initialized. ", end='\n') print("[INFO]Downloading images from urls...") imgs = get_imgs(urls, timeout=IMAGE_TIMEOUT) t_flag = 0 sw_state = base.switches[SW_OFF_DETECT].read() img_index = 0 if imgs is not None: print("[INFO]All images downloaded.") hdmi_show(hdmi_out, imgs[img_index]) else: print("[ERROR]Not even a image accquired. Go check the url, stupid user.") sw_state = not sw_state # this will skip the while block print("[INFO]Toggle SW%d on the board to stop reading." % SW_OFF_DETECT) while base.switches[SW_OFF_DETECT].read() == sw_state: if time.time()-t_flag >= IMAGE_UPDATE: t_flag = time.time() imgs_new = get_imgs(urls=urls,timeout=IMAGE_TIMEOUT) if imgs_new is not None: for i in range(len(imgs_new)): imgs[i] = imgs_new[i] if imgs_new[i] is not None else imgs[i] del imgs_new hdmi_show(hdmi_out, imgs[img_index]) distance = read_distance() print('[INFO]distance: {:.1f}cm '.format(distance), end='\r') if distance<DISTANCE_THRES and distance>0: print('[INFO]Triggered at distance: {:.1f}cm '.format(distance), end='\r') base.leds[LED_NEXT_PAGE].toggle() if img_index == len(imgs)-1: img_index = 0 else: img_index = img_index + 1 if imgs[img_index] is not None: hdmi_show(hdmi_out, imgs[img_index]) else: print('[ERROR]Image No.%d is not available.') time.sleep(DISTANCE_READ_WINDOW) print("[INFO]SW%d toggled, distance measuring stopped." % SW_OFF_DETECT) hdmi_out.stop() hdmi_out.close() del hdmi_out ``` - /etc/systemd/system/hdmi-hcsr04.service ```service= [Unit] Description=HDMI out + HCSR04 distance reader After=boot_leds.service Conflicts=boot_leds.service [Service] Type=simple ExecStart=/usr/bin/python3 /home//xilinx/jupyter_notebooks/StupidMirror/Distance_Detection_http_get_3_picture/hdmi_hcsr04_service.py Restart=always [Install] WantedBy=multi-user.target ```