Raspberry pico W GUI (-O)

The Raspberry Pi Pico W is a microcontroller board that is based on the Raspberry Pi Pico, but with the addition of wireless connectivity features. Specifically, the Pico W includes built-in Wi-Fi and Bluetooth, which allows it to connect to the internet and communicate with other devices wirelessly.

The Pico W is powered by a dual-core Arm Cortex-M0+ processor, which runs at a speed of up to 133 MHz. It also includes 264KB of RAM and 2MB of flash memory, which can be used to store programs and data. Additionally, the board has a variety of input/output (I/O) pins, which can be used to connect to sensors, actuators, and other devices.

The Pico W can be programmed using a variety of programming languages and development environments, including MicroPython and C/C++. This makes it a flexible and versatile platform for a wide range of projects, including Internet of Things (IoT) devices, robotics, and more.

Here is one example how to use Raspberry Pi Pico W with micropython, one senzor connected via I2C and simple GUI on the android device using GUI-O via WiFi.

Upload micropython to r.Pi pico W

To prepare a Raspberry Pi Pico W for MicroPython, you will need to follow these steps:

  1. Download the MicroPython firmware for the Pico W from the official website: https://micropython.org/download/rp2-pico/
  2. Connect your Pico W to your computer using a micro-USB cable.
  3. Put the Pico W into bootloader mode by holding down the BOOTSEL button (located near the micro-USB port) while plugging in the USB cable. The Pico W will appear as a mass storage device on your computer.
  4. Copy the MicroPython firmware file (e.g. “rp2-pico-20210119-v1.14.uf2”) to the Pico W’s mass storage device.
  5. Eject the Pico W’s mass storage device and unplug the USB cable.
  6. Put the Pico W into runtime mode by pressing the RESET button (located near the BOOTSEL button). The Pico W is now ready to run MicroPython.
  7. To interact with the Pico W using MicroPython, you can use a terminal emulator program, such as PuTTY or Minicom, to establish a serial connection with the Pico W over the USB port. Make sure to select the correct serial port and baud rate settings (115200 baud is the default for MicroPython).
  8. Once you have established a serial connection, you can start running MicroPython code on the Pico W! You can use the REPL (Read-Eval-Print Loop) to interactively enter commands, or you can write your code in a text editor and save it to the Pico W as a .py file.

Install python editor Thonny

In order to use Thonny with Raspberry Pi Pico W MicroPython, please follow the steps:

  1. Install Thonny on your computer. You can download it from the Thonny website: https://thonny.org/
  2. Connect your Raspberry Pi Pico W to your computer using a micro-USB cable.
  3. Open Thonny and go to “Tools” > “Options” > “Interpreter”. In the “MicroPython” section, select “Raspberry Pi Pico (with MicroPython)” from the drop-down menu.
  4. Go to “File” > “New” to create a new script. Enter your MicroPython code in the editor.
  5. Connect to the Pico W by clicking the “Connect” button in the Thonny toolbar. If the Pico W is not automatically detected, you may need to select the correct serial port and baud rate manually.
  6. Once you are connected, you can run your code on the Pico W by clicking the “Run” button in the Thonny toolbar. The output will be displayed in the “Shell” pane.

The hardware

In the presented example I will use VEML6075 UV sensor. To connect the sensor to the Raspberry Pi Pico W I2C interface, you will need some breadboard or protoboard. There are several pins suitable for I2C operation:

Pi pico W pinout

We will use pin 16 for SDA ind pin 17 for SCL signal of the I2C interface. Don’t forget to add two pullup resistors from both lines to the 3,3V supply. Finally, connect the supply and I2C from VEML6075 to the board. The reason why I used VEML6075 is because I had some breakout boards left from another weather station project.

Everything connected on protoboard

Python code

Now it’s time to start writing some python code. First, we will check if the sensor is properly connected to I2C. In Thonny shell send following commands:

Scaning the I2C devices with micropython
import machine
i2c = machine.I2C(0,
scl=machine.Pin(17),
sda=machine.Pin(16),
freq=100000)
devices = i2c.scan()
for d in devices:
print(hex(d))

The output should be 0x10, which is the I2C address of the VEML6075.

WiFi

The Raspberry Pi Pico W can be configured as a soft access point using MicroPython. This allows other devices to connect to the Pico W and communicate with it over Wi-Fi. To start the WiFi as access point use following python code:

import network
ssid = 'VEML6075'
password = '12345678'
ap = network.WLAN(network.AP_IF)
ap.config(essid=ssid, password=password)
ap.active(True)
while ap.active() == False:
pass

When AP is activated, phone can connect with WiFi to the Raspberry Pi Pico W.

There will be no internet access.

Warning: the phone will most probably try to connect to the internet using mobile data. In order to avoid that just turn off the mobile data when experimenting with WiFi connections described in this page.

Micropython and WiFi (using sockets)

