IoT Carrier
Introduction
Section titled âIntroductionâ
The ArduinoÂź MKR IoT Carrier is equipped with a lot of different sensors, actuators and also a little display to let your IoT device communicate with the outside world in the easiest way possible. It only works if an Arduino board from the MKR family it attached on its top.
The MKR IoT Carrier comes equipped with:
- RGB LEDs
- Capacitive touch buttons
- Rounded 1.3â TFT display
- Grove connectors
- IMU Accelerometer & Gyroscope
- Humidity & Temperature
- Pressure
- RGB and Gesture
- Relays
- Buzzer
- Battery holder for a 18650 Li-Ion battery
- SD Card slot
Iâll talk about each one of those I/O devices later on this post!
Compatible Boards
Section titled âCompatible BoardsâThe MKR family boards offers different features but share a common pinout so that they can all be easily connected to the MKR IoT Carrier.
Here is a list of the MKR boards:
- MKR WiFi 1010
Basic IoT and pico-network application design - MKR Zero
Made for music makers: provides an SD Card slot and dedicated SPI interfaces - MKR 1000 WiFi
Basic IoT and pico-network application design (just like MKR WiFi 1010) - MKR FOX 1200
Entry point to start working with the European Sigfox networks. - MKR GSM 1400
Build IoT projects connected to GSM / 3G network - MKR NB 1500
Communicates over NB-IoT and LTE-M networks - MKR Vidor 4000
The only board with FPGA chip, camera & HDMI connector - MKR WAN 1300
First LoRaÂź board released by Arduino - MKR WAN 1310
Connects to Arduino LoRaÂź PRO Gateway, existing LoRaWANÂź infrastructure like The Things Network, or even other boards
Mount the Carrier
Section titled âMount the CarrierâThe chosen Arduino MKR board needs to be mounted on top of the MKR IoT Carrier and connected to a computer using a USB cable of type B-mini.
The official image clearly shows the Carrier pinout.

