Network Initialization

The Ethernet interface uses the WIZnet W5500 driver through network.WIZNET5K.

Default SPI and control pins:

Signal

Pin

SPI bus

SPI(2)

CS

PB12

RST

PD9

PWR / enable

PE15

By default, the server tries to use DHCP. If DHCP fails, it falls back to the static IP configuration defined in setup.py.

Default static configuration:

Field

Default value

IP address

10.0.1.109

Subnet mask

255.255.255.0

Gateway

10.0.1.254

DNS

8.8.8.8

The network mode can also be changed from the HTTP network configuration page.


HTTP Server Behavior

The server is a lightweight MicroPython socket server. It listens on port 80, accepts one client connection at a time, handles the request, sends the response, and then closes the client socket.

Supported behavior:

  • GET and POST route registration through server.add_route().

  • Static file serving for JavaScript, CSS, and images.

  • JSON request body handling for configuration and control APIs.

  • HTTP responses with Content-Type, Connection: Close, and optional Content-Length headers.

  • Deferred network reconfiguration through a pending-task queue, so the server can respond to the current request before restarting the socket.

Static paths:

URL prefix

Content type

/js/

text/javascript

/css/

text/css

/img/

image/<extension>


Page Routes

These routes return HTML pages from the template/ directory.

Method

Path

Description

GET

/

Main index page.

GET

/netconfig

Network configuration page.

GET

/io

Digital input/output control page.

GET

/analog_io

Analog input/output page.

GET

/serial

Serial UART page.

GET

/storage

EEPROM storage page.


Network Configuration API

Read current network configuration

GET /netconfig/config

Returns the active Ethernet configuration.

Example response:

{
  "ip_addr": "10.0.1.109",
  "subnet_mask": "255.255.255.0",
  "default_gateway": "10.0.1.254",
  "dns": "8.8.8.8",
  "dhcp": true
}

Change network configuration

POST /netconfig/config
Content-Type: application/json

Use DHCP:

{
  "dhcp": true
}

Use a static IP address:

{
  "dhcp": false,
  "ip": "10.0.1.109",
  "subnet_mask": "255.255.255.0",
  "default_gateway": "10.0.1.254",
  "dns": "8.8.8.8"
}

When static mode is selected, the program validates each IPv4 field before applying the new configuration. A valid IPv4 address must contain four number segments separated by dots, and each segment must be between 0 and 255.

Example success response:

{
  "redirect": true
}

Note

The redirect behavior depends on the selected network mode.
Static IP mode: The webpage automatically redirects to the IP address you entered.
DHCP mode: The IP address is assigned by the network, so you need to open the URL shown in the REPL console manually.

Example validation error response:

{
  "error": true,
  "error_message": "Ensure address are all in ipv4. (x.x.x.x)"
}

After a successful change, the server schedules the network reinitialization as a pending task. This allows the HTTP response to be sent before the old socket is closed and recreated.


Digital I/O API

The program supports eight digital inputs and eight digital outputs.

Type

Names

Digital inputs

IN1 to IN8

Digital outputs

RY1 to RY8

Open digital I/O page

GET /io

Returns the digital I/O control page.

Set digital output

POST /io
Content-Type: application/json

Example request:

{
  "pin": "RY1",
  "value": 1
}

Example response:

{
  "value": 1
}

Read all digital I/O states

GET /io/state

Example response:

{
  "output": [
    ["RY1", 1],
    ["RY2", 0]
  ],
  "input": [
    ["IN1", 0],
    ["IN2", 1]
  ]
}

The actual response contains all eight outputs and all eight inputs.

Read digital inputs only

GET /din

Example response:

{
  "IN1": 0,
  "IN2": 1,
  "IN3": 0,
  "IN4": 0,
  "IN5": 0,
  "IN6": 0,
  "IN7": 0,
  "IN8": 0
}

Analog I/O API

The program supports four analog inputs and two analog outputs.

Type

Names

Analog inputs

AI0 to AI3

Analog outputs

AO0 to AO1

Analog input mode mapping:

Input

Mode

Returned unit

AI0

Current mode

mA

AI1

Current mode

mA

AI2

Voltage mode

V

AI3

Voltage mode

V

Open analog I/O page

GET /analog_io

