{"id":39746,"date":"2021-01-19T18:16:20","date_gmt":"2021-01-19T10:16:20","guid":{"rendered":"\/blog\/?p=39746"},"modified":"2021-01-20T23:38:10","modified_gmt":"2021-01-20T15:38:10","slug":"tiny-ml-with-wio-terminal-1-intro","status":"publish","type":"post","link":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/","title":{"rendered":"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro"},"content":{"rendered":"\n<p>This article is the first article of the series about TinyML. For more details and video tutorial, watch the corresponding video!<\/p>\n\n\n\n<figure class=\"wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe title=\"Arduino Machine Learning Tutorial: Introduction to TinyML with Wio Terminal\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/iCmlKyAp8eQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Let&#8217;s start by explaining what is TinyML. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-785x1030.jpg\" alt=\"\" class=\"wp-image-39747\" width=\"187\" height=\"246\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-785x1030.jpg 785w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-229x300.jpg 229w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-768x1008.jpg 768w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-1171x1536.jpg 1171w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-1561x2048.jpg 1561w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL-1024x1344.jpg 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/81nihP0ASSL.jpg 1951w\" sizes=\"(max-width: 187px) 100vw, 187px\" \/><\/figure><\/div>\n\n\n\n<p>ML as you might have guessed stands for Machine Learning&nbsp;and in most of cases (not always though) nowadays refers to Deep Learning.&nbsp;Tiny in TinyML means that the ML models&nbsp;are optimized to run on very low-power and small footprint devices, such as various MCUs. It is a subset of ML on the Edge or Embedded Machine Learning. <\/p>\n\n\n\n<p>Embedded devices come in all sorts of shapes and sizes, starting from &#8220;embedded&nbsp;supercomputer&#8221; Nvidia Jetson Xavier AGX to the tiniest of microcontrollers, for example ESP32 or Cortex M0. Why embedded ML&nbsp;on microcontrollers is put in a special category and even given its own cool name?<\/p>\n\n\n\n<figure class=\"wp-block-gallery columns-2 wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\"><ul class=\"blocks-gallery-grid\"><li class=\"blocks-gallery-item\"><figure><img fetchpriority=\"high\" decoding=\"async\" width=\"750\" height=\"750\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/1-750x750-1.jpg\" alt=\"\" data-id=\"39749\" data-full-url=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/1-750x750-1.jpg\" data-link=\"\/blog\/?attachment_id=39749\" class=\"wp-image-39749\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/1-750x750-1.jpg 750w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/1-750x750-1-300x300.jpg 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/1-750x750-1-80x80.jpg 80w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/li><li class=\"blocks-gallery-item\"><figure><img decoding=\"async\" width=\"1030\" height=\"542\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-1030x542.png\" alt=\"\" data-id=\"39750\" data-full-url=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px.png\" data-link=\"\/blog\/?attachment_id=39750\" class=\"wp-image-39750\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-1030x542.png 1030w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-300x158.png 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-768x404.png 768w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-1536x808.png 1536w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-1024x539.png 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px-720x380.png 720w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/xavier-module-dev-kit-3qrtr-1945px.png 1600w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure><\/li><\/ul><\/figure>\n\n\n\n<p>Because it comes with&nbsp;it\u2019s own set of advantages and limitations. The attraction of TinyML is in fact that MCUs are ubiquitous, small, consume small amounts of energy&nbsp;and comparatively&nbsp;cheap. Take ARM Cortex M0+ and the little Seeeduino XIAO board which is built around it &#8211; the board is as small as a thumb(20&#215;17.5mm) , consumes only 1.33 mAh of power (which means it can work ~112 hours on a 150 mA battery, much more if put in deep sleep) and cost as little as 4.3 USD. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"688\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/Seeeduino-XIAO-pinout.jpg\" alt=\"\" class=\"wp-image-39751\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/Seeeduino-XIAO-pinout.jpg 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/Seeeduino-XIAO-pinout-300x202.jpg 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/Seeeduino-XIAO-pinout-768x516.jpg 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Thanks to recent improvements in model optimization and emergence of frameworks specifically created for running machine learning model inference on microcontrollers, it has became possible to give more intelligence to these tiny devices. We now can deploy neural networks on microcontrollers for <strong>audio scene recognition<\/strong> (for example elephant activity or sound of breaking glass),<strong> hot-word detection<\/strong>(to activate device with a specific phrase) or even for simple <strong>image recognition<\/strong> tasks. The devices with embedded microcontrollers can be used to give new life and meaning to old sensors, such as using an accelerometer installed on a mechanism for anomaly detection and predictive maintenance &#8211; or to distinguish various kinds of liqueurs as in <a href=\"https:\/\/wiki.seeedstudio.com\/Wio-Terminal-Edge-Impulse-Distinguish-Alochol\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"this demo (opens in a new tab)\">this demo<\/a>! <strong>The possibilities of TinyML are truly huge. <\/strong><\/p>\n\n\n\n<p>What about limitations? The main limiting factor is RAM\/FLASH size of MCUs &#8211; no matter how you well optimize, you wouldn\u2019t be able to fit that YOLO9999 into a tiny microcontroller. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"638\" height=\"359\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/yolo9000-pr023-1-638.jpg\" alt=\"\" class=\"wp-image-39752\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/yolo9000-pr023-1-638.jpg 638w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/yolo9000-pr023-1-638-300x169.jpg 300w\" sizes=\"(max-width: 638px) 100vw, 638px\" \/><figcaption>Obviously YOLO9999 is not far off as well.<\/figcaption><\/figure>\n\n\n\n<p>Same goes for automatic speech recognition &#8211; while simple hot word (or voice command detection) is possible, open domain speech recognition is out of reach of MCUs. <strong>For now.<\/strong> <\/p>\n\n\n\n<p>In this series of videos we\u2019ll mainly be using <strong>ARM Cortex M4F<\/strong> core inside Wio Terminal development board and, as bonus content, ARM Cortex M0+ core inside of XIAO devboard. Wio Terminal is a perfect tool to get started with IoT and TinyML &#8211; it is built around ATSAMD51P19 chip with ARM Cortex-M4F core running at 120MHz, which is very well supported by various frameworks for ML inference on microcontrollers. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"579\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/maxresdefault-1030x579.jpg\" alt=\"\" class=\"wp-image-39753\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/maxresdefault-1030x579.jpg 1030w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/maxresdefault-300x169.jpg 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/maxresdefault-768x432.jpg 768w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/maxresdefault-1024x576.jpg 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/maxresdefault.jpg 1280w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>The board also has <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>built-in light sensor<\/li><li>microphone <\/li><li>programmable buttons <\/li><li>2.4 inch LCD display <\/li><li>accelerometer <\/li><li> 2 Grove ports for easy connection of more than 300 various Grove ecosystem sensors<\/li><\/ul>\n\n\n\n<p>The list goes on, for full specs have a look at <a href=\"https:\/\/wiki.seeedstudio.com\/Wio-Terminal-Getting-Started\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Wio Terminal Wiki page here (opens in a new tab)\">Wio Terminal Wiki page here<\/a>.<\/p>\n\n\n\n<p>Software-wise we will be using Arduino IDE for programming the devices and a mix of Edge Impulse and Tensorflow Lite for Microcontrollers for model training and inference. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"547\" height=\"92\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/index.png\" alt=\"\" class=\"wp-image-39754\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/index.png 547w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/index-300x50.png 300w\" sizes=\"(max-width: 547px) 100vw, 547px\" \/><\/figure>\n\n\n\n<p>Edge Impulse is a user-friendly development platform for machine learning on edge devices, providing beginner friendly (yet powerful) web interface and toolkit for whole TinyMl pipeline, from data collection all the way to model deployment. In later articles I will also demonstrate how you can use pure Tensorflow Lite for Microcontrollers to implement your own model training and inference pipeline.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/tensorflow-lite-logo-social-1-1030x579.png\" alt=\"\" class=\"wp-image-39755\" width=\"315\" height=\"196\" \/><\/figure>\n\n\n\n<p>For this article, let\u2019s quickly train and deploy a simple neural network for classifying rock-paper-scissors gestures with just a <strong>single light sensor<\/strong>. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"414\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/i-dont-believe-vmn19t.jpg\" alt=\"\" class=\"wp-image-39756\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/i-dont-believe-vmn19t.jpg 600w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/i-dont-believe-vmn19t-300x207.jpg 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure><\/div>\n\n\n\n<p>Don\u2019t believe it\u2019s possible? Well, let\u2019s find out!<\/p>\n\n\n\n<p>We start by registering an account on <a href=\"https:\/\/www.edgeimpulse.com\/.\">https:\/\/www.edgeimpulse.com\/.<\/a>&nbsp;Then, since Wio Terminal is at the moment is a Community supported board and doesn&#8217;t have all built-in sensors data collection pipeline implemented yet, we will use data forwarder tool from edge-impulse-cli to gather data samples.<\/p>\n\n\n\n<p>Install Node.JS 12 on your computer <a href=\"https:\/\/snapcraft.io\/node\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"using snap package (opens in a new tab)\">using snap package<\/a>, then execute <\/p>\n\n\n\n<p><code>npm install -g edge-impulse-cli<\/code><\/p>\n\n\n\n<p>If (or &#8220;when&#8221; to be precise) you run into permission problems on Linux, <a rel=\"noreferrer noopener\" aria-label=\"configure Node.js (opens in a new tab)\" href=\"https:\/\/github.com\/sindresorhus\/guides\/blob\/master\/npm-global-without-sudo.md\" target=\"_blank\">configure Node.js<\/a> to install packages into a different folder than usr\/lib.<\/p>\n\n\n\n<p>After edge-impulse-cli is installed create a new project in Edge Impulse Dashboard and prepare to gather the data. You can forward any type of sensor data to Edge Impulse platform with <a href=\"https:\/\/docs.edgeimpulse.com\/docs\/cli-data-forwarder\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"data forwarder (opens in a new tab)\">data forwarder<\/a> &#8211; here is a sample code for forwarding arbitrary sensor data (in this example accelerometer) from device:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;Arduino_LSM9DS1.h&gt;\n\n#define CONVERT_G_TO_MS2    9.80665f\n#define FREQUENCY_HZ        50\n#define INTERVAL_MS         (1000 \/ (FREQUENCY_HZ + 1))\n\nvoid setup() {\n    Serial.begin(115200);\n    Serial.println(\"Started\");\n\n    if (!IMU.begin()) {\n        Serial.println(\"Failed to initialize IMU!\");\n        while (1);\n    }\n}\n\nvoid loop() {\n    static unsigned long last_interval_ms = 0;\n    float x, y, z;\n\n    if (millis() &gt; last_interval_ms + INTERVAL_MS) {\n        last_interval_ms = millis();\n\n        IMU.readAcceleration(x, y, z);\n\n        Serial.print(x * CONVERT_G_TO_MS2);\n        Serial.print('\\t');\n        Serial.print(y * CONVERT_G_TO_MS2);\n        Serial.print('\\t');\n        Serial.println(z * CONVERT_G_TO_MS2);\n    }\n}<\/code><\/pre>\n\n\n\n<p>If you have multiple sensor values in one packet, each sensor value should be separated with <strong>a comma or tab character<\/strong>. The end of the packet is denoted by a <strong>new line character<\/strong>, so you can just use Serial.println for last value in a packet. In this project we just have one sensor that sends one value in each packet.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define INTERVAL_MS 25\n\nvoid setup() {\n    Serial.begin(115200);\n    Serial.println(\"Started\");\n    }\n\nvoid loop() {\n    static unsigned long last_interval_ms = 0;\n    float light;\n\n    if (millis() &gt; last_interval_ms + INTERVAL_MS) {\n        last_interval_ms = millis();\n        light = analogRead(WIO_LIGHT);\n        Serial.println(light);\n        \/\/Serial.print('\\t');\n    }\n}<\/code><\/pre>\n\n\n\n<p>Once you uploaded the code to Wio Terminal, run <\/p>\n\n\n\n<p><code>edge-impulse-data-forwarder<\/code><\/p>\n\n\n\n<p>and log in with your Edge Impulse credentials. Now you are ready to receive data in Edge Impulse dashboard. &nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"500\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/image-1030x500.png\" alt=\"\" class=\"wp-image-39757\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1030x500.png 1030w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-300x146.png 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-768x373.png 768w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1536x745.png 1536w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1024x497.png 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image.png 1857w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>Set sample length to about 10000 ms or 10 seconds and create 10 samples for each gesture, waving the hand in vicinity of Wio terminal. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"320\" height=\"180\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/gif1.gif\" alt=\"\" class=\"wp-image-39764\" \/><\/figure><\/div>\n\n\n\n<p>This is a small dataset, but we also have a tiny neural network, so underfitting is more likely than overfitting in this particular case. When collecting samples it is important to provide diversity for model to be able to generalize better, for example have samples with different direction, speed and distance from sensor. In general, the network only can learn from data present in the dataset &#8211; so if the only samples you have are gestures being moved from left to right above the sensor, you shouldn\u2019t expect trained model to be able to recognize gestures being moved right to left or up and down.<\/p>\n\n\n\n<p>After you collected the samples it is time to design an \u201cimpulse\u201d. Impulse here is the word Edge Impulse used to denote data processing &#8211; training pipeline. I\u2019d say currently is is the weakest spot of Edge Impulse interface &#8211; there is a lot of options, but not so much documentation, which can leave you confused, unless you have background in Data science and\/or Digital Signal Processing. For this proof-of-concept project, &nbsp;I have tried three different prepossessing blocks with default parameters(except for adding scaling) &#8211; I started with Flatten block, which takes computes Average, Min, Max and other functions of raw data within time window.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"629\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/image-1-1030x629.png\" alt=\"\" class=\"wp-image-39758\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1-1030x629.png 1030w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1-300x183.png 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1-768x469.png 768w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1-1536x938.png 1536w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1-1024x626.png 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-1.png 1568w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>I have also tried Spectral Features block, which extracts the frequency and power characteristics of a signal over time<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"624\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/image-2-1030x624.png\" alt=\"\" class=\"wp-image-39759\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-2-1030x624.png 1030w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-2-300x182.png 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-2-768x465.png 768w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-2-1024x620.png 1024w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-2.png 1532w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>and Raw data block, which as you might have guessed just feeds raw data to NN learning block (optionally normalizing the data). I then went on training simple fully-connected network with 2 hidden layers, 20 and 10 neurons in each hidden layer respectively for Flatten and Spectral Features processing blocks and a 2-layer Convolutional network for Raw features. Here are the Keras API codes for both networks (it&#8217;s easier for me to understand what&#8217;s going on by reading code, than looking at blocks in the interface)<\/p>\n\n\n\n<p>Fully-connected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># model architecture\nmodel = Sequential()\nmodel.add(Dense(20, activation='relu',\n    activity_regularizer=tf.keras.regularizers.l1(0.00001)))\nmodel.add(Dense(10, activation='relu',\n    activity_regularizer=tf.keras.regularizers.l1(0.00001)))\nmodel.add(Dense(classes, activation='softmax', name='y_pred'))<\/code><\/pre>\n\n\n\n<p>Convolutional:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># model architecture\nmodel = Sequential()\nmodel.add(Reshape((int(input_length \/ 1), 1), input_shape=(input_length, )))\nmodel.add(Conv1D(8, kernel_size=4, activation='relu', padding='same'))\nmodel.add(MaxPooling1D(pool_size=2, strides=2, padding='same'))\nmodel.add(Conv1D(16, kernel_size=2, activation='relu', padding='same'))\nmodel.add(MaxPooling1D(pool_size=2, strides=2, padding='same'))\nmodel.add(Flatten())\nmodel.add(Dense(classes, activation='softmax', name='y_pred'))<\/code><\/pre>\n\n\n\n<p>The final results after training for 500 epochs with 1e-4 learning rate and Adam optimizer(beta_1=0.9, beta_2=0.999), batch size 32 were <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Flatten FC 69.9 % accuracy<\/li><li>Spectral Features FC 70.4 % accuracy<\/li><li>Raw Data Conv1D 92.4 % accuracy<\/li><\/ul>\n\n\n\n<p>To dissect the performance of the models, it is important to look at the data and how it is processed. Both Flatten and Spectral Features processing blocks remove the time relationship within each window &#8211; Flatten block simply turns the raw values, that are initially in sequence  to Average, Min, Max, etc. values calculated on all values in time window,<strong> irrespective<\/strong> of their order.  Spectral Features block extracts the frequency and power characteristics and the reason it didn&#8217;t work that well for this particular task is probably that the duration of each gesture is too short.<\/p>\n\n\n\n<p>If we think about it, for classifying rock-paper-scissors gestures we just need to count how many times and for how long the light sensor has received &#8220;lower-than-normal&#8221; values. If it is one relatively long time &#8211; then it is rock (fist passing above the sensors). If it is two times, then it is scissors. Anything more than that is paper. Sounds easy, but preserving time series data is really important for neural network to be able to learn this relationship in data points.<\/p>\n\n\n\n<p>We could have just used a simple fully-connected NN to work on raw data as well &#8211; but that would unnecessarily increase the size of the network. With 40 Hz frequency and time window size of 1000 ms we have 40 data points in each window, so 40 inputs multiplied by 20 neurons in the first hidden layer gives us 800 weights. By using Conv1D layers, we can get away with just 40 weights in the first hidden layer instead and then use MaxPool layers to reduce size of feature maps. <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/max\/6198\/1*-hYGWjdLF_RuWO4OcrFd-g.png\" alt=\"Types of Convolution Kernels : Simplified | by Prakhar Ganesh | Towards  Data Science\" \/><\/figure>\n\n\n\n<p>We will discuss Convolutions and how useful they are in later articles about sound and image processing.<\/p>\n\n\n\n<p>Feature visualization is particularity useful tool in Edge Impulse web interface, as it allows users to get graphical insights into how the data looks after prepossessing. For example this is data after Flatten processing block:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"703\" height=\"705\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/image-3.png\" alt=\"\" class=\"wp-image-39760\" srcset=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-3.png 703w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-3-300x300.png 300w, https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/image-3-80x80.png 80w\" sizes=\"(max-width: 703px) 100vw, 703px\" \/><\/figure>\n\n\n\n<p>We can see that the data points for different classes are roughly divided, but there is a lot of overlap between rock and other classes.<\/p>\n\n\n\n<p>After the training you can test the model using Live classification tab, which will gather a data sample from device and classify it with model hosted on Edge Impulse. We test with three different gestures and see the accuracy is satisfactory as far as proof of concept goes. <\/p>\n\n\n\n<p>The next step is deployment on device. After clicking on Deployment tab, choose Arduino library and download it. Extract the archive and place it in your Arduino libraries folder. Open Arduino IDE and choose static buffer sketch, which already has all the boilerplate code for classification with your model in place. Neat!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;video_tinyml_inference.h&gt;\n\nfloat features[40];\n\n\/**\n * @brief      Copy raw feature data in out_ptr\n *             Function called by inference library\n *\n * @param[in]  offset   The offset\n * @param[in]  length   The length\n * @param      out_ptr  The out pointer\n *\n * @return     0\n *\/\nint raw_feature_get_data(size_t offset, size_t length, float *out_ptr) {\n    for (byte i = 0; i &lt; 41; i = i + 1) \n    {\n    features[i]=analogRead(WIO_LIGHT);\n    delay(25);\n    }\n    memcpy(out_ptr, features + offset, length * sizeof(float));\n    return 0;\n}\n\n\n\/**\n * @brief      Arduino setup function\n *\/\nvoid setup()\n{\n    \/\/ put your setup code here, to run once:\n    Serial.begin(115200);\n\n    Serial.println(\"Edge Impulse Inferencing Demo\");\n}\n\n\/**\n * @brief      Arduino main function\n *\/\nvoid loop()\n{\n    ei_printf(\"Edge Impulse standalone inferencing (Arduino)\\n\");\n\n    if (sizeof(features) \/ sizeof(float) != EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE) {\n        ei_printf(\"The size of your 'features' array is not correct. Expected %lu items, but had %lu\\n\",\n            EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, sizeof(features) \/ sizeof(float));\n        delay(1000);\n        return;\n    }\n\n    ei_impulse_result_t result = { 0 };\n\n    \/\/ the features are stored into flash, and we don't want to load everything into RAM\n    signal_t features_signal;\n    features_signal.total_length = sizeof(features) \/ sizeof(features[0]);\n    features_signal.get_data = &amp;raw_feature_get_data;\n\n    \/\/ invoke the impulse\n    EI_IMPULSE_ERROR res = run_classifier(&amp;features_signal, &amp;result, false \/* debug *\/);\n    ei_printf(\"run_classifier returned: %d\\n\", res);\n\n    if (res != 0) return;\n\n    \/\/ print the predictions\n    ei_printf(\"Predictions \");\n    ei_printf(\"(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)\",\n        result.timing.dsp, result.timing.classification, result.timing.anomaly);\n    ei_printf(\": \\n\");\n    ei_printf(\"[\");\n    for (size_t ix = 0; ix &lt; EI_CLASSIFIER_LABEL_COUNT; ix++) {\n        ei_printf(\"%.5f\", result.classification[ix].value);\n#if EI_CLASSIFIER_HAS_ANOMALY == 1\n        ei_printf(\", \");\n#else\n        if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {\n            ei_printf(\", \");\n        }\n#endif\n    }\n#if EI_CLASSIFIER_HAS_ANOMALY == 1\n    ei_printf(\"%.3f\", result.anomaly);\n#endif\n    ei_printf(\"]\\n\");\n\n    \/\/ human-readable predictions\n    for (size_t ix = 0; ix &lt; EI_CLASSIFIER_LABEL_COUNT; ix++) {\n        ei_printf(\"    %s: %.5f\\n\", result.classification[ix].label, result.classification[ix].value);\n    }\n#if EI_CLASSIFIER_HAS_ANOMALY == 1\n    ei_printf(\"    anomaly score: %.3f\\n\", result.anomaly);\n#endif\n\n    delay(1000);\n}\n\n\/**\n * @brief      Printf function uses vsnprintf and output using Arduino Serial\n *\n * @param[in]  format     Variable argument list\n *\/\nvoid ei_printf(const char *format, ...) {\n    static char print_buf[1024] = { 0 };\n\n    va_list args;\n    va_start(args, format);\n    int r = vsnprintf(print_buf, sizeof(print_buf), format, args);\n    va_end(args);\n\n    if (r &gt; 0) {\n        Serial.write(print_buf);\n    }\n}<\/code><\/pre>\n\n\n\n<p>The only thing for use to fill in is the data acquisition on-device. We\u2019ll use a simple for loop with delay to account for frequency (if you remember we had 100 ms delay when gathering data for training dataset). <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    for (byte i = 0; i &lt; 41; i = i + 1) \n    {\n    features[i]=analogRead(WIO_LIGHT);\n    delay(25);\n    }<\/code><\/pre>\n\n\n\n<p>Certainly there are better ways to implement this, for example a sensor data buffer , which would allow us to perform inference more often. But we\u2019ll get to that in later articles of this series.<\/p>\n\n\n\n<p>After you added sensor data acquisition part to sample code upload it to Wio Terminal and open Serial monitor. Move your hand while performing a gesture and see the probability results printed out on Serial monitor.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"600\" src=\"https:\/\/blog.seeedstudio.com\/wp-content\/uploads\/2021\/01\/gif3-3.gif\" alt=\"\" class=\"wp-image-39775\" \/><\/figure><\/div>\n\n\n\n<p>Mind blowing! <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/memegenerator.net\/img\/instances\/23990718.jpg\" alt=\"MIND = BLOWN - Dwight Schrute | Meme Generator\" \/><\/figure><\/div>\n\n\n\n<p>While it was just a proof of concept demonstration, it really shows TinyML is up to something big. As a person who does a lot of Computer vision projects, I knew it is possible to recognize gestures with a camera sensor, even if image is down-scaled a lot. What I didn\u2019t know that it is possible to recognize gestures with <strong>just 1 pixel<\/strong>!<\/p>\n\n\n\n<p>Tell us your ideas for cool TinyML projects in the comment section and stay tuned for more articles and videos in upcoming weeks!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is the first article of the series about TinyML. For more details and<\/p>\n","protected":false},"author":3505,"featured_media":39763,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_tribe_ticket_capacity":"0","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"iawp_total_views":0,"footnotes":""},"categories":[1],"tags":[2227,1608,2965,3171,3003],"class_list":["post-39746","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","tag-arduino-projects","tag-machine-learning","tag-sensor-output","tag-tinyml","tag-wio-terminal"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Learn TinyML using Wio Terminal and Arduino IDE #1 Intro - Latest News from Seeed Studio<\/title>\n<meta name=\"description\" content=\"The devices with embedded microcontrollers can be used to give new life and meaning to old sensors.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro - Latest News from Seeed Studio\" \/>\n<meta property=\"og:description\" content=\"The devices with embedded microcontrollers can be used to give new life and meaning to old sensors.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/\" \/>\n<meta property=\"og:site_name\" content=\"Latest News from Seeed Studio\" \/>\n<meta property=\"article:published_time\" content=\"2021-01-19T10:16:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-20T15:38:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1082\" \/>\n\t<meta property=\"og:image:height\" content=\"838\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Dmitry Maslov\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Dmitry Maslov\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/\",\"url\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/\",\"name\":\"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro - Latest News from Seeed Studio\",\"isPartOf\":{\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png\",\"datePublished\":\"2021-01-19T10:16:20+00:00\",\"dateModified\":\"2021-01-20T15:38:10+00:00\",\"author\":{\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/#\/schema\/person\/be44021cef50367de429a4d5f613ed2f\"},\"description\":\"The devices with embedded microcontrollers can be used to give new life and meaning to old sensors.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#primaryimage\",\"url\":\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png\",\"contentUrl\":\"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png\",\"width\":1082,\"height\":838},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.seeedstudio.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/#website\",\"url\":\"https:\/\/www.seeedstudio.com\/blog\/\",\"name\":\"Latest News from Seeed Studio\",\"description\":\"Emerging IoT, AI and Autonomous Applications on the Edge\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.seeedstudio.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/#\/schema\/person\/be44021cef50367de429a4d5f613ed2f\",\"name\":\"Dmitry Maslov\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.seeedstudio.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b60714970fdc7dfa4a5d9915477bdd24?s=96&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b60714970fdc7dfa4a5d9915477bdd24?s=96&r=g\",\"caption\":\"Dmitry Maslov\"},\"url\":\"https:\/\/www.seeedstudio.com\/blog\/author\/dmitry-maslov\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro - Latest News from Seeed Studio","description":"The devices with embedded microcontrollers can be used to give new life and meaning to old sensors.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/","og_locale":"en_US","og_type":"article","og_title":"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro - Latest News from Seeed Studio","og_description":"The devices with embedded microcontrollers can be used to give new life and meaning to old sensors.","og_url":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/","og_site_name":"Latest News from Seeed Studio","article_published_time":"2021-01-19T10:16:20+00:00","article_modified_time":"2021-01-20T15:38:10+00:00","og_image":[{"width":1082,"height":838,"url":"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png","type":"image\/png"}],"author":"Dmitry Maslov","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Dmitry Maslov","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/","url":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/","name":"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro - Latest News from Seeed Studio","isPartOf":{"@id":"https:\/\/www.seeedstudio.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#primaryimage"},"image":{"@id":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#primaryimage"},"thumbnailUrl":"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png","datePublished":"2021-01-19T10:16:20+00:00","dateModified":"2021-01-20T15:38:10+00:00","author":{"@id":"https:\/\/www.seeedstudio.com\/blog\/#\/schema\/person\/be44021cef50367de429a4d5f613ed2f"},"description":"The devices with embedded microcontrollers can be used to give new life and meaning to old sensors.","breadcrumb":{"@id":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#primaryimage","url":"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png","contentUrl":"https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png","width":1082,"height":838},{"@type":"BreadcrumbList","@id":"https:\/\/www.seeedstudio.com\/blog\/2021\/01\/19\/tiny-ml-with-wio-terminal-1-intro\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.seeedstudio.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Learn TinyML using Wio Terminal and Arduino IDE #1 Intro"}]},{"@type":"WebSite","@id":"https:\/\/www.seeedstudio.com\/blog\/#website","url":"https:\/\/www.seeedstudio.com\/blog\/","name":"Latest News from Seeed Studio","description":"Emerging IoT, AI and Autonomous Applications on the Edge","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.seeedstudio.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.seeedstudio.com\/blog\/#\/schema\/person\/be44021cef50367de429a4d5f613ed2f","name":"Dmitry Maslov","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.seeedstudio.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b60714970fdc7dfa4a5d9915477bdd24?s=96&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b60714970fdc7dfa4a5d9915477bdd24?s=96&r=g","caption":"Dmitry Maslov"},"url":"https:\/\/www.seeedstudio.com\/blog\/author\/dmitry-maslov\/"}]}},"modified_by":"Dmitry Maslov","views":8998,"featured_image_urls":{"full":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png",1082,838,false],"thumbnail":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-80x80.png",80,80,true],"medium":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-300x232.png",300,232,true],"medium_large":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-768x595.png",640,496,true],"large":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-1030x798.png",640,496,true],"1536x1536":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png",1082,838,false],"2048x2048":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png",1082,838,false],"visody_icon":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png",32,25,false],"magazine-7-slider-full":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011.png",1082,838,false],"magazine-7-slider-center":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-936x838.png",936,838,true],"magazine-7-featured":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-1024x793.png",1024,793,true],"magazine-7-medium":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-720x380.png",720,380,true],"magazine-7-medium-square":["https:\/\/www.seeedstudio.com\/blog\/wp-content\/uploads\/2021\/01\/wio-011-675x450.png",675,450,true]},"author_info":{"display_name":"Dmitry Maslov","author_link":"https:\/\/www.seeedstudio.com\/blog\/author\/dmitry-maslov\/"},"category_info":"<a href=\"https:\/\/www.seeedstudio.com\/blog\/category\/news\/\" rel=\"category tag\">News<\/a>","tag_info":"News","comment_count":"0","_links":{"self":[{"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/posts\/39746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/users\/3505"}],"replies":[{"embeddable":true,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/comments?post=39746"}],"version-history":[{"count":8,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/posts\/39746\/revisions"}],"predecessor-version":[{"id":39858,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/posts\/39746\/revisions\/39858"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/media\/39763"}],"wp:attachment":[{"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/media?parent=39746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/categories?post=39746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.seeedstudio.com\/blog\/wp-json\/wp\/v2\/tags?post=39746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}