Despite perturbations in the transportation network in Canada and the Covid-19 pandemic, a long-awaited package from Seeed Studio arrived on March 18. Surprisingly, it contained a Seeeduino XIAO which was not expected with the other items because it was on pre-order. This post contains my first impressions of the XIAO. Because I don't really have much experience with micro-controllers except for a bit of work with the ESP8266 and the very occasional experiment with Arduino boards, this overview will be at a rather superficial level. Hopefully, it may be of interest to other neophytes. I welcome advice and corrections from those more knowledgeable: click on the link below.
Table of contents
- Meet the Seeeduino XIAO
- Precursors, Competitors and References
- XIAO Input Output Pins
- Arduino IDE
- PlatformIO
- A "Hello World" Sketch or Two
- Digital Input and Output
- Analogue Input and Output
- I²C Bus
- SPI Bus
- Disclaimer and First Impression
- Further Thoughts (Dec. 22 2020)
Meet the Seeeduino XIAO
According to Wikipedia, a xiao is a Chinese flute typically made of bamboo not unlike a recorder except that there is no mouthpiece and the player blows air across a hole in the top of the tube. Paul Battley kindly corrected me: "although there is an instrument called a xiao 箫/簫 I'm pretty sure I read somewhere that [the board] is just named after the word xiao 小 meaning small." That makes sense, because the Seeeduino XIAO is tiny; the image below greatly exaggerates its size.
The XIAO is an inexpensive Arduino type board based on the SAM D21G an ARM-Based micro-controller by Atmel (now Microchip). It is well made, looks robust and has a very clean appearance. Most components are under a metal cover (hidden by a sticker with pin and function labels) with only four exposed LEDs below the USB-C connector. These are labelled P, L, R and T. There are no components on the underside of the board, but a couple of pads are of importance.
The 32-bit SAM D21 was introduced in 2012 as a low power and high performance alternative to the mostly 8 bit devices used for IoT applications at the time. The high performance is relative, the core cannot perform floating point arithmetic in hardware. The same applies to 32 bit integer division and 32 bit integer multiplication with 64 bit results. Nevertheless, the M0+ core is a significant step up from AVR type micro-controllers.
ATTINY85-20MU | ATMEGA328P-MUR | ATSAMD21G18A-MU | |
---|---|---|---|
Core Size (bits) | 8 | 32 | |
Speed (MHz) | 20 | 48 | |
Flash Memory (K bytes) | 8 | 32 | 256 |
RAM (K bytes) | 0.5 | 2 | 32 |
I/O | 6 | 23 | 38 |
ADC (number/bits) | 4/10 | 8/10 | 14/12 |
DAC (number/bits) | 0 | 1/10 | |
Connectivity | IIC, SPI, UART | IIC, SPI, UART, LIN, USB | |
Unit price ($US) | 0.95 | 2.08 | 3.00 |
Prices were obtained from Digikey on March 20, 2020. At just under $5.00 from Seeed Studio, the XIAO looks like a bargain. I very much doubt one could purchase the CPU, an external crystal, a voltage regulator, four LEDs, various capacitors and resistors, metal can and a USB-C connector to make a similar board any cheaper. You could try, the schematic is available.
Precursors, Competitors and References
The Seeeduino XIAO is not the first board based on the SAMD21 microprocessor. The major players in the hobbyist world have numerous boards in production:
- Arduino,
- See the Zero, MKR Zero and MKR 1000.
- Adafruit, and
- See the METRO M0, Feather M0 Basic Proto and the many other Feather devices based on the same processor.
- Sparkfun
- See the Redboard Turbo, SAMD21 Dev Breakout and SAMD21 Mini Breakout.
There are others. Freescale (an offshoot of Motorola but now owned by NXP which is itself an offshoot of Phillips) may have been one of the first to offer boards based on the SAM D21. PjRC and avdweb produce small boards based on the same processor. Even Seeed Studio has at least four other SAM D21 based boards on offer (such as the Seeeduino Lotus Cortex-M0+ and Seeeduino LoRaWAN).
Given the number of boards available, there is good information on the Web about the SAM D21. Adafruit has a tutorial Adafruit Feather M0 Basic Proto, Wanna play with the ARM Cortex M0 chipset? that is useful for XIAO users, particularly the section entitled Adapting Sketches to M0 & M4. The same is true at Sparkfun: RedBoard Turbo Hookup Guide and SAMD21 Mini/Dev Breakout Hookup Guide. The avdweb site also has useful information although it may be a little difficult to find. I use the search facility to find something I remember having seen previously.
The data sheet for the processor can be obtained from Microchip itself. Of course, the XIAO Wiki at Seeed is the main source of information about the XIAO including the images and the pin diagram found in this post.
The original Arduino core for the SAMD21 CPU is available on GitHub, Seeed Studio has a fork with variants for its own boards.
XIAO Input Output Pins
Seeed Studio did have to make some choices in creating such a small board that is nevertheless breadboard friendly. There are 7 pins holes along each of the two long edges which can accommodate standard 0.1" headers. Three pins are used for power (3.3V, 5V and ground), leaving only 11 pins for I/0. However, there are an additional 2 pads on the underside for the serial debug interface, a reset pad to the side of the USB-C socket and 3 of the four LEDs on the other side of the socket are connected to additional I/O lines.
The pin names Ax
, where x
= 0 to 10, are those used in the Arduino IDE, the Dx
names shown on the diagram are not used to identify the I/O pins in the IDE. The addition of those Dx
names is probably to underline the flexibility of the chip. Each I/O pin can be a digital input or output or an analogue input. The table below is another view of the board connections based on the pin identification found in the schematic.
Seeedino XIAO | ||||||
---|---|---|---|---|---|---|
Function | SAMD21 Pin | A/D | SAMD21 Pin | Function | ||
DAC | PA2/EIC/AIN0 | 0 | 5V | |||
PA4/EIC/REF/AIN4/SCOM0PAD0/TC0 | 1 | GND | ||||
PA10/EIC/AIN18/SCOM2PAD2+/TC1 | 2 | 3.3V | ||||
PA11/EIC/AIN18/SCOM2PAD3+/TC1 | 3 | 10 | PA6/EIC/AIN6/SCOM0PAD2/TC1 | MOSI | ||
SDA | PA8/I2C/AIN16/SCOM2PAD0+/TC0 | 4 | 9 | PA5/EIC/AIN5/SCOM0PAD1/TC0 | MISO | |
SCL | PA9/I2C/EIC/AIN17/SCOM2PAD1+/TC0 | 5 | 8 | PA7/EIC/AIN7/SCOM0PAD3/TC1 | SCK | |
TX | PB8/EIC/AIN2/SCOM4PAD0/TC4 | 6 | 7 | PB9/EIC/AIN3/SCOM4PAD1/TC4 | RX |
LEDS | |||
---|---|---|---|
Label | Colour | SAMD21 Pin (Arduino Pin) | Function |
P | Green | - | Power indicator |
T | Blue | PA19/EIC/SCOM1PAD3+/TC3 (11) | UART TX activity |
R | Blue | PA18/EIC/SCOM1PAD2+/TC3 (12) | UART RX activity |
L | Yellow | PA17/I2C/EIC/SCOM1PAD1+/TC2 (13) | Free |
Serial Wire Debug Interface | ||
---|---|---|
SAMD21 Pin | Function | |
PA31/EIC/SCOM1PAD3/TC1 | SWDIO | |
PA30/EIC/SCOM1PAD2/TC1 | SWCLK |
Legend | |
---|---|
Acronym | Meaning |
AIN | AC Analogue Inputs |
EIC | External Interrupt Controller |
REF | External Voltage Reference |
SCOM | Serial Communication |
TC | Timer Counter |
Warning: The Seeeduino XIAO is a 3.3 volts device and applying 5 volts to an input will overload and damage the XIAO. There may be a 5 volt power connection on the board, but DO NOT use it to power say an I²C RTC clock because the latter's data connections would then be at the 5 volt level when in a HIGH state. Look at the absolute maximum ratings of VPIN
in the following table.
Table 41-2. Absolute Maximum Ratings | ||||
---|---|---|---|---|
Symbol | Description | Min. | Max. | Units |
VDD | Power supply voltage | 0 | 3.8 | V |
IVDD | Current into a VDD pin | - | 92 (1) | mA |
IGND | Current out of a GND pin | - | 130 (1) | mA |
VPIN | Pin voltage with respect to GND and VDD | GND-0.6V | VDD+0.6V | V |
Tstorage | Storage temperature | -60 | 150 | °C |
1. | Maximum source current is 46mA and maximum sink current is 65mA per cluster. A cluster is a group of GPIOs as shown in the table below. Also note that each VDD/GND pair is connected to two clusters so current consumption through the pair will be a sum of the clusters source/sink currents. |
Source: Microchip, SAM D21/DA1 Family, Complete Datasheet DS40001882E, p. 1008.
Arduino IDE
Seeeduino XIAO programs can be written and downloaded to the device flash memory in the Arduino IDE. The initial steps to install the needed tools in the IDE are described in the Software section of the wiki. The procedure is the same as that required for non-AVR boards such as the ESP based boards. In short, it is a two-step procedure that needs to be done only once.
- Add
https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
to the list ofAdditional Boards Manager URLs
in the IDE Preferences (File/Preferences
). - Install the latest version of
Seeed SAMD Boards by Seeed Studio
(version 1.7.6 on June 24, 2020) core library in Board Manager (Tools/Board:xxxx/Board Manager...
and enterSeeed SAMD
in the search filter).
To go on to create a sketch, plug a USB-C cable from the desktop to XIAO. The green power LED will light on the device and it will show up on a Linux desktop as ttyACMxxx
. If using Windows it will show up as a COM
port.
In the Arduino IDE, it is even easier to identify the correct port as the image shows (Tools/Port:...
).
The correct board must also be used. This is done by selecting the Seeeduino XIAO
board in the Tools/Board:
menu, as shown above. More details can be found elsewhere on this site, in the Adafruit and Sparkfun tutorial referenced above and in the Seeeduino XIAO wiki.
PlatformIO
PlatformIO now supports the Seeeduino XIAO. Some, including myself, prefer PlatformIO to the Arduino IDE. New users of PlatformIO or those that are curious about that programming environment may want to consult a short post on how to program the XIAO in that environment: "Hello XIAO" in PlatformIO. The information in the rest of this post remains pertinent for users of PlatformIO.
A "Hello World" Sketch or Two
Here is a simple, do nothing, "hello world" sketch which nevertheless taught me a few lessons.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
This is the output displayed in the IDE serial monitor.
The first surprise was the time it took for the serial port to come up. When I first tried a simple 10 or 100 millisecond delay after the Serial.begin()
, which I was systematically using in ESP8266 or Arduino Uno sketches, the serial output in the setup()
section was not displayed in the IDE serial monitor. To be fair, the almost 8 seconds delay in the above case was unusually long. Delays of about 0.7 to 0.8 seconds are typical. Given the variability, it is not a bad idea to suspend the setup
code until the serial port is available as shown in the sketch.
D. J. Park had some interesting comments about that little bit of code. First Serial.begin()
is not needed. I tried commenting it out and the serial monitor did display the output of the sketch at 115200 baud. I assume that is a default rate because it worked even after powering off the Xiao and then powering it back on. Secondly the time measure is "meaningless [because it] includes the time taken by the user to open the terminal application and open the port." D. J. goes on to say that a delay of 1700 ms seemed sufficient on his Windows 10 system.
This is a good spot to add a comment of my own about this delay. While it made sense to wait until a serial connection to the console was established before continuing with the sketches in this post, in practice that is a very bad idea. It was puzzling that the I2C sketches in the following post would not work whenever the XIAO was powered independantly. It finally dawned on me that it was being hung up by the !Serial()
in the setup()
. Consequently this is how I currently do the test.
Note that in this case, it is necessary to initialize the Serial
object otherwise the !Serial()
test may fail.
The second surprise was how clean the serial output is. There is no garbage at boot time which seems inevitable with the ESP8266. Consequently, there is no need for the initial line feeds which I often used in ESP sketches to separate the desired serial output from what precedes.
The third surprise was that the code worked. In the documentation found on the Web I often saw that SerialUSB
would have to be used to send text to the IDE serial monitor. The explanation is found in the last two lines of the variant.h
header file in the .../packages/Seeeduino/hardware/samd/1.7.0/variants/XIAO_m0/
directory:
Had I used SerialUSB
, the sketch would have compiled and worked just as well. By the way, just where the packages
subdirectory is found will depend on the desktop operating system and the type of installation chosen for the Arduino software. I have a portable installation in a custom directory on a Linux system, so the full path to variant.h
is:
/home/michel/ED/arduino-1.8.10/portable/packages/Seeeduino/hardware/samd/1.7.0/variants/XIAO_m0/variant.h
If I insist on that file, it's because it warrants examination. In that file, 17 I/O signals are defined, among which are those 11 that are brought out to pins identified with the A0
to A10
names. If you want to use Dx
pin names, which is the usual nomenclature with ESP8266 based boards, then you could add the following in each sketch or, once, in the variant.h
file.
Or perhaps you might want to mimic the definition of the analogue pins.
This will use up a further 10 bytes. However, the hello_world.ino
sketch "uses 12584 bytes (4%) of program storage space. Maximum is 262144 bytes" so 10 bytes does not seem like much.
Lastly, I observed that it could be difficult to download the sketch a second time. This problem merits a subsection of its own which follows next. The section title promised more than one sketch. Here is the second one.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
The following table was made with output from the sketch and the content of variant.h
.
Seeeduino XIAO I/O Pin Names and Attributes | ||||||
---|---|---|---|---|---|---|
Pin | Digital In/Out | analogue | PWM | |||
Index | Static int | Macro | In | Out | ||
0 | A0, DAC0 | PIN_A0, PIN_DAC0 | ✔ | ✔ | ✔ | ✘ |
1 | A1 | PIN_A1 | ✔ | ✔ | ✘ | ✔ |
2 | A2 | PIN_A2 | ✔ | ✔ | ✘ | ✔ |
3 | A3 | PIN_A3 | ✔ | ✔ | ✘ | ✔ |
4 | A4, SDA | PIN_A4, PIN_WIRE_SDA | ✔ | ✔ | ✘ | ✔ |
5 | A5, SCL | PIN_A5, PIN_WIRE_SCL | ✔ | ✔ | ✘ | ✔ |
6 | A6 | PIN_A6, PIN_SERIAL1_TX | ✔ | ✔ | ✘ | ✔ |
7 | A7 | PIN_A7, PIN_SERIAL1_RX | ✔ | ✔ | ✘ | ✔ |
8 | A8, SCK | PIN_A8, PIN_SPI_SCK | ✔ | ✔ | ✘ | ✔ |
9 | A9, MISO | PIN_A9, PIN_SPI_MISO | ✔ | ✔ | ✘ | ✔ |
10 | A10, MOSI | PIN_A10, PIN_SPI_MOSI | ✔ | ✔ | ✘ | ✔ |
11 | PIN_LED3, PIN_LED_TXL | ✔ | ✘ | ✘ | ✔ | |
12 | PIN_LED2, PIN_LED_RXL | ✔ | ✘ | ✘ | ✔ | |
13 | PIN_LED_13, PIN_LED, LED_BUILTIN | ✔ | ✘ | ✘ | ✔ | |
14 | PIN_USB_HOST_ENABLE | ✔ | ✘ | ✘ | ✘ | |
15 | PIN_USB_DM | ✔ | ✘ | ✘ | ✘ | |
16 | PIN_USB_DP | ✔ | ✘ | ✘ | ✘ |
Like characters in a Russian novel, some pins have five names!
You may want to install the arduino ZeroRegs library and run its example sketch which "... prints the [configuration] registers for the Arduino Zero (and similar boards)" including the XIAO. I can't say that I can make much sense of the output, but it's something that could be useful later when I learn more about the SAM D21.
Uploading/Bootloader/COM Port/Reset Problem
There is an entry, Reset, in the Seeeduino XIAO wiki on the subject with a short video showing how to reset the board by shorting the two pads labelled RST
beside the USB connector. I must admit that I do not quite understand the accompanying explanation. This inability to upload a sketch or to reset the board seems to be a common problem which shows up in the forum more than once ( XIAO Boot issue, Serial Monitor with XIAO not working, and An error occurred when uploading sketch to seeeduino lorawan board via arduino ide). Most often, the same answer is provided: the board must be reset twice when it hangs in this fashion. Lady Ada says as much in Bootloader Launching. The problem is further discussed in a question on the
Feather HELP! page:
UNO-type Arduinos have a separate serial port chip (aka "FTDI chip" or "Prolific PL2303" etc etc) which handles all serial port capability separately than the main chip. This way if the main chip fails, you can always use the COM port.
M0 and 32u4-based Arduinos do not have a seperate chip, instead the main processor performs this task for you. It allows for a lower cost, higher power setup...but requires a little more effort since you will need to 'kick' into the bootloader manually once in a while.The avdweb site also contains a discussion of the problem, Arduino Zero com port detection and upload problems which a similar explanation of its source. Unfortunately none of the proposed solution seems to work for me. With experience I have learned to wait long enough after a failed attempt at uploading a sketch before trying again. If I am patient enough, it usually works on the second try. The yellow LED seems to be a good indicator. If it is quickly blinking, then the device is busy ant the upload will not work. The LED should be either fully on or if it is slowly pulsing up and down, wait for a few cycles before attempting to upload. Now I can repeatedly upload a sketch, being patient between retries and only occasionally resorting to hard resets. I think that initially I often did not manage to cleanly "ground" the RST pad twice in quick succession. With experience it seems that I have mastered that.
When the XIAO is in this "bootloader" mode, it shows up as a storage device named Arduino on my system as can be seen below.
Uploading will work. Hardy explorers can consult the definitive source about the USB Flashing Format (UF2).
Digital Input Output
All I/O pins on the XIAO can be used as digital pins, which means pins that should be in either a LOW state or HIGH state when used as inputs or outputs.
Obligatory Blink Sketch
We will begin this discussion with a simple LED flashing sketch with a slight twist as it that blinks all three LEDs on the XIAO that are connected to I/O lines. Note that these I/O connections are active LOW: it is necessary to write a 0 to the pin to turn the corresponding LED on which is contrary to the typical Arduino convention.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
It just is a bit difficult to show on a static page but, trust me, the three LEDs do flash four times quickly in sequence.
D. J. Park wrote "the led pins are controlled as low side switches like open drain and ... the digital pin connected to the led [turns the latter ON when set LOW and OFF when set HIGH]. I think it is worth mentioning in your post since most people will expect HIGH is ON." Fair enough, but users of ESP8266 devices such as the Lolin/Wemos D1 mini and the nodeMCU boards are used to the reverse logic also in place on the XIAO. At least the comments in the script were explicit about that.
Timer Based Blink Sketches
There are two timer based blink sketches in the Arduino IDE example sketches for the Seeeduino XAIO. Try them (File/Examples/
scroll down to Examples for Seeeduino XAIO
and select TimerTC3/ISRBlink
and TimerTCC0/ISRBlink
), they both work. The sketches are almost identical, the only difference is in the timer used. Here they are combined, with the choice of the timer done with a macro directive.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
See the TimerOne & TimerThree Libraries example program from PJRC for an excellent explanation of the use of the volatile type and of the need to disable interrupts in the main loop. Note how the mode of the PIN_LED_TXL
pin is set to INPUT
. Otherwise the blue TX LED will flash at each character written to the serial monitor which distracts from the flashing yellow LED. The output in the IDE serial monitor,
is not very interesting but it does follow the yellow LED on/off pattern. I cannot find information about the TimerTC3
and TimerTCC0
libraries, so I will have to look at the source code and the SAM D21 datasheet if there's a need to use timers in the future.
Pulse Width Modulation
Simple Arduino style pulse width modulation is available on pins A1 to A10 and on the three I/O lines connected to the on-board LEDs. The example Fade.ino
sketch (File/Examples/Basic/Fade
) works, here is a modified version the makes three of the XIAO LEDS fade in and out at different rates.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
See the warning by Lady Ada about the difference between AVR and ARM cortex devices when writing the value 255: analogWrite() PWM range. I have not investigated that topic. Nevertheless the setPwm()
routine implements the recommendation to use digitalWrite()
to obtain a 100% duty cycle.
Digital Input
A normally open push button is used to experiment with digital inputs on the XIAO. The connection could not be simpler: one side of the switch is connected to ground, the other to an I/O pin. In the following sketches digital pin 7 of the XIAO is used, but any of the 11 pins could be used. Here are too very short sketches which ensure that the yellow LED is on when the button is pressed (when digital pin 7 is grounded) and off when the button is released (and when pin 7 is brought to Vcc by the internal resistor).
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
I will make three comments about this sketch.
- Note how the button pin mode is set to
INPUT_PULLUP
which activates the internal pull up resistor as well as setting the I/O pin connected to the button as an input. - The only statement in the
loop()
procedure, sets the pin controlling the yellow LED to the value read from the button input. This works because of the reversed logic of the LED. All the XIAO LEDS are active LOW which means the pin connected to them must be set to 0 to turn on the LED. The logic of the statementdigitalWrite(LED_BUILTIN, digitalRead(BUTTON));
isif (digitalRead(BUTTON) == HIGH) { // If the buttonState is HIGH, the button is release so turn the LED off: digitalWrite(LED_BUILTIN, HIGH); } else { // If the buttonState is LOW, the button is pressed so turn LED on: digitalWrite(LED_BUILTIN, LOW); - The state of the button is continuously polled in this sketch, and the LED pin is continuously updated.
It is not difficult to write to the LED pin only when necessary.
It is possible to forego all this polling busy work by using an interrupt.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
As D.J. Park reminded me, the digitalPinToInterrupt()
macro is defined twice.
- In
.../packages/Seeeduino/hardware/samd/1.7.2/cores/arduino/Arduino.h
(line 136) as
#define digitalPinToInterrupt(P) ( P )
. - In
.../packages/Seeeduino/hardware/samd/1.7.2/variants/XIAO_m0/variant.h
(line 54) as
#define digitalPinToInterrupt(P) ((g_APinDescription[P].ulExtInt)
.
D. J. added that he "commented [out] that line in variant.h
file so that there will be no warning." He motivates that choice as follows: "Arduino.h
is included first and it includes variant.h
. The macro in the variant.h
is defined first, and the same macro in Arduino.h
is defined again. The macro defined later takes effect, so #define digitalPinToInterrupt(P) ( P )
is used."
Being the paranoid type, I decided to investigate before changing variant.h
. I looked at all the variant.h
files of the SAM D21 devices noting two things: the compliance value and the presence or not of a digitalPinToInterrupt(p)
macro in the file.
Board | ARDUINO_SAMD_VARIANT_COMPLIANCE | variant.h |
---|---|---|
arduino_zero | 10606 | <none> |
femto_m0 | 10610 | #define digitalPinToInterrupt(P) (g_APinDescription[P].ulExtInt) |
grove_ui_wireless | 10610 | <none> |
wio_terminal | 10610 | <none> |
XIAO_mo | 10610 | #define digitalPinToInterrupt(P) (g_APinDescription[P].ulExtInt) |
zero_radio | 10606 | <none> |
Then I looked at the macro in the Arduino.h
file and the attachInterrupt()
code in WInterrupts.c
located in the same directory.
Clearly D. J. was correct to remove the macro from the variant file. Had that macro ever been invoked, the attached interrupt would have been g_APinDescription[g_APinDescription[BUTTON].ulExtInt].ulExtInt;
which would not have been good.
variant.h
no longer contains the offending digitalPinToInterrupt(P)
macro definition. That's confirmation the advice from D. J. was, once again, correct.
One could be tempted to attach the interrupt with the simpler
attachInterrupt(BUTTON, buttonISR, CHANGE);
which would obviously work. The one reason to leave the digitalPinToInterrupt()
macro in place is that other Arduino compatible boards may require such a function because pin and interrupt numbers do not map identically.
All three versions of these sketches work, choose whichever is better for a specific application. My button libraries mdButton and mdButton2 will have to be updated to handle the XIAO. This should be done soon.
Analogue Input and Output
Up to now, I have had basically no experience with analogue input and output because I have mostly worked with ESP8266 based devices, many of which did not even use its single analogue input pin. The SAM D21 is quite different, as almost every I/O pin can be used for digital or analogue input and output. This was a good opportunity to learn some of the details about this aspect of micro-controllers.
Analogue Input Calibration
Pins A1 and A2 to the XIAO are connected to the ground and 3.3 volts pins and the following simple sketch performs continuous analogue reads of both pins.
The analogue inputs of the SAM D21 microprocessor on the Seeeduino XIAO have 12 bit digital analogue converters. That means that the input voltage measured at the pin is translated into one of 2^12 = 4096 possible values. When the input voltage is 0 volts, the value read should be 0, when voltage is equal to Vcc (approximately 3.3 volts) the input value should be 4095. That is not quite what was returned by the sketch.
While the returned value when measuring 0 volts was fine, there was quite a bit of variation in the values returned when measuring Vcc as can be seen with the following histogram established after 741 measurements.
Note how the highest returned value was 4067 which is short of 4095, the theoritical maximum value. Among the example sketches installed in the Arduino IDE along with the SAM D1 board manager there is one named CorrectADCResponse
. I ran it and obtained this output.
I added two lines to the adc_in.ino
sketch. The first, inserted at the beginning of the sketch, added a library.
In the setup()
routine, the following line
was added as instructed. Reading the analogue input lines yielded the expected results with these corrections.
Analogue Measure of Light with an LDR
Here is the simple circuit used to measure the quantity of light built around a light dependant resistor (LDR) and a fixed resistor. The 5K value of the fixed resistor is just an indication, it is not critical. Besides, I do not know the characteristics of the LDR. Any of the 11 I/O pins of the XIAO could be used, I chose A3.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
I took these measures in the late afternoon when the light level in the room was decreasing as the sun was getting closer to the horizon.
Values over 4000 can be obtained by bringing a COB LED quite near the LDR. The measured value can drop quickly to 0, or very near that level, by cupping my hand tightly around the LDR and thus shutting out most of the light.
Analogue Output
There is a single "true analogue" output signal on the XIAO which is available on pin A0. The term true analogue was in quotation marks because the signal is obtained through a 10 bit digital to analogue converter (DAC) so that the output voltage can be set to one of 2^10 = 1024 values. The actual voltage is given by the following formula:
DAC output voltage Vout = (DATA/1023)*Vref
where DATA
is any value from 0 to 1023. The reference voltage, Vref
can be one of many values, but by default it is the XIAO input voltage which is nominally 3.3V. Accordingly only discrete voltages can be obtained but the resolution, which by default is 0.003226 volts or 3.226 millivolts, is probably better than I will ever need. Using a Vref
of 1 volt, the step will fall to slightly less than 1 millivolt: 0.9775.
To test this analogue signal, I simply connected A0 to A8 but any other analogue input from A1 to A10 could be used although it is best to avoid A1. Here is a simple sketch that simply ramps the output analogue signal up and down in a linear fashion and reads the pin output. In essence it produces a triangular wave with code rather similar to the sketch using PWM to pulse the intensity of LEDs.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
The loop()
function pumps out lines of output and input measures along with two reference values to the serial port.
The serial output of the sketch can be viewed in the IDE serial plotter (Tools/Serial Plotter
).
The graph could be surprising on first look, but remember this plot is not a direct measure of the output and input voltages. The triangular blue wave shows the numeric data written to the DAC to specify the output voltage on pin 0. The red wave (or higher amplitude wave, for colour-blind readers) shows the numeric data read from the ADC on pin 8 as it converts the output voltage read on pin A1. The ADC has a 12 bit resolution, so it divides the 0 to 3.3 voltage range into 4096 steps. Writing 64 to the output DAC will result in an output voltage of 0.2064 (=3.3*64/1023). The ADC reads that voltage as 4095*0.2064/3.3 = 256.12, which is 4 times 64 (when ignoring rounding and measurement errors). The input voltage is quite close to the output voltage notwithstanding the scale factor. This can be verified by scaling either the DAC or ADC measure. When SCALE is defined the output value is scaled and the result is the following graph.
It is now obvious that what is read is precisely what is output.
Important Note: when using pin 0 to output the DAC signal, DO NOT set the pin mode to OUTPUT
. Here is what happens if pinMode(DAC_PIN, OUTPUT);
statement is included the setup()
function. (See analogWrite() DAC on A0.)
Remember the red truncated wave is the actual voltage on the output pin, the blue wave is the set output voltage which is manifestely not obtained at times. Note that the DAC and ADC measures has been converted to microvolts. The sketch, dac2dac_v.ino
, that produced this plot can be found in the archive that accompanies this post.
I²C Bus
To test the XIAO I²C bus, I connected it to a couple of I²C devices: an 0.96" OLED display and a module with RTC clock (DS3231) and EEPROM ().
XIAO OLED RTC & EEPROM ------- ---- ------------ GND-----GND------GND 3.3V-----VCC------VCC D4(PA8)-----SDA------SDA D5(PA9)-----SCL------SCL
This preliminary is just a scan of the I²C bus to ensure that the connected devices can be found. I did this with the i2c_scanner.ino
sketch that can be easily be found on the Web such as in Thomas Feldmann gist. I changed just a couple of lines in the setup()
function.
This is the output in the IDE serial monitor.
Those are the correct addresses of the three I²C devices. Let's go on to test I²C communications.
Displaying Light Levels on an I²C OLED Display
For a second test a 0,96" OLED display is connected the hardware I²C bus on the XIAO: SDA is pin PA8 (A4) and SCL is pin PA9 (A5). The display is a no name 128 by 64 pixels SSD1306 purchased from China. The rest of the setup has already been seen. It is a voltage divider made with a fixed 5 K ohms resistor and a light dependant resistor (LDR) tied together. That junction is connected to pin PA10 (A3) which is used as an analogue input.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
The sketch uses the U8g2 library by oliver version 2.27.6. That library was installed using the IDE library manager. Note that the default hardware I²C bus and that the SDA
and SCL
signals are not specified.
The variant.h
file contains the pin numbers of the I²C SDA
and SCL
signals. This is a rather large library, but when compilation is complete, the IDE reports that program storage is not dented in an appreciable way.
SPI Bus
Unfortunately, I do not have sensors that use the Serial Peripheral Interface (SPI) communication protocol. I do have a SPI display, but it is currently being used. So the only test I could do quickly was to connect a cheap USB logic analyzer and to look at the output while running the SPI example sketch found in the XIAO Wiki. There was a problem with using the name SS
for the slave select pin so I changed that to CS
. Setting the mode of the chip select pin was also missing.
The sketch is available in the xiao_sketches.zip archive along with all the other sketches presented on this page.
I added serial print statements to see the "Hello world" message as hexadecimal values to make it easier to verify that the message is indeed printed on the SPI bus.
Here is the capture of three pins of the XIAO involved in the transmission of the message on the SPI bus.
At that level it can be seen that 14 characters were transmitted while the CS signal was active (LOW), which is a good omen because that is exactly the number of characters in the message. The first two characters are shown below, but it was necessary to cut out the time lapsed between them because otherwise the image would have been much too wide.
That shows the SPI bus does work as expected.
Disclaimer and First Impressions
As already stated, Seeed Studio did provide the Seeeduino XIAO at a discount for which I am grateful. The company did not impose any restrictions, just asking that I write up a review in return. Furthermore, the amount involved was not sufficient to buy even a small fraction of my soul. Nevertheless, it is only fair that I warn readers before emitting an opinion about this device.
I do not have much experience with micro-controllers of the size of the XIAO. The only comparison I can make is with a Digispark compatible ATTiny85 mini board. The build quality of the XIAO is much better, but then the ATTiny device was obviously a knock off. While both boards can be programmed in the Arduino environment, the experience is quite different. Uploading a sketch to the ATTiny is awkward, while it is rather simpler with the XIAO once used to the procedure. The real and meaningful difference is in the capabilities of the two devices. One feels at ease with a 32-bit CPU with 256K of RAM, while one has to always be cognizant of the limit imposed by 512 bytes of RAM in the case of the ATTiny. I think it will be possible to use the ATTiny85 as a hardware watchdog of my home automation system, but I also believe that it will be possible to do as much and then much more with the XIAO. I am looking forward to completing both projects and presenting the results here.
There are some things that could be improved. Unfortunately, the Seeeduino XIAO is not yet officially supported in the PlatformIO environment. Hopefully that will be changed in the future. Currently, there is a dearth of information specific to the XIAO. It is a new product, so it will take a bit of time before others start using the XIAO and before the more knowledgeable write reports showing us how to do more than blink LEDs as shown above. I agree with Seeed, the XIAO is both tiny and cute, and hopefully it will be a success.
Further Thoughts (Dec. 22 2020)
Looking at this 8 months later, I realized that we remain in the grip of the pandemic. On the other hand, there have been some changes in the of the XIAO. As stated before, it is now directly supported in PlatformIO. Also more information is available. Of course, Seeed Studio is a good source:
- The Seeeduino XIAO Wiki. Asside from the introductory page there are 8 other topics. I highly recommend Seeeduino XIAO Get Started By Nanase as a better introduction to the device than my attempt here.
- Search the Seeed Studio Forum for XIAO.
- Search the The Seeed Studio Blog for XIAO. There's a Seeeduino XIAO Resources Roundup by Elaine Wu. It was published 7 months ago, but it is being updated.
A search of GitHub for "SEEED XIAO" will produce some interesting projects along with chaff. The DroneBot Workshop published a Meet the Seeeduino XIAO blog post along with a YouTube video just yesterday (Dec 1, 2020). The author Bill (William) is a fellow Canadian born in Montréal as I was. Back to the topic, I have a number of additionals posts about the XIAO:
- "Hello XIAO" in PlatformIO
- I²C Light Sensor using a Seeeduino XIAO
- Seeeduino XIAO Serial Communication Interfaces (SERCOM)
- The XAIO as a USB-Serial Converter
and there will probably be an upcoming post on connecting a 2" ILI9225 colour TFT display to the XIAO using hardware SPI. Just got this to work yesterday; there's still a lot to learn about DMA. Maybe I will investigate connecting a second SPI device such as an SD card reader which would be an interesting combination.