Returns the analog I/O page.

Read all analog input states

GET /analog_io/state

Example response:

{
  "AI0": {
    "value": 12.3,
    "mode": 1
  },
  "AI1": {
    "value": 11.8,
    "mode": 1
  },
  "AI2": {
    "value": 2.5,
    "mode": 0
  },
  "AI3": {
    "value": 3.1,
    "mode": 0
  }
}

Mode values:

Value

Meaning

0

Voltage mode

1

Current mode

Set analog output voltage

POST /analog_out
Content-Type: application/json

Example request:

{
  "index": 0,
  "voltage": 5.0
}

The program converts the requested voltage into a 12-bit DAC value. The DAC output is calibrated with the measured minimum and maximum voltage values stored in DAC_CONFIG.

Calibration values:

Output

Minimum measured voltage

Maximum measured voltage

AO0

0.024 V

9.89 V

AO1

0.079 V

9.88 V

Values outside the supported range are clamped to the DAC range.


Serial UART API

The program exposes UART communication through the HTTP interface. The UART is initialized as UART(3), and its default settings come from UART_CONFIGS in config.py.

Default UART setting fallback values:

Field

Fallback value

Baudrate

9600

Data bits

8

Parity

None

Stop bits

1

Open serial page

GET /serial

Returns the serial communication page.

Note

You can test the UART section with our WIZnet Serial Debugging Tool.

Send UART message

POST /serial
Content-Type: application/json

Example request:

{
  "message": "hello"
}

The message is encoded as UTF-8 and written to UART3.

Receive UART message

GET /serial/recv

Example response when data is available:

{
  "message": "OK"
}

Example response when no data is available:

{
  "message": null
}

The receive function reads all currently available UART bytes and decodes them as UTF-8. Invalid bytes are replaced during decoding.


EEPROM Storage API

The board checks for an EEPROM device on the I2C bus during startup. The I2C bus is created with software I2C on PB6 and PB7.

Signal

Pin

SCL

PB6

SDA

PB7

The EEPROM is considered connected when the scan result contains addresses from 0x50 to 0x57.

EEPROM limits:

Operation

Maximum size

Write

1000 bytes

Read

1000 bytes

Open storage page

GET /storage

Returns the EEPROM storage page.

Write data to EEPROM

POST /storage/write
Content-Type: text/plain

Example body:

hello from WIZ-RTU

The program writes the received body to EEPROM starting at address index 0. String data is encoded to UTF-8 before writing.

Example response:

Success.

Read data from EEPROM

GET /storage/read

Reads up to 1000 bytes from EEPROM starting at address index 0.

Example response:

hello from WIZ-RTU

Error Handling

Common error behavior:

Situation

Response

Unknown route

404 Not Found

Invalid JSON body

400 Bad Request

Header larger than maximum size

Plain text response: Header too large

Invalid IPv4 field

JSON response with error: true and error_message

Invalid digital output pin

JSON response with error: true

The server closes the client connection after each response.


Example Usage With curl

Read network configuration:

curl http://10.0.1.109/netconfig/config

Set static IP configuration:

curl -X POST http://10.0.1.109/netconfig/config \
  -H "Content-Type: application/json" \
  -d '{"dhcp":false,"ip":"10.0.1.109","subnet_mask":"255.255.255.0","default_gateway":"10.0.1.254","dns":"8.8.8.8"}'

Turn on RY1:

curl -X POST http://10.0.1.109/io \
  -H "Content-Type: application/json" \
  -d '{"pin":"RY1","value":1}'

Read digital I/O state:

curl http://10.0.1.109/io/state

Set AO0 to 5.0 V:

curl -X POST http://10.0.1.109/analog_out \
  -H "Content-Type: application/json" \
  -d '{"index":0,"voltage":5.0}'

Send a UART message:

curl -X POST http://10.0.1.109/serial \
  -H "Content-Type: application/json" \
  -d '{"message":"hello"}'

Read UART data:

curl http://10.0.1.109/serial/recv

Write EEPROM data:

curl -X POST http://10.0.1.109/storage/write \
  -H "Content-Type: text/plain" \
  -d 'hello from WIZ-RTU'

Read EEPROM data:

curl http://10.0.1.109/storage/read