Carrier library
Section titled âCarrier libraryâAll the code snippets used below assume that you include Arduino_MKRIoTCarrier library and instantiate an object of type MKRIoTCarrier.
For these reasons, this sketch could be used as template for all your projects with the Carrier:
// include the library#include <Arduino_MKRIoTCarrier.h>
// instantiate the objectMKRIoTCarrier carrier;
void setup() { // CARRIER_CASE refers to the plastic casing in the kit // and the capacitive buttons on the carrier. // set to 'true' when the plastic casing is used // set to 'false' when not (default). CARRIER_CASE = false;
// initialize the object carrier.begin();
// ...}
void loop() { // ...}Moreover, Arduino_MKRIoTCarrier library includes lots of other libraries to control the I/O devices.
Those libraries are all mentioned in the Quoted Libraries section of this post.
RGB LEDs
Section titled âRGB LEDsâThe Carrier comes with 5 digital RGB LEDs placed on the top side of the carrier in front of the buttons.
The LEDs are controlled with the Adafruitâs DotStar library.
You can control the LEDs with those methods:
// update the new state of the LEDscarrier.leds.show();
// set the color of the index's LEDcarrier.leds.setPixelColor(index, green, red, blue);
// set the overall brightness, from 0 (no brightness) to 255 (maximum brightness)carrier.leds.setBrightness(0-255);
// clear the buffer of the LEDscarrier.leds.clear();
// fill a given amount of the LEDs with the same colorcarrier.leds.fill(color, firstLedToCount, count);
// save a custom coloruint32_t myColor = carrier.leds.Color(green, red, blue);Take a look at RGB-LEDs directory from arduino-projects GitLab repository.
Capacitive touch buttons
Section titled âCapacitive touch buttonsâThe Carrier has five capacitive qTouch buttons on its top, numbered from 00 to 04.
The buttons are sensitive to direct touch and detect wireless touch.
You can control the buttons with those methods:
// replace X with a number from 0 to 4
// reads the state of the pads// put this on the top of 'void loop()' methodcarrier.Buttons.update();
// get if the pad is getting touched// it's value is 'true' until it gets releasedcarrier.Buttons.getTouch(TOUCHX);carrier.ButtonX.getTouch();// i.e. carrier.Buttons.getTouch(TOUCH0);// i.e. carrier.Button0.getTouch();
// get when have been a touch downcarrier.Buttons.onTouchDown(TOUCHX);carrier.ButtonX.onTouchDown();
// get when the button has been releasedcarrier.Buttons.onTouchUp(TOUCHX);carrier.ButtonX.onTouchUp();
// get both, touched and releasedcarrier.Buttons.onTouchChange(TOUCHX);carrier.ButtonX.onTouchChange();Take a look at touch directory from arduino-projects GitLab repository.
Rounded 1.3â TFT display
Section titled âRounded 1.3â TFT displayâThe screen on the Carrier has a 240 x 240 resolution and a diameter of 36 x 40 mm.
The display is controlled through the Adafruit-ST7735-Library.
Every color with the prefix 'ST77XX_' (i.e. 'ST77XX_BLACK') can be used without having to know its hexadecimal value.
Colors available from the library are BLACK, WHITE, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW and ORANGE.
You can configure and control the display with those methods:
// set the display background using hexadecimal codescarrier.display.fillScreen(color);
// set the angle of the screen, 0 is the starting position with no rotation// the screen can only be rotated 90, 180 or 270 degrees by replacing the 0 with 1, 2 or 3carrier.display.setRotation(0);
// print the text inside the string at the current cursor positiondisplay.print("Hello World!");
// display a bitmap visual. 'x' and 'y' are the top left coordinates where the visual is drawn// 'w' and 'h' are the width and height of the visual. The data for the 'bitmap_visual' graphic// can be stored as a byte array and used as the 'bitmap_visual'carrier.display.drawBitmap(x, y, bitmap_visual, w, h, color);
// set the color of the text using hexadecimal codescarrier.display.setTextColor(color);
// set the text sizecarrier.display.setTextSize(number);
// indicate the position, given in pixel, where printing startscarrier.display.setCursor(x, y);Take a look at display directory from arduino-projects GitLab repository.
Grove connectors
Section titled âGrove connectorsâThe Carrier comes with three grove connectors (2 analog and 1 I2C) that enables you to easily connect external sensors.
The type of the connector is labeled clearly on the back of the carrier.
IMU & Gyroscope
Section titled âIMU & GyroscopeâThe LSM6DSOXTR microcontroller from STM is an IMU (Inertial Measurement Unit) that features a 3D digital accelerometer and a 3D digital gyroscope. It also features a machine learning core, which is useful for any motion detection projects, such as free fall, step detector, step counter, pedometer.
The unit is placed underneath the Carrierâs display. It connects to the mounted Arduino MKR board through an I2C interface, and acquires Low power consumption (0.55mA at most).
Accelerometer range is set at ±4 g with a resolution of 0.122 mg.
Gyroscope range is set at ±2000 dps with a resolution of 70 mdps.
Output data rate is fixed at 104 Hz.
You can find some code examples in IMU-accelerometer-and-gyroscope directory from arduino-projects GitLab repository.
Humidity & Temperature
Section titled âHumidity & TemperatureâThe HTS221 Humidity Sensor is mounted on the top side of the carrier under the display, marked with a drop icon.
The sensor uses capacitive sensing with a humidity sensing range of 0-100% and accuracy of ± 3.5% rH (20 to +80% rH), and a temperature sensing range of -40 to 120° C, with an accuracy of ± 0.5 °C, 15 to +40 °C.
The sensor uses a low power consumption (2ÎŒA at 1 Hz sampling rate) and connects to the mounted Arduino MKR board through a I2C interface.
The values from those sensors can be stored in float variables, as shown below:
// get temperature value in Celsiuscarrier.Env.readTemperature();
// get relative humidity (rH) in percentagecarrier.Env.readHumidity();
float temperature = carrier.Env.readTemperature();float humidity = carrier.Env.readHumidity();Pressure
Section titled âPressureâThe LPS22HBTR Pressure Sensor is mounted on the top side of the carrier under the display, marked with a meter icon.
The sensor measures absolute pressure range of 26 to 126 kPa (kilopascal) which is equivalent to 0.25 to 1.24 atm (Atmosphere) and connects to the mounted Arduino MKR board through a I2C interface.
The values from the pressure sensor can be stored in float variables, as shown below:
// returns pressure value in Kilopascal (kPa)float pressure = carrier.Pressure.readPressure();RGB and Gesture
Section titled âRGB and GestureâThe Carrier contains a Broadcom APDS-9660 RGB and Gesture sensors, placed under the display and marked with a bulb icon. It is very useful for ambient light, and RGB color sensing, proximity sensing, gesture detection and even more.
Moreover, it defines the enumerator below to easily control which type of gesture has been performed:
// [around line 80]//Gesture change for APDS9960enum { NONE = -1, DOWN = 3, UP = 2 , LEFT = 1, RIGHT = 0};Take a look at gesture directory from arduino-projects GitLab repository.
Moreover, by using the same sensor, you can also interact with the RGB sensor: its color values can be stored into int variables.
The function below requires 3 or 4 integer variables as arguments where the read color will be stored:
r: the red component of the read color,g: the green component of the read color,b: the blue component of the read color,a: the ambient light intensity.
int r, g, b, a;carrier.Light.readColor(r, g, b, a);Take a look at color-test sketch from gesture directory.
The Carrier has two 5V Coil voltage KEMET EE2-5NU-L relays, located on its back side.
The relays are non-latching with the following contacts:
COM(Common),NO(Normally open),NC(normally closed)
They can take up a max of 2A (Ampere) and 24V (Volt) of input each.
Once the cables are introduced inside the connectors, they will automatically be locked inside. To unlock a cable and remove it from the connector, you need to insert a tool through the top rectangular hole (a flat screwdriver, a hard piece of plastic or something similar). As you can see in the picture below, the wires must be places inside the round holes stroked in blue. While to unlock the wires you need to insert the flat screwdriver inside the red-stroked rectangular holes.

Moreover, the L1 and L2 LEDs on the front of the Carrier are visual indicators of the relaysâ state: if the LED is ON, it means that relayâs COM and NO terminal are connected, while if the LED is OFF it means that COM and NC are connected.
How it works
Section titled âHow it worksâRelay has two groups of pins: low voltage group and high voltage group.
low voltage group are connected to Arduino:
GNDpin is connected toGNDpinVCCpin is connected toVCCpinINpin receives the signal from Arduino through a digital input
high voltage group are connected to a high voltage device:
COMpin (Common),NOpin (Normally open),NCpin (normally closed)
In the following schema, the Arduino Uno controls the DC Motor without having to dealt with the high voltage of the motor. Note that the schema is purely illustrative since when using the Arduino MKR IoT Carrier, you not need to care about the low-voltage group.

The relay works with two modes: normally open mode (NO) and normally closed mode (NC). These modes are the opposite.
To use the Normally Open mode, connect the high voltage device to the COM and NO open just like above.
// control the relays withcarrier.RelayX.open();carrier.RelayX.close();
// reads the status of the relayscarrier.RelayX.getStatus();You need to replace the placeholder X with the numbers 1 or 2.
// swap to the Normally Open (NO) circuit of relay 1 (turns it on)carrier.Relay1.open();
// swap to the Normally Closed (NC) circuit of relay 2 (turns it off), default mode on power offcarrier.Relay2.close();
// boolean variable, returns the status: LOW means NC and HIGH means NObool relayStatus = carrier.Relay2.getStatus();You can find some examples in relays-test from arduino-projects GitLab repository.
The Carrier is equipped with a sound buzzer on the bottom side of it, under the housing of the Arduino MKR board.
There are a couple of methods to control the buzzer:
Equivalent to tone(): it will make the tone with the selected frequency.
carrier.Buzzer.sound(freq)Equivalent to noTone(): it will stop the tone signal.
carrier.Buzzer.noSound()playMelody
Section titled âplayMelodyâDespite you could think to use a buzzer only to trigger the userâs attention, you could also use it for playing songs and let it accompany you as a counterpoint when you play an instrument.
Thatâs what I made in play_melody_on_carrier! Letâs drive into the major steps.
Define the header files:
musical-notes.hfilled with the notes constants fromB0toD#8(and a couple of bonus constants:ENDandPAUSE)musical-constants.hfilled with the notesâ duration (i.e. semibreve, minim, crotchet)songs.hthat contains bi-dimensional arrays filled with the notes (in a row) and their duration (in the other row).
The 4th step is, off course, to write the script that brings it all together, but the code is already very well self-documented with lots of comments all around. So jump right into play_melody_on_carrier.ino to learn it all!
Battery holder for a 18650 Li-Ion battery
Section titled âBattery holder for a 18650 Li-Ion batteryâThe Carrier can be either powered through a USB cable connected to the mounted MKR board, or through a battery. The battery used should be a LI-ION 18650 3.7 v battery, which can be mounted to the carrier via the battery holder on the bottom side.
A cable with JST connectors on both ends are needed to connect the MKR IoT Carrier and the MKR board. The Battery can then be recharged via a USB connection through the MKR Board (Runs up to 48h with a 3.7v 2500mAh).
SD Card slot
Section titled âSD Card slotâThe Carrier contains a SD Card slot that can hold a Micro SD, with which you can locally store data recorded from the sensors.
The SD library supports FAT16 and FAT32 file systems on standard SD cards and SDHC cards. It uses short 8.3 names for files. The file names passed to the SD library functions can include paths separated by forward-slashes, /, e.g. "home/sunrise.txt".
Since the working directory is always the root of the SD card, a name refers to the same file whether it includes a leading slash (e.g. "/file.txt" is equivalent to "file.txt"). As of version 1.0, the library supports opening multiple files.
The communication between the microcontroller and the SD card uses SPI, which takes place on digital pins 11, 12 and 13 (on most Arduino boards). Additionally, another pin must be used to select the SD card.
This can be the hardware SS pin - pin 10 (on most Arduino boards) - or another pin specified in the call to SD.begin(). Note that even if you donât use the hardware SS pin, it must be left as an output or the SD library wonât work.
Conclusion
Section titled âConclusionâThis is one of the very first steps to jump right into IoT development. I know this blog post is very complex and could be difficult to read and understand, but the I/O devices that the MKR IoT Carrier gives you are very complex too.
I tried to write the paragraphs and the code snippets as readable as possible!
Documentation
Section titled âDocumentationâI took inspiration from Arduino Docsâ MKR IoT Carrier Cheat Sheet article to write this blog post.
You can also take a look at official MKR Datasheet.
Quoted Libraries
Section titled âQuoted LibrariesâHere is the full list of libraries I quoted within this article:
Arduino libraries:
Arduino_MKRIoTCarrierArduino_MCHPTouchArduino_LSM6DS3Arduino_HTS221Arduino_LPS22HBArduino_APDS9960SD
Adafruit libraries:
Other libraries:
MKR-IoT-Carrierdirectory ofarduino-projectsGitLab repository