본문 바로가기

파이썬 코드로 IoT 임베디드 보드 제어해 보기 프로젝트, 오늘은 속도를 측정하기 위해서는 기본적으로 라즈베리파이 피코 보드와 W5500 보드가 연결되어 Ethernet 환경을 쓸 준비가 되어 있어야 한다. 

(PC 파이썬과는 약간 제약이 있을 수 있다. Micropython, CircuitPython 키워드로 검색을 해 봐야 합니다. 임베디드 세계에서는 :) )

1. 준비하기

기본적인 하드웨어, 기본 연결, CircuitPython 환경 설정, W5500 기본 드라이버, 동작 확인 등등은 아래 3개의 글을 참고하면 됩니다. :)

 

그래도 간략하게 먼저 CircuitPython 환경 만들기는

간단하게 한글로 가져오면,

 

1. 일단 아래 uf2 파일을 다운로드 한다. 아무곳에서 다운 받아도 된다.

개인 github repo - https://github.com/bjnhur/pico-W5500/blob/main/adafruit-circuitpython-raspberry_pi_pico-en_US-6.2.0.uf2
혹은 진짜 오리지널 파일 from Adafruit CircuitPython 6.2.0 - 
adafruit-circuitpython-raspberry_pi_pico-en_US-6.2.0.uf2

2. 라즈베리파이 피코 보드에 BOOTSEL 을 누른 상태에서 USB을 연결한 다음 버튼을 뗀다.

3. 그러면, 아래 그림처럼 RPI-PR2 라는 드라이버가 잡힐 것이다. 

4. 그럼 아까 받아놓은 uf2 파일을 해당 드라이버로 복사한다. 그러면 자동으로 CircuitPython을 쓸 수 있는 상태가 된다. 아래 그림처럼 자동으로 "CIRCUITPY" 드라이버가 인식됨을 볼 수 있다.

 

하드웨어는 아래처럼,

라즈베리파이 피코 보드와 W5500 이더넷 보드 연결하기

자세한 내용은 아래 3개글을 찬찬히 둘러보세요.

2021.04.19 - [IT/IoT | Hardware] - Raspberry Pi Pico + Ethernet 연결하기 1 - 환경설정 라즈베리파이 피코 W5500

2021.04.19 - [IT/IoT | Hardware] - Raspberry Pi Pico + Ethernet 연결하기 2 - Ping 라즈베리파이 피코 W5500

2021.04.19 - [IT/IoT | Hardware] - Raspberry Pi Pico + Ethernet 연결하기 3 - DHCP 라즈베리파이 피코 W5500

 

Raspberry Pi Pico + Ethernet 연결하기 3 - DHCP 라즈베리파이 피코 W5500

이제 소프트웨어 환경과 간단하게 Ping 테스트가 가능한 IoT 기기 비슷하게 만들어 보았다. 2021.04.19 - [IT/IoT | Hardware] - Raspberry Pi Pico + Ethernet 연결하기 1 - 라즈베리파이 피코 W5500 Raspberry P..

wiznxt.tistory.com

2. 속도 측정 툴 AX1 준비하기

이젠, 간단하게 Loopback 기능을 메인에 넣어서 속도를 측정해 보자.

네트워크 속도 측정 프로그램은 위즈네트에서 제공하는 AX1이라는 툴로 간단하게 해 볼 예정이다.

AX1에 대한 설치 및 사용과 관련된 글은 아래 글을 꼭 참고하세요.

2021.04.27 - [IT/IoT | Hardware] - AX1 - WIZnet 위즈네트 TCP 속도 측정 툴

 

AX1 - WIZnet 위즈네트 TCP 속도 측정 툴

기능이 많이 있지는 않아도 연결해서 데이터 주고 받고, 속도를 측정해서 출력해주는 간단한 기능으로는 쓸 만 한 툴이다. 만든지 오래되어서 OS를 타는 지는 모르겠는데 내 Windows10 에서는 문제

wiznxt.tistory.com

3. WIZNET5K 파이썬 라이브러리 준비하기