In MicroPython, the socket module provides an interface to work with sockets, which are endpoints of a two-way communication link between two programs running over a network. Here is a brief overview of how sockets work in MicroPython:

  1. First, you need to import the socket module in your MicroPython program using the following command:
try:
import usocket as socket #importing socket
except:
import socket

Next, you can create a socket object by calling the socket function of the socket module. This function takes two arguments: the address family (e.g. AF_INET for IPv4) and the socket type (e.g. SOCK_STREAM for TCP), binding it to the port 80:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #avoid addr in use error
s.bind(('', 80))
s.listen(5)
conn, addr = s.accept()

Now it’s time to add some GUI.

GUI-O

From the GUI-O web page:


GUI-O lets you quickly create professional graphical user interfaces for controlling any device using ASCII text based commands. All widgets are initialized dynamically by your embedded microcontroller – this feature allows each device to create and use its own GUI.


GUI-O application is designed to help you minimize GUI development costs at any project stage, while boosting your productivity. It also significantly reduces GUI programming complexity due to its ease of use and flexibility.

https://www.gui-o.com/what-is-gui-o

For more details about GUI-O, please refer to the GUI-O Reference Manual. You may also consider buying full licence. It is not expensive and it offers really attractive features.

Finally, it’s time to put everything together in one file. It’s not super clean code, but it is easier to put everything in one single source. It’s free to use it or modify. Please note this page as reference if you find the provided information useful. Thanks!

Here is complete code:

try:
 import usocket as socket        #importing socket
except:
 import socket
import network                   #importing network
import gc

import machine
import time

from machine import Pin

led = Pin("LED", Pin.OUT)


# Soft AP SSID and password -------------------------------------------------------------
ssid = 'VEML6075'                  #Set access point name 
password = '12345678'              #Set your access point password

# Initialize I2C with pins --------------------------------------------------------------
i2c = machine.I2C(0,
                  scl=machine.Pin(17),
                  sda=machine.Pin(16),
                  freq=100000)

# VEML6075 ------------------------------------------------------------------------------
VEML6075_ADDR  = 0x10
VEML6075_ADDR  = 0x10
VEML6075_DEVID = 0x26

REG_CONF        = 0x00  # Configuration register (options below)
REG_UVA         = 0x07  # UVA register
REG_UVD         = 0x08  # Dark current register (NOT DUMMY)
REG_UVB         = 0x09  # UVB register
REG_UVCOMP1     = 0x0A  # Visible compensation register
REG_UVCOMP2     = 0x0B  # IR compensation register
REG_DEVID       = 0x0C  # Device ID register

CONF_IT_50MS    = 0x00  # Integration time = 50ms (default)
CONF_IT_100MS   = 0x10  # Integration time = 100ms
CONF_IT_200MS   = 0x20  # Integration time = 200ms
CONF_IT_400MS   = 0x30  # Integration time = 400ms
CONF_IT_800MS   = 0x40  # Integration time = 800ms
CONF_IT_MASK    = 0x8F  # Mask off other config bits

CONF_HD_NORM    = 0x00  # Normal dynamic seetting (default)
CONF_HD_HIGH    = 0x08  # High dynamic seetting

CONF_TRIG       = 0x04  # Trigger measurement, clears by itself

CONF_AF_OFF     = 0x00  # Active force mode disabled (default)
CONF_AF_ON      = 0x02  # Active force mode enabled (?)

CONF_SD_OFF     = 0x00  # Power up
CONF_SD_ON      = 0x01  # Power down
# --------------------------------------------------------------------------------------

# init the sensor
def VEML6075_init():
    conf_data = bytearray(2)
    conf_data[0] = 0x00
    conf_data[1] = 0
    i2c.writeto_mem(VEML6075_ADDR, REG_CONF, conf_data)
    time.sleep(0.1)

# read values from sensor
def VEML_read_reg():
    deviceUVA = bytearray(2)
    deviceUVB = bytearray(2)
    deviceUVcomp1 = bytearray(2)
    deviceUVcomp2 = bytearray(2)
    
    i2c.readfrom_mem_into(VEML6075_ADDR, REG_UVA, deviceUVA)
    i2c.readfrom_mem_into(VEML6075_ADDR, REG_UVB, deviceUVB)
    i2c.readfrom_mem_into(VEML6075_ADDR, REG_UVCOMP1, deviceUVcomp1)
    i2c.readfrom_mem_into(VEML6075_ADDR, REG_UVCOMP2, deviceUVcomp2)
    
    return deviceUVA[1]*256+deviceUVA[0], deviceUVB[1]*256+deviceUVB[0], deviceUVcomp1[1]*256+deviceUVcomp1[0], deviceUVcomp2[1]*256+deviceUVcomp2[0]



# WiFi stuff ---------------------------------------------------------------------------

# --------------------------------------------------------------------------------------
# Start the Soft AP with provided credentials
def WiFistart():
    gc.collect()
    # Start Soft AP
    ap = network.WLAN(network.AP_IF)
    ap.config(essid=ssid, password=password)
    ap.active(True)                    #activating

    while ap.active() == False:
      pass

    print('Connection is successful')
    print(ap.ifconfig())


