element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Community Hub
Community Hub
Member Blogs SAMD21 Mini Modules
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Leaderboard
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Community Hub requires membership for participation - click to join
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: ralphjy
  • Date Created: 29 Nov 2020 3:56 AM Date Created
  • Views 1694 views
  • Likes 4 likes
  • Comments 3 comments
  • seeed xiao
  • rpc
  • adafruit qt py
Related
Recommended

SAMD21 Mini Modules

ralphjy
ralphjy
29 Nov 2020

I recently came across same small footprint SAMD21 boards that I've found to be very useful for tinkering.   I've used the SAMD21 processors with a number of Arduino boards (Nano 33 IoT, MKR WAN 1300, MKR WiFi 1010) and I've been happy with their capability.  Quite a step up from the AVR parts.  What impressed me with these new boards is their small size and low cost.  Almost as cheap as buying the SAMD21 chip by itself.  I've been wanting a small low cost board that I could incorporate into smaller standalone projects that don't require radio communication capability.  Also one that I wouldn't be too concerned about damaging.  Another plus are the castellated pads which allows using it as a component on an expansion board.

 

The first board that I found and have been using is the Seeeduino Xiao https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html?utm_source=blog&utm_med…

Seeeduino XIAO

Microcontroller ATSAMD21G18, 48MHz 32-Bit ARM Cortex M0+  48 pins  6 Sercom  38 IO  14 ADC

USB Type C connector for power and data

Operating Voltage 3.3V

Digital I/O Pins 11

PWM Pins 10

Analog I/O Pins 11

Flash Memory 256KB

SRAM 32KB

Size 23.5mm x 17.5mm

Price $4.90

 

And recently I found that Adafruit had made the QT Py, a variant of the Xiao, that adds some other features but has the same footprint and pinout https://www.adafruit.com/product/4600

Adafruit QT Py

Same size, form-factor, and pin-out as Seeed Xiao

Primary differences

ATSAMD21E18 processor which has a smaller package with only 32 pins so only 4 Sercom  26 IO  10 ADC

Built in RGB NeoPixel LED

PWM Pins 9

Analog I/O Pins 9

I2C port with STEMMA QT plug-n-play connector

Optional SOIC-8 SPI Flash chip on bottom

Reset button for starting your project code over or entering bootloader mode

Price $6.00

 

So, you can see that Adafruit traded off some I/O pins to get space for extra features.  I like the added reset button because the SAMD21 is easy to lock up and with the Xiao you need to short the reset pads to get into bootloader mode.

The NeoPixel is nice but the feature I really like is the ability to add additional flash memory to the bottom of the PCB.  Adafruit has a 2MB Flash chip for $1.25 http://www.adafruit.com/product/4763. I think that they added that capability to be able to run larger CircuitPython programs.

 

Here's a picture of the two boards, the Xiao is on top and the QT Py on the bottom.  You can see that I've added the flash chip on the QT Py.  The Xiao has 4 single LEDs adjacent to the USB-C connector - 1 user, 1 power, 2 for Tx and Rx of the UART.

imageimage

 

Seeed Studio has a couple of handy breakout boards for the Xiao.  I have the Grove shields https://www.seeedstudio.com/Grove-Shield-for-Seeeduino-XIAO-p-4621.html  which are handy for prototyping with sensors and I'll be able to use them with the QT Py too.

 

 

RPC Testing

I've wanted to play around with using external microcontroller capability with machine vision cameras via UART.  I haven't used RPC (Remote Procedure Call) protocol much and I thought that it might be fun to prototype it using a couple of Xiao boards.

 

Here's a quick demo - the Xiaos are mounted on the Grove shields which I use to connect their UARTs and added a pushbutton, an LED and a potentiometer for testing.  The long cables between the boards are the UART connection with the Rx/Tx crossover.  The board on the top is the master, the one on the bottom the slave.  The master has a pushbutton that that controls a green LED on the slave and the slave sends the value from an ADC connected potentiometer to the master which is displayed on its serial monitor.

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

Here's the code for the master and slave.  The code uses the openmvrpc library and is built from openmv example code.

xiao_to_xiao_communication_as_the_controller_device.ino

// Remote Control - As The Controller Device
//
// This script configures your Xiao to remotely control another Xiao.
//

#include <openmvrpc.h>
// The RPC library above provides mutliple classes for controlling an Arduino over
// CAN, I2C, SPI, or Serial (UART).

//initialize and declare variables
const int ledPin = 13; //led attached to this pin
const int buttonPin = 2;     // the number of the pushbutton pin
uint8_t buttonState = LOW; //this variable tracks the state of the button, low if not pressed, high if pressed

// We need to define a scratch buffer for holding messages. The maximum amount of data
// you may pass in any on direction is limited to the size of this buffer.

openmv::rpc_scratch_buffer<256> scratch_buffer; // All RPC objects share this buffer.

///////////////////////////////////////////////////////////////
// Choose the interface you wish to control a Xiao over.
///////////////////////////////////////////////////////////////
// Uncomment the below line to setup your Xiao for controlling over a hardware UART.
//
openmv::rpc_hardware_serial_uart_master interface(115200);

void setup() {
    // initialize the pushbutton pin as an input:
    pinMode(buttonPin, INPUT);
    
    // Startup the RPC interface and a debug channel.
    interface.begin();
    Serial.begin(115200);
}

//////////////////////////////////////////////////////////////
// Call Back Handlers
//////////////////////////////////////////////////////////////

// This example shows reading a Digital I/O pin remotely.
//
void digital_read_example() {
    uint8_t state;
    if (interface.call_no_args(F("digital_read"), &state, sizeof(state))) {
        Serial.print(F("Remote Digital I/O State: "));
        Serial.println(state);
    }
}