아래 링크를 방문해서 lib 폴더를 통째로 복사해서 Raspberry Pi Pico 보드 드라이브로 복사한다.

1단계 글들을 잘 보고 정상적으로 설치가 다 되었다면 CIRCUITPY 라는 드라이브 폴더로 보여질 것이다.

이번 AX1 루프백 테스트를 위한 라이브러리는 반드시 여기 GitHub에 있는 것만을 사용해야 한다.

Adafruit WIZNET5K 라이브러리에 일부 수정을 하고 embed_recv() 라는 함수를 하나 추가해서 사용하고 있다.

 

bjnhur/pico-W5500

Add W5500 Ethernet to Raspberry Pi Pico. Contribute to bjnhur/pico-W5500 development by creating an account on GitHub.

github.com

    def embed_recv(self, bufsize=0, flags=0):  # pylint: disable=too-many-branches
        """Reads some bytes from the connected remote address and then return recv().
        :param int bufsize: Maximum number of bytes to receive.
        :param int flags: ignored, present for compatibility.
        """
        # print("Socket read", bufsize)
        ret = None
        avail = self.available()
        if avail:
            if self._sock_type == SOCK_STREAM:
                self._buffer += _the_interface.socket_read(self.socknum, avail)[1]
            elif self._sock_type == SOCK_DGRAM:
                self._buffer += _the_interface.read_udp(self.socknum, avail)[1]
        gc.collect()
        ret = self._buffer
        # print("RET ptr:", id(ret), id(self._buffer))
        self._buffer = b""
        gc.collect()
        return ret

그냥 recv()함수를 부르고, 사이즈가 큰 파일을 전송하면 메모리 할당 오류가 뜨면서 죽기 때문에 이 함수를 추가해서 사용하고 있다.

수신 버퍼 처리에 약간의 버그가 있는 부분도 수정되어 있다. 수정 부분만을 보고 싶다면 아래 링크를 클릭해 보세요.

github.com/bjnhur/pico-W5500/commit/9465720cb6c3eb08152b556975e7a3135d15b2f8

 

embed_recv() 추가 & wiznet5k 버그 수정, AX1 Loopback 코드 · bjnhur/pico-W5500@9465720

Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files embed_recv() 추가 & wiznet5k 버그 수정, AX1 Loopback 코드 Loading branch information Showing 5 changed files wi

github.com

4. 메인 code.py 작성하기

AX1과 통신하여 속도를 측정하기 위해선,

메인 코드에 데이터를 수신하고, 그 데이터를 바로 전송하는 아주 간단한 코드만 있으면 된다.

주의할 점은 Adafruit WIZNET5K socket 함수의 recv 대신에 위에 추가한 embed_recv()를 사용해야 한다.

코드를 간단하게 살펴보면 아래와 같다. 혹은 GitHub에서 바로 살펴볼 수 있다.

github.com/bjnhur/pico-W5500/blob/main/Pico_W5500_AX1_Loopback.py

 

bjnhur/pico-W5500

Add W5500 Ethernet to Raspberry Pi Pico. Contribute to bjnhur/pico-W5500 development by creating an account on GitHub.

github.com

import board
import busio
import digitalio
import time
from adafruit_wiznet5k.adafruit_wiznet5k import *
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
import neopixel

SPI1_SCK = board.GP10
SPI1_TX = board.GP11
SPI1_RX = board.GP12
SPI1_CSn = board.GP13
W5500_RSTn = board.GP15

print("Wiznet5k AX1 Loopback Test (DHCP)")
# Setup your network configuration below
# random MAC, later should change this value on your vendor ID
MY_MAC = (0x00, 0x01, 0x02, 0x03, 0x04, 0x05)
IP_ADDRESS = (192, 168, 0, 111)
SUBNET_MASK = (255, 255, 0, 0)
GATEWAY_ADDRESS = (192, 168, 0, 1)
DNS_SERVER = (8, 8, 8, 8)

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT

ethernetRst = digitalio.DigitalInOut(W5500_RSTn)
ethernetRst.direction = digitalio.Direction.OUTPUT

# For Adafruit Ethernet FeatherWing
cs = digitalio.DigitalInOut(SPI1_CSn)
# For Particle Ethernet FeatherWing
# cs = digitalio.DigitalInOut(board.D5)

spi_bus = busio.SPI(SPI1_SCK, MOSI=SPI1_TX, MISO=SPI1_RX)

# Reset W5500 first
ethernetRst.value = False
time.sleep(1)
ethernetRst.value = True

# # Initialize ethernet interface without DHCP
# eth = WIZNET5K(spi_bus, cs, is_dhcp=False, mac=MY_MAC, debug=False)
# # Set network configuration
# eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER)

# Initialize ethernet interface with DHCP
eth = WIZNET5K(spi_bus, cs, is_dhcp=True, mac=MY_MAC, debug=False)

print("Chip Version:", eth.chip)
print("MAC Address:", [hex(i) for i in eth.mac_address])
print("My IP address is:", eth.pretty_ip(eth.ip_address))

# Initialize a socket for our server
socket.set_interface(eth)
server = socket.socket()  # Allocate socket for the server
server_ip = None  # IP address of server
server_port = 50007  # Port to listen on
server.bind((server_ip, server_port))  # Bind to IP and Port
server.listen()  # Begin listening for incoming clients
print("server listen")

conn = None

while True:
    if conn is None:
        conn, addr = server.accept()  # Wait for a connection from a client.
        print("socket connected")
        print(conn, addr)
    else :
        if conn.status in (
            SNSR_SOCK_FIN_WAIT,
        ):
            print("socket SNSR_SOCK_FIN_WAIT")
            conn.close()
            conn = None
        elif conn.status in (
            SNSR_SOCK_CLOSE_WAIT,
        ):
            print("socket SNSR_SOCK_CLOSE_WAIT")
            conn.disconnect()
            conn.close()
            conn = None
        else :
            # print("socket established", conn.status)
            avail = conn.available()
            if avail:
                # print("Received size:", avail)
                # data = conn.recv(0)
                data = conn.embed_recv(0)
                if data:
                    # print("DATA ptr", id(data), ",DATA Len: ", len(data))
                    conn.send(data)  # Echo message back to client

메인 코드는 간략하게 보면 아래 5가지 코드 블럭이 있다.

 

  1. DHCP수행
  2. 서버소켓 생성 및 Listen
  3. 연결 확인 및 연결 종료 확인 코드
  4. 데이터 수신 확인
  5. 수신 데이터 전송

코드가 복잡하진 않으니, 세부 분석은 생략해도 될듯 ^^;;;

이제 이 코드를 Raspberry Pi Pico 보드의 code.py 파일로 복사해서 저장하기만 하면 끝!

5. 결과 확인

시리얼 터미널에 출력된 (REPL 윈도우) 결과는 아래와 같이 간단하다. 

AX1과 연결되었다는 메시지를 끝으로 아무런 내용은 없다. ^^;;;

 시리얼 터미널 결과 확인

AX1을 통해 측정한 결과는 아래와 같다. 임베디드 보드니 약 45K 정도 파일을 전송하고 받은 결과이다.

약 400Kbps 정도의 속도가 나오는 것을 확인할 수 있다. (툴이 거짓말을 하는 게 아니길 :) )

PC에서 전송은 금방 해버리고, 루프백 되어서 돌아오는 데이터가 거의 9초 정도 걸리는 것라는 출력 결과를 볼 수 있다.

Raspberry Pi Pico W5500 Ethernet bandwidth

이상 간단하게 라즈베리파이 피코 보드의 Ethernet W5500을 연결한 속도 측정 내용을 알아보았다.

앞서 올려드린 GitHub 코드를 참고해서 파이썬 코드를 가지고 임베디드 보드에 올려 복잡한 응용도 도전해 보시길

 

BJ.

B로그0간

개발 관련 글과 유용한 정보를 공유하는 공간입니다.