Printed Circuit Boards and Android

A Love Story Between Two Engineering Disciplines

by Mario Bodemann

The idea: A digital die

Hardware needed

https://wiki.seeedstudio.com/Seeeduino-XIAO/

🍞 Breadboards 🍞

Perfboards

PCBs

Printed Circuit Boards

https://easyeda.com

Preview in 3D

Good for visual checking

https://jlcpcb.com

Outcome

SMD vs TH

> Through hole components on board, only wiring by printing service (3rd)

👨‍💻 Let's see some code 👩‍💻

Circuit Python

Circuit Python

Hello World for hardware: 💡

Setup Code:

import time
import board
from digitalio import DigitalInOut, Direction

A = DigitalInOut(board.A0)
A.direction = Direction.OUTPUT

Circuit Python

Running forever:

while(True):
  A.value = True
  time.sleep( 0.3 )
  A.value = False
  time.sleep( 0.3 )

Show Blinking

Hello World!

😍 Communication: Talk to a chip 🤖

Serial Console

Python Firmware Setup

boot.py

import usb_cdc
usb_cdc.enable(console=True, data=True)

code.py

Serial communication: Python side

import usb_cdc

# …

line = str(usb_cdc.data.readline(), 'utf-8')

if line == "light on":
  A.value = True
elif line == "light off":
  A.value = False

🐧 Linux calling Circuit Python 🐧

or: how to test the communication?

echo 'light on' > /dev/ttyACM1
echo 'light off' > /dev/ttyACM1

🍎 macOS: different device name 🍎

🗗 Windows: %INSERT_INSTRUCTIONS% 🗗

Android Serial Communication

📈📉🤦🤔🔒😅

USB Device Discovery

val manager : UsbManager =
  context.getSystemService(
    Context.USB_SERVICE
  ) as UsbManager

USB Device Discovery

val xiao : UsbDevice = manager
  .deviceList // actually: It is a map 😸
  .values
  .first { device ->
    device.productName == "Seeeduino XIAO"
    // and more …
  }

Finding the Right™ Device

Connecting to the Device

USB device permissions:

if (!manager.hasPermission(xiao)) {
  // …
}

Connecting to the Device

Create Pending Intent

val intent = PendingIntent.getBroadcast(
    context,
    0,
    Intent(ACTION_USB_PERMISSION),
    PendingIntent.FLAG_IMMUTABLE or
        PendingIntent.FLAG_ONE_SHOT
)

Connecting to the Device

Tie it together:

val filter = IntentFilter(ACTION_USB_PERMISSION)
context.registerReceiver(usbReceiver, filter)

manager.requestPermission(xiao, intent)

Connecting to the Device

With the permission, the device can be opened:

val connection = manager.openDevice(xiao)

Connecting to the Device

The payload (bytes) created:

val bulkData = "light on\n".toByteArray()

Connecting to the Device

And finally sent:

val result = connection.bulkTransfer(
    endpoint, // mind the direction!
    bulkData,
    bulkData.size,
    3_000 // timeout
)

(result == number of bytes send)

All together

val manager : UsbManager =
  context.getSystemService(
    Context.USB_SERVICE
  ) as UsbManager

val xiao : UsbDevice = manager
  .deviceList
  .values
  .first { device ->
    device.productName == "Seeeduino XIAO"
    // and more …
  }
if (!manager.hasPermission(xiao)) {
    val intent = PendingIntent.getBroadcast(
        context,
        0,
        Intent(ACTION_USB_PERMISSION),
        PendingIntent.FLAG_IMMUTABLE or
            PendingIntent.FLAG_ONE_SHOT
    )

    val filter = IntentFilter(ACTION_USB_PERMISSION)
    context.registerReceiver(usbReceiver, filter)

    manager.requestPermission(xiao, intent)
}

All together

else {
    val connection = manager.openDevice(xiao)
    val bulkData = "light on\n".toByteArray()
    val result = connection.bulkTransfer(
         endpoint,
         bulkData,
         bulkData.size,
         3_000 // timeout
     )
}

👨‍💻+⌛+🤔=♥️

💡

Let us watch a video.

🗒️ Notes for Architecture 🏗️

Further Ideas

Thanks to

Mobimeo

♥️ And you ♥️

Come and find me, I might have a PCB for you to get started.

😱🙊

💫

HID

What if I press a button on the chip and it sends keyboard codes to the app?

Python Keyboard Firmware

code.py

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import usb_hid

kbd = Keyboard(usb_hid.devices)
kbd.send(Keycode.A)
# 🌟

Android Keyboard Handling in Activity

Activity.kt

override fun onKeyUp(keyCode: Int, event: KeyEvent)
    : Boolean {
  return if(
    event.device.name == "Seeed Seeeduino XIAO" &&
    event.keyCode == KEYCODE_A) {
    // 🌟
    true
  } else {
    super.onKeyUp(keyCode, event)
  }
}

Result: Clicking Switches influences Android

🧹

Clean PCB communication

👨‍💻 Arduino Code 👩‍💻

The Code

void setup() {
  pinMode(LED_1, OUTPUT);
}

void loop() {
  digitalWrite(LED_1, HIGH);
  delay(300);
  digitalWrite(LED_1, LOW);
  delay(300);
}

Next

🐍

Easy/User mode: Changing python code

🥷 BACKUP AND VISSUALS, PLEASE IGNORE 🥷

1