def parse_GuiO(msg, con):
    if msg.startswith("@init"):
        print("GUI-O app is requesting INITIALIZATION!")
        con.send("|LB UID:title X:50 Y:5 TXT:\"VEML6075\" FFA:\"font8\" FSZ:3.5\r\n")
        con.send("|BT UID:btread X:50 Y:15 TXT:\"Read Registers\"\r\n")
        con.send("|LB UID:uva X:50 Y:25 TXT:\"UVA\"\r\n")
        con.send("|LB UID:uvb X:50 Y:30 TXT:\"UVB\"\r\n")
        con.send("|LB UID:comp1 X:50 Y:35 TXT:\"Comp1\"\r\n")
        con.send("|LB UID:comp2 X:50 Y:40 TXT:\"Comp2\"\r\n")
        con.send("|BT UID:log1 X:25 Y:55 TXT:\"Write 1\"\r\n")
        con.send("|BT UID:log10 X:75 Y:55 TXT:\"Write 10\"\r\n")
#        con.send("|RTC UID:rtc1 HID:rtc\r\n")
        con.send("|EXTF UID:extf1 FNA:\"veml.txt\" HID:extf DTF:\"yyyy-MM-dd HH:mm:s.z\"\r\n")
        con.send("|TA UID:status X:50 Y:80 W:98 H:39 FSZ:1.5\r\n")
        
    if msg.startswith("@btread"):
        print("GUI-O Read Registers Button pressed")
        uva, uvb, comp1, comp2 = VEML_read_reg()
        con.send("@uva TXT:\"UVA = {0:5d}\"\r\n".format(uva))
        con.send("@uvb TXT:\"UVB = {0:5d}\"\r\n".format(uvb))
        con.send("@comp1 TXT:\"Comp1 = {0:5d}\"\r\n".format(comp1))
        con.send("@comp2 TXT:\"Comp2 = {0:5d}\"\r\n".format(comp2))

    if msg.startswith("@log1"):
        print("GUI-O Log 1 Button pressed")
        uva, uvb, comp1, comp2 = VEML_read_reg()
        
        con.send("@extf1 FAC:0\r\n")
        con.send("@status TXT:\"A={0:5d}, B={1:5d}, C1={2:5d}, C2={3:5d}\"\r\n".format(uva, uvb, comp1, comp2))
        con.send("@extf1 FAC:1 FP:\"{0:5d},{1:5d},{2:5d},{3:5d}\"\r\n".format(uva, uvb, comp1, comp2))         
        con.send("@extf1 FAC:3\r\n")         
        
    if msg.startswith("@log10"):
        print("GUI-O Log 10 Button pressed")

        con.send("@extf1 FAC:0\r\n")         # open file
        for i in range(10):                  # write 10 readings
            uva, uvb, comp1, comp2 = VEML_read_reg()    
            con.send("@extf1 FAC:1 FP:\"{0:5d},{1:5d},{2:5d},{3:5d}\"\r\n".format(uva, uvb, comp1, comp2))
            con.send("@status TXT:\"A={0:5d}, B={1:5d}, C1={2:5d}, C2={3:5d}\"\r\n".format(uva, uvb, comp1, comp2))
            time.sleep(0.2)
            print("Readout {0:2d}/10".format(i+1))
            led.toggle()
        con.send("@extf1 FAC:3\r\n")         # close file



def GuiO_main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #creating socket object
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  #avoid addr in use error
    s.bind(('', 80))
    s.listen(5)
    conn, addr = s.accept()
    print('Got a connection from %s' % str(addr))

    while True:
      request = conn.recv(1024)
      
      if not request:
          conn.close()
          conn, addr = s.accept()
      
      if request:
          led.on()
          print('Content = %s' % str(request))
          parse_GuiO(request, conn)
          led.off()
    #  response = parse_GuiO(request, conn)
    #  conn.send(response)
    #  conn.close()


# --------------------------------------------------------------------------------------
# Let's run the GUI-O
WiFistart()
VEML6075_init()
GuiO_main()

Save the above code in file main.py on your R.pi pico W in order to autorun it after reset. Connect to the access point VEML6075 and start GUI-O application on the phone. In menu select “Connections” and under Connection select “Ethernet” and fill in the device parameters:

Adding new Ethernet connection to the GUI-O

Enable “Autoconnect” if you want to start the connection automatically each time the GUI-O is started.

After the connection is established, the GUI-O will send initialization string and the device will respond with strings to create the GUI. Now you can click on buttons and read the values from the registers.

GUI-O application, connected to the Raspberry Pi Pico W

The two buttons “Write 1” and “Write 10” will write the register readings to the file located on the phone. The default location is

/Android/data/com.guio.guioapp/files/

and the file name is VEML6075.txt

Leave a Reply