// This example shows reading an Analog I/O pin remotely.
//
void analog_read_example() {
    uint16_t state;
    if (interface.call_no_args(F("analog_read"), &state, sizeof(state))) {
        Serial.print(F("Remote Analog I/O State: "));
        Serial.println(state);
    }
}

// This example shows writing a Digital I/O pin remotely.
//
void digital_write_example(uint8_t state) {
    // static uint8_t state = 1;
    if (interface.call(F("digital_write"), &state, sizeof(state))) {
        //state = !state; // flip state for next time
//        Serial.print(F("Local Button State: "));
//        Serial.println(state);
    }
}

// This example shows writing an Analog I/O pin remotely.
//
void analog_write_example() {
    static uint8_t state = 0;
    if (interface.call(F("digital_write"), &state, sizeof(state))) {
        state = state + 1; // counts from 0 to 255 then rolls over
    }
}

void serial_print_example() {
    char *str = "Hello World!";
    interface.call(F("serial_print"), str, strlen(str));
}

void loop() {
  
    // digital_read_example();
    
    analog_read_example();

    buttonState = digitalRead(buttonPin);
    digitalWrite(ledPin, !buttonState);
    digital_write_example(buttonState);

    // analog_write_example();

    serial_print_example();
    
}

 

xiao_to_xiao_communication_as_the_remote_device.ino

// Remote Control - As The Remote Device
//
// This script configures your Xiao to be remotely controlled by another Xiao.
//

#include <openmvrpc.h>
// The RPC library above provides mutliple classes for being cotnrolled over
// CAN, I2C, SPI, or Serial (UART).

const int ledPin =  2; //led attached to this pin

// We need to define a scratch buffer for holding messages. The maximum amount of data
// you may pass in any on direction is limited to the size of this buffer.

openmv::rpc_scratch_buffer<256> scratch_buffer; // All RPC objects share this buffer.

// The interface library executes call backs on this device which have to be registered
// before they can be called. To avoid dyanmic memory allocation we have to create a buffer
// with the maximum number of call backs we plan to support to hold the registrations.
//
// Note that callback registrations only work on the rpc interface that registered them.

openmv::rpc_callback_buffer<8> callback_buffer; // All RPC objects share this buffer.

///////////////////////////////////////////////////////////////
// Choose the interface you wish to be controlled over.
///////////////////////////////////////////////////////////////

// Uncomment the below line to setup for be controlled over a hardware UART.
//
openmv::rpc_hardware_serial_uart_slave interface(115200);

//////////////////////////////////////////////////////////////
// Call Backs
//////////////////////////////////////////////////////////////

size_t digital_read_example(void *out_data) {
    // Get what we want to return into a variable.
    uint8_t state = digitalRead(4);

    // Move that variable into a transmit buffer.
    memcpy(out_data, &state, sizeof(state));

    // Return how much we will send.
    return sizeof(state);
}

size_t analog_read_example(void *out_data) {
    // Get what we want to return into a variable.
    uint16_t state = analogRead(A0);

    // Move that variable into a transmit buffer.
    memcpy(out_data, &state, sizeof(state));

    // Return how much we will send.
    return sizeof(state);
}

void digital_write_example(void *in_data, size_t in_data_len) {
    // Create the primitive or complex data type on the stack.
    uint8_t state;

    // Check that we received the amount of data we expected.
    if (in_data_len != sizeof(state)) return;

    // Copy what we received into our data type container.
    memcpy(&state, in_data, sizeof(state));

//    Serial.print(F("Remote Button State: "));
//    Serial.println(state);
    
    // Use it now.
    digitalWrite(ledPin, state);
//    if (state > 0){
//      digitalWrite(ledPin, HIGH);  //LED off
//    } else {
//      digitalWrite(ledPin, LOW);   //LED on
//    }
}

void analog_write_example(void *in_data, size_t in_data_len) {
    // Create the primitive or complex data type on the stack.
    uint8_t state;

    // Check that we received the amount of data we expected.
    if (in_data_len != sizeof(state)) return;

    // Copy what we received into our data type container.
    memcpy(&state, in_data, sizeof(state));

    // Use it now.
    analogWrite(A1, state);
}

void serial_print_example(void *in_data, size_t in_data_len) {
    // Create the string on the stack (extra byte for the null terminator).
    char buff[in_data_len + 1]; memset(buff, 0, in_data_len + 1);

    // Copy what we received into our data type container.
    memcpy(buff, in_data, in_data_len);

    // Use it now.
    Serial.println(buff);
}

void setup() {

    // initialize the LED pin as an output:
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, HIGH);

    // register callbacks
    interface.register_callback(F("digital_read"), digital_read_example);
    interface.register_callback(F("analog_read"), analog_read_example);
    interface.register_callback(F("digital_write"), digital_write_example);
    interface.register_callback(F("analog_write"), analog_write_example);
    interface.register_callback(F("serial_print"), serial_print_example);
         
    // Startup the RPC interface and a debug channel.
    interface.begin();
    Serial.begin(115200);
}

// Once all call backs have been registered we can start
// processing remote events.

void loop() {
     interface.loop();
}

 

 

I'm looking forward to using the QT Py.  I'll probably try that out with CircuitPython since I've added the extra memory image.

  • Sign in to reply
Parents
  • neilk
    neilk over 4 years ago

    Hi Ralph,

     

    Interesting little board and a very neat demo. Thanks for posting.

     

    Neil

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • neilk
    neilk over 4 years ago

    Hi Ralph,

     

    Interesting little board and a very neat demo. Thanks for posting.

     

    Neil

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube