Beginners Guide on how to start with the Arduino Ecosystem + electronics

I’m in a lucky position that this blog ranks very well on search engines which leads to a high amount of daily visitors. In addition, I have a lot of beginner tutorials on this blog. As a result, I get a lot of emails, many of them are about how to get started with Arduino, sensor/actuators, etc.
Unfortunately, I get many more emails/messages than I can answer. That is why I started this article to address some of these questions. This article has been written especially for those readers who are just thinking about starting with the Arduino ecosystem or electronics (e.g. ESP8266, ESP32,…).

Why do you want to start with Arduino/Electronics?

3d开机号试机号before you start, maybe think about why you want to start with electronics. besides my professional life, i acquired some skills in other disciplines, such as construction knowledge, woodworking, 3d printing etc. if i order all these disciplines by how often i really need to apply them, then electronics is maybe the one i could spare most. don’t get me wrong, in my spare time, i do often electronics and i like it… but it would not hurt me in terms of life quality or financial savings if i just stop. for example, we are currently refurbishing our house, so my construction skills come in handy. in addition, i build many furnishings (table, lamps, shelves,…) myself, so i do also woodworking a lot. i guess, all the money and time i spent to improve my construction and woodworking capabilities (e.g. by buying new tools) did payback multiple times in improved life quality and/or financial savings.

i’m note sure if this applies also to my activities related to electronics and the arduino ecosystem. the main reason why i started was to deepen my knowledge in sensors and actuators. my main background has been computer science with a strong focus on software architecture/engineering/development – but i always intended to go into “hardware engineering”, too. so, when i started with electronics, it had already been clear to me, that gaining knowledge in electronics will be part of my life for a long time. therefore, i probably spent a bit more money on my “initial equipment” than i this article will suggest.

getting to the point: the recommendations in this article address especially readers that do not know for sure if they will stick with electronics for a longer time frame. in my opinion, in such cases it makes no sense to spent a lot of money to get started. the good news is that starting with the arduino ecosystem is not very cost-intense. there are excellent starter kits available for less than 25$. if you already know that you will stick with electronics for some time – like in my case, then it can make sense to spend a bit more on a starter kit.

What do you, as a person, need to start?

naturally, it will be beneficial if you have already acquired some basic knowledge in electronics. moreover, it also helps if you have someone around that can help you if you get stucked (e.g. uncle or aunt who is familiar with the basics of electronics). nonetheless, if you have no experience at all, but are motivated enough to learn the ropes, you will very likely succeed. there are so many video or written tutorials around, so there is almost no excuse to not get started.

What software do you need?

Screenshot of the Arduino IDE.

3d开机号试机号the is basically everything you need to get started. fortunately, the arduino ide is available for free. there are very good alternatives available that are also for free, e.g. . but i recommend to start with the arduino ide, as its widely used and very easy to understand. if you are missing some advanced features, you can always go to another software platform.

What hardware equipment do you need?

as a starting point i recommend to aquire a breadboard, some jumper wires and, of course, an arduino. in addition it makes sense to buy also some resistors and leds and a switch in order to implement very basic use cases.

Basic equipment to start with:
– Breadboard [Search on | ]
– Jumper wires [Search on | ]
– Arduino [Search on | ]
– LED [Search on | ]
– Switch [Search on | ]
– Resistor (1k ohm) [Search on | ]


breadboards are perfect prototyping platforms for making circuits. the main advantage of breadboards is that soldering is not required in order to integrate components into a circuit. in particular, many components can be just placed onto a breadboards. this makes breadboards the perfect choice for prototyping or testing (new) components. the drawback is that breadboards are not the best solution when it comes to permanent applications. especially, if the breadboard gets moved or shaken around, components might come loose. nonetheless, they are the perfect starting point for beginners.

when buying some breadboards, i don’t recommend to buy cheapest ones. once or twice i bought a batch of breadboards for a very low price. unfortunately, the quality turned out to be not really sufficient, as wires and legs of components did not stick well into the exposed holes of these breadboards. therefore, i recommend to buy rather 3-5 more expensive breadboards (or with good customer ratings) than 10 cheap breadboards. starting with one breadboard is also fine. but, in order to preserve a project for some time, it makes sense to have multiple breadboards.

3d开机号试机号in most cases, the standard size of about 5.5 cm x 8.5 cm / 2.2″ x 3.4″ is fine. though, i recommend to have at least one larger breadboard (5.5 cm x 17 cm / 2.2″ x 7″).

Jumper Wires

jumper wires (also called jump wires) are electrical wires with connector at each ends. there exists three types of different jumper wires in terms of their connectors: female/female, male/male, and female/male. the male connectors fit perfectly into the exposed holes of breadboards. jumper wires are the connection elements when it comes to implement a circuit on a breadboard. in other words, jumper wires are used to connect electrical components in order to form a circuit.

jumper wires are available in different lengths, where lengths of 10 cm and 20 cm are very common. in many tutorials – also in mine, black is used for gnd and red for 5v. when you plan to use the same color scheme and start to wire, you will shortly recognize that you need black and red more often than the other colors. for this reason, i bought extra batches of just black and red wires.

Arduino (+USB cable)

Three different variants of the Arduino Uno R3: Noname Arduino Uno R3, Elegoo Uno R3 and Seeeduino

i guess, for many people, arduino is just the arduino uno r3 single-board microcontroller. but actually, there is more to it: there is the integrated development editor (ide), the company arduino llc, the website, etc. therefore, i see arduino primarily as an ecosystem with a hardware platform targeting on prototype projects.

3d开机号试机号anyway, to get started you need to pick a hardware: there exists many variants, such as the popular arduino uno r3, arduino nano, arduino mini etc. when starting, i would go for a “normal” arduino uno r3. the reason is that it is widely used an especially beginners do not get confused when copying/adapting from existing wiring diagrams.

3d开机号试机号if you decided for an uno r3, the question is which one to buy? i own around ten arduino uno r3s ranging from 1$ (noname from aliexpress) to around 25$ (original arduino). the “original” arduino made in italy is for sure of high quality, but also very expensive. especially, when considering the arduino uno r3 is almost 10 years old. from a price point, i recommend arduinos in a price range between 7-15$. if you plan to use only the analog inputs and digital inputs/outputs, then you are probably fine with a cheap arduino. at least i had many problems with cheap arduinos for application in which spi, i2c or serial connections were used.

besides the arduino uno r3 type, i can also recommend the arduino nanos. they are very compatible with the arduino unos and they fit perfectly on a breadboard. especially, if you do some prototyping over a longer time frame, it makes sense to use a nano in order to have everything on a single breadboard. btw. make sure that the arduino comes also with a usb cable if you don’t have one at home. the arduino uno has a usb b input and the nano has a usb mini input.

LED + 1k Resistor

Resistors (1k Ohm) + LEDs in different colors.

LEDs (light-emitting diodes) are perfect when you need output components that you want to control with an Arduino. LEDs can only emit light if wired correctly: GND is connected to the cathode (short leg) and the 5V signal to the anode (long leg). Moreover, LEDs require a resistor. You can either use Ohm’s Law or stick with the 1k rule of thumb (“1k works always, except in 1 out of 1000 cases”). If you are interested in more details, I made a tutorial about how to let an LED blink with an Arduino Uno.


3d开机号试机号switches are perfect as “input components” for starters. they are very simple to use as pressing a switch will result in a high signal and releasing the switch in a low signal (sometimes it’s also the other way around). for the first batch of switches, i recommend the ones that fit directly on a breadboard. the main advantage is that you can use them without soldering.

Starter Kits

Arduino Starter Kit (Elegoo Basic Starter Kit)

There are a lot of starter kits available which contain all of the previous components. Some days ago, Elegoo gave me their “Basic Starter Kit” for testing. In my opinion, it has a very good price-quality ratio and has contains the most important components. For these reasons, I can honestly recommend the starter kit (please see my Sponsorship Disclosure).

– Arduino starter kit [Search on | ]
– Elegoo Basic Starter Kit [Search on | ]

I did the basics, what’s next?

Selection of different breakout boards that can be directly wired to an Arduino, e.g. with a jumper wire.

If you started with a basic kit and are asking for more now, or want to start more ambitious direct from the beginning, I recommend to just go for more sensors and actuators. In many cases, it is not possible to wire a sensor directly to an Arduino since additional hardware is required. Luckily, there exist tons of breakout boards which contain the sensor/actuator and the required hardware components as well. Often, breakout boards are also referred to as “name of sensor/actuator”-module, especially when searching them up on online shops. There are a lot of breakout boards available that can directly wired to an Arduino. If you look up my tutorials you can find many of them: For example, KMR-1.8 SPI (TFT Display), RDM630/RDM6300 (RFID Reader), GY-521/MPU-6050 (gyroscope+accelerometer).

instead of buying each component individually, there is also the possibility to buy a kit with multiple sensor/actuator components. when i started with this topics some years ago, one of the first things i bought was also a kit with around 25 breakout boards.

– Arduino sensor kit [Search on | ]

What about debugging?

Multimeter (left) and low-cost DSO138 oscilloscope (right).

3d开机号试机号you will often come to point where you think that you code and wiring is correct but your application just does not work. then it makes sense to find the cause (also referred to as bug) and to do some debugging.

3d开机号试机号the most basic approach is to use the serial.print() function and add “print outs” to the code. this helps you to find software related problems, e.g. to check how often a for-loop has been executed etc.

3d开机号试机号finding a problem related to the hardware can be sometimes more complicated. the probably most typical mistake is that the wiring is not correct. for example, if you mix up a 3.3v input of a component with a 5v signal, the components gets damaged, and then good luck finding the problem. a good start is always using a multimeter to check whether the voltage levels are as expected. sometimes, an application is expected to change the voltage level based on a specific pattern, e.g. a led is supposed to light up for two seconds, go out for two seconds, light up for to two seconds and so on. in such cases, oscilloscopes are the perfect tool as they can monitor the timing behaviour. unfortunately, oscilloscopes are also very expensive. luckily, there is the so-called dso138 oscilloscope which is, in my opinion, the best oscilloscope in terms of quality-price-ratio. the dso138 can be purchased for around 10-20$ but has everything you need for debugging typical circuits of arduino applications.

– Multimeter [Search on | ]
– DSO138 oscilloscope [Search on | ]

What are alternatives to Arduino?

ESP32 development board.

3d开机号试机号since the start of the arduino ecosystem more than ten years have been passed. but i think it is still one of the best systems for starting with electronics. if you look up for alternatives, you probably come across recommendations for esp8266 and esp32. the esp8266 is a low-cost wi-fi microchip. in comparison to the arduino uno r3, it enables you to connect to a wireless network. whenever you want to push data to a network or the internet, the esp8266 is a good choice. the esp32 can be seen as a successor to the esp8266 (more features, more performance, etc.). the good thing about esp8266 and esp32 is that they are very compatible to the arduino ecosystem. for example, you can also use the arduino ide to program them. additionally, a lot of libraries written for the arduino do also work for esp8266 and esp32. if you know right from the start that you want to implement wireless application, that maybe go for a esp8266 or esp32. alternatively, when you have acquired some experience with the “plain” arduinos, the esp8266 and esp32 are the perfect platforms “for taking the next step”.

Arduino-to-Arduino Communication (via Serial Connection)

this tutorial shows how to establish a serial connection connection from an arduino to another arduino. each arduino has a tact switch and an led. if an arduino’s tactile switch is pressed, the led of the other arduino will be turned on.

List of materials (each item of this list is needed 2x):
– Jumper wires [Search on | ]
– Breadboard [Search on | ]
– Arduino [Search on | ]
– Tactile switch [Search on | ]
– LED [Search on | ]
– Resistor (1k ohm) [Search on | ]

Components used in this tutorial: 2x Arduinos, 2x tact switches, 2x 1k resistors and LEDs.
Components used in this tutorial: 2x Arduinos, 2x tact switches, 2x 1k resistors and LEDs.

3d开机号试机号in order to demonstrate the arduino-to-arduino communicaten two different types of arduinos are used. the first arduino is an seeeduino nano, which is a variant that is compatible to the arduino nano. the second arduino is an seeeduino v4.2 which is fully compatible to the arduino uno (see for more information). both arduinos will send only on of two bytes: either ‘0’ or ‘1’. if ‘0’ has been transmitted, the led will be turned off. if ‘1’ has been transmitted, the led will be turned on.


Setup after performing the wiring.
Setup after performing the wiring.

3d开机号试机号both arduino setups have the basically the same wiring: a tact switch, an led and a 1k resistor is added to a breaboard. the tact switch is wired to gnd and two digital pin #2. the led is wired to gnd and the 1k resistor. the resistor is wired to digital pin #3. the serial connection requires three wires: for gnd, receive and transmit. the receive wire is connected to digital pin #10. the transmit wire is connected to digital pin #11. in order to make the serial connection work, the receive wire of one arduino is connected to the transmit wire of the other arduino. the gnd wire might not be needed, e.g. as both arduinos probably share the same gnd signal when powered from the same power supply. nonetheless, it has been added to the wiring diagram for the sake of completeness.


3d开机号试机号first, the pins for the tact switch (input_pullup) and led (output) are set up. then, the serial connection is started. in the loop function, it is checked whether a byte was received from the serial connection. the digital output is set to the received byte: either ‘0’/false to turn off the led or ‘1’/true to turn it on. next, the current status of the tact switch is sent. ‘0’ is sent to the other arduino, if the tact switch if not pressed. otherwise, ‘1’ is sent. at the end of the loop function, a delay of 250ms is added.

// (c) Michael Schoeffler 2020,* * This program is part of a tutorial that shows how to communicate from an Arduino to another Arduino via a serial connection.  * The status of a tact switch is sent to the other Arduino. If the switch is pressed, an LED is turned on. * This program has to be transferred to both Arduinos in order to make the application work.  */#include <SoftwareSerial.h>const int IN_TACT_SWITCH = 2; // input pin for tactile switchconst int OUT_LED = 3; // output pin for LEDSoftwareSerial sserial(10,11); // receive pin=10, transmit pin=11void setup() {  pinMode(IN_TACT_SWITCH, INPUT_PULLUP); // set the LED pin to input pullup mode  pinMode(OUT_LED, OUTPUT); // set the LED pin to output mode  sserial.begin(9600); // start serial connection}void loop() {  // receive  if (sserial.available() > 0) {    byte incomingByte = 0;    incomingByte =;    if (incomingByte != -1) {      Serial.print(incomingByte);      digitalWrite(OUT_LED, incomingByte); // switch LED on or off     }  }  // send   sserial.write(!digitalRead(IN_TACT_SWITCH)); // Tact switch (used in the corresponding tutorial) is inverted. Therefore, inverted status is sent to other Arduino    delay(250); // delay required to avoid flooding the other Arduino ("DoS attack")}


3d开机号试机号the source code has to be transferred to both arduinos (= both arduinos have the same very same code). if everything has been executed correctly, an arduino’s led is switched on, if the tact switch of the other arduino has been pressed.

Tact switch of Arduino Uno is pressed (background) >> Yellow LED of Arduino Nano is switched on.
Tact switch of Arduino Nano is pressed (background), Green LED of Arduino Uno is switched on.


Control Fairy LED Strings with a Relay Module and an Arduino

3d开机号试机号this tutorial shows how to control so-called “fairy led strings” (also called led strings, fairy lights, fairy leds etc.) with an arduino. the idea is to have multiple fairy led strings that are switched on and off corresponding to a specific pattern. typically, these strings are either powered with a battery pack or with a usb cable/power supply. here, we focus on the usb-powered leds, since they are easier to get working with an arduino. arduinos are normally not able to provide enough power for such fairy stringy by their digital outputs. therefore, we make also use of a relay modules in this tutorial.

List of materials:
– Jumper wires [Search on | ]
– Breadboard [Search on | ]
– Fairy LED strings   [Search on | ]
– Arduino [Search on | ]
– Relay Module   [Search on | ]
– USB terminal adapter (female) [Search on | ]


Fairy LED Strings.

Fairy LED Strings
I don’t know for sure, but fairy LED strings are maybe called fairy LEDs strings, as they look like tiny fairies when watching from some distance. In many stores, they are presented inside a jar which might remind on the fairies of the popular video game series “Zelda” (where fairies are often transported in jars by the main protagonist “Link”).
Normally, fairy LED strings consist of a chain of simple LEDs which are connected via insulated copper wire. In order to make the LEDs more robust, they are wrapped in some sort of dry hot glue.

Seeeduino Nano.

Arduino (Seeeduino Nano)
3d开机号试机号In this tutorial, I make use of a which comes with a nicely red-colored PCB. Additionally, it’s compatible to a conventional Arduino Nano. In contrast to a normal Arduino Nano, it has a USB Type-C connector instead of a USB Mini connector. This might be an advantage if you own more USB Type-C cables than USB Mini cables (imho which are rarely distributed nowadays). In this tutorial, the Seeedunio Nano is used to “store the lightning program” and control the fairy LEDs strings according to this program.

Relay Module HL-545.

Relay module
3d开机号试机号In order to switch on an LED, the Seeeduino must bring 5V to the fairy LED string’s USB connector. To my knowledge, typical Arduinos are only able to provide 40mA via an digital output pin. Normally, this is not sufficient to power a string with multiple LEDs. In order to account for this, we utilize a relay module. A relay module (as used in this tutorial) exists in different variants: supporting 1-, 2-, 4-, 8 ports. In this tutorial, the HL-545 with 4 ports is used to power two fairy LED strings (yellow and blue).

USB Terminal Adapter.

USB Terminal Adapter
Now, the question is how to wire a USB-based fairy LED string to a breadboard / “jumper wire system”. For this use case, a female USB terminal adapter is quite useful. These adapters allow you to plug in an USB cable and, then, have the corresponding signal also on a terminal block. Luckily, jumper wires can be easily connected to the terminal blocks. In particular, we are interested to connect the GND/- and 5V/+ pins of the USB cable to two separate jumper wires.


in this setup exist two 5v circuits. the first one is for powering the fairy led strings. the second one is for powering the arduino and the relay module. it would also be possible to have only one 5v circuit which powers all components.

Wiring schematic.

Source code

the program is very basic since there is no special code for the relay module or for the fairy led strings… it is more or less only setting two output pins. the idea of the program is to perform a little “light show”. in the first phase, no fairy led strings is on. then, only the yellow string is shown. next, only the blue string is shown. finally, both strings are shown. in addition, each phase is shown for two seconds.

in the setup function, digital pin 2 and 3 are declared as output pins. then in the loop function, the “light show phases” are represented by setting the two outputs pin and adding a delay of two seconds. for example, if both leds are set, the output pins are set two low. yes, low is correct as the relay model triggers on low signals!

// (c) Michael Schoeffler 2019, This program shows how to switch on two different "fairy LEDs" by utilizing a relay module. // In particular, the program resembles a small "lighting program":// Both LEDs are off, only first LED is switched on, only the second LED is switched on, both LEDs are switched on.// Each "light mode" shows up for two seconds.void setup() {  pinMode(2, OUTPUT); // Digital pin 2 is an output pin  pinMode(3, OUTPUT); // Digital pin 3 is an output pin}void loop() {  // keep in mind: relay module "switches on" if signal is LOW    // nothing is switched on  digitalWrite(2, HIGH);  digitalWrite(3, HIGH);  delay(2000); // wait for two seconds.  // LED is switched on  digitalWrite(2, LOW); //Fairy LED on digital output 2 is switched on  digitalWrite(3, HIGH);  delay(2000); // wait for two seconds.  // the other LED is switched on  digitalWrite(2, HIGH);   digitalWrite(3, LOW); //Fairy LED on digital output 3 is switched on  delay(2000); // wait for two seconds.  // both LEDs are switched on  digitalWrite(2, LOW);  //Fairy LED on digital output 2 is switched on  digitalWrite(3, LOW); //Fairy LED on digital output 3 is switched on  delay(2000); // wait for two seconds.}

3d开机号试机号if the program is transferred to the seeeduino nano/arduino, the “lighting show” should look like this:

Video tutorial

SunSpec Tutorial Part I: Modbus

this is a three-part tutorial about sunspec, an open specification that aims at increasing the interoperability within the solar and distributed energy industry. the goal of this series is to give an overview of the specification and to demonstrate how it can be used for basic use cases. this part focuses on fundamentals about the modbus protocol which is, at time of writing, the most important communication technology for working with the sunspec specification. the second part gives a brief introduction to sunspec in general. it elaborates on the sunspec information model and its relationship to modbus. the third part is a hands-on tutorial. it shows how to use an esp32/esp8266 to retrieve data from a kostal plenticore hybrid inverter (kostal plenticore plus).

3d开机号试机号this introduction should not be seen as a comprehensive guide for starting with modbus. instead, only aspects are considered that are important for reading the other two parts and, in addition, might be necessary to get a good understanding of sunspec in general.


3d开机号试机号according to the modbus application specification, modbus is the industry’s serial de facto standard since 1979 and enable millions of automation devices to communicate. even though technologies originating from the industrial domain are known to have long lifespans, it is kind of remarkable that modbus has recently been chosen to be sunspec’s main communication protocol. i came across modbus several times during my studies, professional or private life. my personal opinion about modbus is that, on the one hand, appears to be somewhat antiquated, but on the other hand, is also very easy to use. especially when it comes to simply retrieving data without having too many other requirements, the ease of use of modbus can be a major advantage.

When talking about Modbus, one has to specify what exactly is meant: Modbus defines the so-called “Modbus Application Layer” that is implemented for various bus/network types (e.g. EIA/TIA-232 or TCP/IP). In particular, the Modbus Application Layer describes a messaging protocol for client/server communication. In further specifications it is describe how to apply the messaging protocol for a specific bus/network type. For example, the application of the Modbus messaging protocol on TCP/IP (Ethernet) is described in .
3d开机号试机号In this tutorial series, the focus is set to the Modbus messaging protocol over TCP/IP (also called ModbusTCP).

Modbus Protocol (Basics)

similar to many other protocols, modbus is a client/server protocol meaning a single or multiple clients communicate with a server. a client is typically a “user application” (e.g. monitoring application), whereas the server is typically a “device” being monitored (e.g. heat pump with sensor values).

3d开机号试机号the protocol data unit (pdu) of modbus has two fields: “function code” and “data”. the function code field specifies which action to be performed when a message is sent from the client to the server. the data field contains additional data that belong to the function code. for some function codes / actions, the data field is not required and, therefore, contains 0 bytes.

besides the pdu, modbus defines a so-called application data unit (adu). the adu contains and additional address, the pdu and an error check. basically, the adu is a mapping of a message to a specific bus or network type.

<-                    Application Data Unit (ADU)               ->------------------------------------------------------------------| Additional address |  Function code |    Data    | Error Check |------------------------------------------------------------------                     <- Protocol Data Unit (PDU ) ->   

Modbus Data Model

besides the modbus protocol, there exists a specific data model in modbus. the data model distinguishes between discrete inputs, coils, input registers and holding registers. normally, the client send messages (adus) to the server in order to retrieve data that is organized based on the modbus data model. when implementing a modbus server on a device, the developer can decide how to organize the sensor values into the modbus data model. the modbus specification does only restrict the size of the data model elements (1bit or 16bit) and whether a data element is readable or readable/writeable:

Primary tables Object type (size)Type of (r/w)Comments
Discrete InputSingle bitRead-onlyThis type of data can be provided by an I/O system (device).
CoilsSingle bitRead/WriteThis type of data can be alterable by a user application.
Input Registers16-bit wordRead-only This type of data can be provided by an I/O system (device).
Holding Registers16-bit wordRead/Write This type of data can be alterable by a user application.

Accessing data

let’s assume a device organizes it sensor values according to the modbus data model. for example, some sensor values are stored as discrete inputs as they are only “true” or “false” (e.g. light barrier sensors) and some other sensor values are input registers as they have to be represented as numeric values (e.g. temperature sensors). moreover, let’s assume the device has some configuration values that can also be written by a user application. the device would store them into the coils and holding registers data space.

3d开机号试机号if a user application (client) wants to access this data, it has to send a message with a function code. for example, if a coil has to be read, function code 0x01 has to be sent to the device (server). in addition to the function code, the client sends also the starting address and the number of coils to be read (stored in the data frame of the message). if successful, the server sends a response with the same function code, the byte count (length of the coil status) and the coil status (actual values).

the following table shows some of the most important functions codes:

Function codeNameAccess
0x01Read CoilsBit access
0x02Read Discrete InputsBit access
0x03Read Holding Registers16 bits access
0x04Read Input Registers16 bits access
0x05Write Single CoilBit access
0x06Write Single Registers16 bits access

Modbus on TCP

When using Modbus on TCP/IP, clients and servers communicate over an Ethernet network. The default port for Modbus servers is 502. It is also possible that servers listen on an additional port, however, according to the specification, port 502 must always be available (“It is important to note that even if another TCP server port is configured for MODBUS service in certain applications, TCP server port 502 must still be available in addition to any application specific ports“).

the modbus implementation guide (modbus messaging on tcp/ip implementation guide v1.0a) contains many more details on how to communicate modbus over tcp/ip. for the two other two parts of this tutorials series, it is not required to know these further details.

3d开机号试机号in the second part, you will learn more about sunspec and how it is related to modbus (coming soon!).

WS2813 vs. WS2812B + “WS2813 Mini”-based RGB LED Ring Tutorial

the ws2812b from the ws2812 series has been my favorite rgb chip when it comes to projects where lighting in different colors is involved. not so long ago, i got notice that there is a successor on the market for already some time. the new rgb chip is called ws2813, which also comes in different variants (e.g. ws2813a, ws2813b, ws2813c,…). in this post, i want to give an introduction into the new features of the new rgb chip and give a short tutorial about ws2813-based rgb rings.


WS2813B-Mini RGB chip mounted on an LED ring.
WS2813B-Mini RGB chip mounted on an LED ring.

according to the official data sheet of worldsemi, the first version of the ws2813 was introduced in 2017. at the first look, the ws2813 has the same functionalities as its predecessors: it’s a small chip with an integrated multi-color led that can light up in different colors (three primary colors with 256 brightness level →  corresponds to 256*256*256= 16777216 colors). moreover, the rgb chip can be controlled with a single control wire – in addition to the gnd- and 5v power signal. the control wire can also be used for cascading multiple rgb chips in order to form an “led strip” or an “led ring”.

What are the WS2813’s main features compared to the previous versions (e.g. 2812B)?

  • Dual-signal wires: The control wire is basically doubled by introducing an additional input “backup control data signal input” next to the “control data signal input”. As a result, if a single RGB chip of an LED strip get damaged, the damage does not affect the RGB chips to follow.
  • Increase of refresh frequency: Compared to the WS2812 series, the refresh frequency has been increased from 400 Hz to 2000 Hz.

3d开机号试机号fortunately, existing libraries, such as , , can be used to control also ws2813 rgb chips. next, i give a tutorial that shows how to control rgb rings.


my guess is that most people probably make use of rgb chips in form of led strips. alternatively, there are also led/rgb rings on the market. recently, i got hand on two variants of series which come with ws2813b-mini rgb chips. in this tutorial, i want to show how to control such an rgb led ring with an arduino uno.

List of materials:
– Arduino Uno [Search on | ]
– Jumper wires [Search on | ]
– Breadboard [Search on | ]
– RGB LED Ring (my model is Seeedstudio Ultimate RGB LED Ring v1.0)  [Search on | ]

Wiring pin layout of this tutorial.
Wiring pin layout of this tutorial.

Wiring Pin Layout:
The wiring is very simple as only three wires have to be used to connect the Arduino with the LED Ring. I used the “Grove connector” of the LED Ring to make my connections. Grove is a feature available for many components from Seeedstudio. It makes it easier for beginners to connect components, e.g., to an Arduino. Basically, grove users get a shield for their Arduino and then can use standardized connectors to make connections between the components and the shield. Luckily, conventional jumper wires fit very well into the Grove connectors.

regarding the actual wiring, arduino’s 5v pin has to be connected to the vcc pin of the led ring, arduino’s gnd to gnd, and arduino’s digital pin #6 to sig.

3d开机号试机号The program represents a very basic lightning demo for the LED ring. The program “walks over” each RGB chip and sets it to a random color. If it has “walked over” all RGB chips, it starts again and overwrites the existing colors with a new random color.

The program is based on the FastLED library which has to be installed on your Arduino IDE installation (Tools -> Manage Libraries…). After including the header file of the FastLED library, the number of available LEDs has to be configured. The actual number depends on your LED ring type. I added a comment to the code about numbers from LED ring types that I’m aware of. In the setup function, FastLED is initialized. Here, you can simply configure it with type WS2813 since the new RGB chip has already been considered by the developers of FastLED.
In each loop function call, an index is incremented. This index represents the “current” RGB chip that is set with a random color. If the index is greater than the number of available RGB chips on the LED ring, it is set back to zero and the whole procedure starts again.

// (c) Michael Schoeffler 2019,* * This program demonstrates how to use RGB LED Rings. The program "walks over" each LED and sets it to a random color.  * If you are already familiar with programming LED stripes, you will recognize that there is basically no difference. * The code has been written for the Ultimate RGB LED Ring v1.0, but can easily be adapted.  *  */#include "FastLED.h"// some LED numbers that I'm aware of...// Grove - RGB LED Ring (16-WS2813 Mini): 16 LEDs// Grove - RGB LED Ring (20-WS2813 Mini): 20 LEDs// Grove - RGB LED Ring (24-WS2813 Mini): 24 LEDs// Grove - Ultimate RGB LED Ring: 42 LEDs#define NUM_LEDS 42 // add number of LEDs of your RGB LED Ring here#define PIN_LED_RING 6 // digital output PIN that is connected to DIN of the RGB LED Ring#define UPDATE_TIME 250 // each 250ms, a new random color is setCRGB rgb_led_ring[NUM_LEDS]; // color array of the LED RGB Ringunsigned index = 0; // index represents the currently "walked over" LEDvoid setup() {   FastLED.addLeds<WS2813, PIN_LED_RING>(rgb_led_ring, NUM_LEDS); // Change WS2813 to something else, if your RGB LED Ring has a different chipset (e.g. WS2812B instead of WS2813). }void loop() {  rgb_led_ring[index] = CHSV(random8(),random8(),random8()); // we set the color of the LED represented by index  index++; // index is increased, i.e. the color of the LED to the right is set next time.; // state of color array is transfered to RGB LED Ring  if (index >= NUM_LEDS) { // if we "walked over" all LEDs, we start from the beginning again.   index = 0;   }    delay(UPDATE_TIME); // program waits for 250ms}

Programming variant: Two RGB LED Rings
Some time ago, I made a tutorial about WS2812B-based LED strips. Multiple times, I was asked how to apply the program when having two LED strips. If you make use of FastLED, you can just register a second LED strip (or LED ring) to FastLED in the setup function. I changed the previous program in order to be able to control two LED rings. (Ultimate RGB LED Ring with 42 LEDs and RGB LED Ring “16-WS2813 Mini” with 16 LEDs) . Basically, I just copy’n’pasted each line and made slight changes. Regarding the wiring, I connected the GND of the second ring to a GND pin of the Arduino and then I used a mini breadboard to split up the 5V pin of the Arduino in order to draw 5V connections to both rings. As a last step, I connected the SIG pin to Arduino’s digital pin #7.

// (c) Michael Schoeffler 2019,* * This program demonstrates how to use two RGB LED Rings at the same time. For each RGB LED Ring, the program "walks over" each LED and sets it to a random color.  * If you are already familiar with programming LED stripes, you will recognize that there is basically no difference. * The code has been written for the Ultimate RGB LED Ring v1.0, but can easily be adapted.  *  */#include "FastLED.h"// some LED numbers that I'm aware of...// Grove - RGB LED Ring (16-WS2813 Mini): 16 LEDs// Grove - RGB LED Ring (20-WS2813 Mini): 20 LEDs// Grove - RGB LED Ring (24-WS2813 Mini): 24 LEDs// Grove - Ultimate RGB LED Ring: 42 LEDs#define NUM_LEDS_RING1 42 // add number of LEDs of the first RGB LED Ring here#define NUM_LEDS_RING2 16 // add number of LEDs of the second LED Ring here#define PIN_LED_RING1 6 // digital output PIN that is connected to DIN of the first RGB LED Ring#define PIN_LED_RING2 7 // digital output PIN that is connected to DIN of the second RGB LED Ring#define UPDATE_TIME 250 // each 250ms, a new random color is setCRGB rgb_led_ring1[NUM_LEDS_RING1]; // array representing the color layout of the first ringCRGB rgb_led_ring2[NUM_LEDS_RING2]; // array representing the color layout of the second ringunsigned index_ring1 = 0; // index represents the currently "walked over" LED of the first ringunsigned index_ring2 = 0; // index represents the currently "walked over" LED of the second ringvoid setup() {   FastLED.addLeds<WS2813, PIN_LED_RING1>(rgb_led_ring1, NUM_LEDS_RING1); // Change WS2813 to something else, if the first RGB LED Ring has a different chipset (e.g. WS2812B instead of WS2813).   FastLED.addLeds<WS2813, PIN_LED_RING2>(rgb_led_ring2, NUM_LEDS_RING2); // Change WS2813 to something else, if the second RGB LED Ring has a different chipset (e.g. WS2812B instead of WS2813). }void loop() {  rgb_led_ring1[index_ring1] = CHSV(random8(),random8(),random8()); // we set the color of the LED represented by index (first ring)  index_ring1++; // index is increased, i.e. the color of the LED to the right is set next time.  rgb_led_ring2[index_ring2] = CHSV(random8(),random8(),random8()); // we set the color of the LED represented by index (second ring)  index_ring2++; // index is increased, i.e. the color of the LED to the right is set next time.;  if (index_ring1 >= NUM_LEDS_RING1) { // if we "walked over" all LEDs, we start from the beginning again (first ring)   index_ring1 = 0;   }    if (index_ring2 >= NUM_LEDS_RING2) { // if we "walked over" all LEDs, we start from the beginning again (second ring)   index_ring2 = 0;   }    delay(UPDATE_TIME); // program waits for 250ms}


Arduino Tutorial: Making the KMR-1.8 SPI (TFT Display) work!

KMR-1.8 SPI TFT display with a resolution of 128 (height) x 160 (width)

recently, i had the idea to make a digital picture frame—one of these kinds which load images from sd cards and show each image for some time. i was remembering myself that i already own a small tft display, the kmr-1.8 spi, that works out of the box with an arduino uno. when i digged up my kmr-1.8 spi, i realized that it has also an in-built sd card reader. moreover, i looked up the internet and found ready-to-use libraries for the in-built sd card reader as well as showing images on the tft display. for these reasons, i thought making such an digital picture frame will turn out very easy.

3d开机号试机号when i started to implement my first lines of codes and started to connect my arduino uno to the kmr-1.8 spi, i ran into two major problems. first, the colors of my image file did not match to the colors displayed by the kmr-1.8 (red and blue were interchanged). second, my first prototypes stopped to work after about 5 minutes. the application started to freeze and showed the same image forever instead of displaying the next image after a chosen time. 

3d开机号试机号i did some research on the internet and i found out that many people ran into similar problems. the second problem seemed to be caused by some memory leaks in the code. nevertheless, i did not came across any example code that worked out of the box for my setup. therefore, i want to share how i made it work. 

List of materials:
– Arduino Uno [Search on | ]
– Jumper wires [Search on | ]
– Breadboard [Search on | ]
– KMR-1.8 SPI TFT display (width 160px, height 128px)  [Search on | ]
– SD Card Adapter [Search on | ]

Important note:

3d开机号试机号there exists various versions of so-called “1.8 tft displays” from different manufacturers. not all of them are 100% compatible to each other. therefore, if you own a tft display and want to use my tutorial to make it work, please check if your tft display really matches the version i used in this tutorial:

Front of my KMR-1.8 TFT display.
Back of my KMR-1.8 TFT display.

Wiring / Pin Layout:

to make it work, you have to connect many wires between the arduino and the tft display. i created a fritzing file that shows all the wiring:

the wiring is more or less straight forward. keep in mind that the arduino’s 5v pin goes to the vcc pin as well as to the led+ pin. the same applies to the arduino’s gnd pin which goes to gnd and led- of the tft display. arduino’s digital pin #13 goes also to two pins (sck and scl). next, there is a picture of my setup with completed wiring:

Source code:
3d开机号试机号The source code relies on three header files (and libraries): SPI.h (), SD.h () and TFT.h (). Please make sure that all of them are correctly installed before trying out my source code (In Arduino IDE: Tools -> Manage Libraries…).

3d开机号试机号in the introduction of this blog post, i mentioned that i came across two major problems: the colors red and blue were interchanged and my early arduino programs started to freeze after some time. luckily, i was able to fix all issues. the following source code works perfect on my setup. my “digital picture frame” does not require to be restarted after some time (my long-term test lasted about two weeks—and no restart was necessary).

i overcame the first problem by not using the default initialization method (“tftscreen.begin();”) of the tft library. instead, i looked up whats inside the “begin”-method. i found a method called “initr” which has a parameter that allows to perform the initialization for a specific chip. here, the parameter value “initr_blacktab” worked for me as the colors were then shown correctly. in addition, i call the method “setrotation” with parameter value “1” in order to be conform to the default initialization method. in the end, the code for the setting up the tft library object looks like this:

// ...TFTscreen.initR(INITR_BLACKTAB);TFTscreen.setRotation(1);// ...

3d开机号试机号i solved the second problem (application freezes after some time) by avoiding any possible memory leak, i.e. to “free” every bit of memory that was reserved before as soon as it is not needed anymore. therefore, you will find a lot of “close”-method calls as well as some weird string handling. when i wrote the code, i thought i could simplify a few things. however, the memory leak problems came back. so, the code might look weird but it works :)

here is the full source code:

// (c) Michael Schoeffler 2019, <SPI.h>#include <SD.h>#include <TFT.h> #define PIN_SD_CS 4#define PIN_TFT_CS 10#define PIN_DC 9#define PIN_RST 8#define DELAY_IMAGE_SWAP 60000 // each image is shown for 60 secondsTFT TFTscreen = TFT(PIN_TFT_CS, PIN_DC, PIN_RST);void setup() {  // initialize default serial connection to send debug information  Serial.begin(9600);  while (!Serial) {    // wait until default serial connection is fully set up  }    //The following two lines replace "TFTscreen.begin();" => avoids that red and blue (?) are swapped/interchanged  TFTscreen.initR(INITR_BLACKTAB);  TFTscreen.setRotation(1);      TFTscreen.background(255, 255, 255); // prints black screen to TFT display    init_SD(); // function call that initializes SD card}void init_SD() {  // try to init SD card  Serial.print(F("SD card init..."));  if (!SD.begin(PIN_SD_CS)) {    Serial.println(F("ERROR")); // failed    return;  }  Serial.println(F("SUCCESS")); // ok}void loop() {  File dir ="/"); // open root path on SD card  File entry;  char name[16];  bool worked_once = false;  while (entry = dir.openNextFile()) { // iteratively opens all files on SD card.     Serial.print(F("Opened File: "));    Serial.println(;    strcpy(name,; // file name is copied to variable "name"    entry.close(); // After copying the name, we do not need the entry anymore and, therefore, close it.    int filename_len = strlen(name);    if ((filename_len >= 4 && strcmp(name + filename_len - 4, ".BMP") == 0)) { // check if the current filename ends with ".BMP". If so, we might have an image.      PImage image = TFTscreen.loadImage(name); // loads the file from the SD card      if (image.isValid()) { // If the loaded image is valid, we can display it on the TFT.        Serial.println(F("Image is valid... drawing image."));          TFTscreen.image(image, 0, 0); // this function call displays the image on the TFT.         worked_once = true; // we set this variable to true, in order to indicate that at least one image could be displayed        delay(DELAY_IMAGE_SWAP);      } else {        Serial.println(F("Image is not valid... image is not drawn."));        }        image.close(); // image is closed as we do not need it anymore.    } else {      Serial.println(F("Filename does not end with BMP!"));      }  }  dir.close(); // directory is closed  if (worked_once == false) { // if not a single image could be shown, we reconnect to the SD card reader.    Serial.println(F("Warning: Printing an image did not work once! Trying to reinitalize SD card reader."));            SD.end();    init_SD();  }}

3d开机号试机号the code looks for image files (*.bmp) on the sd card and shows each image for 60 seconds. you can change the display time by setting “delay_image_swap” to a new value.

3d开机号试机号important note: the image files on the sd card must be stored as bmp with a resolution of 160×128 pixels (width x height). moreover, long file names and special characters must be avoided.

if everything was done correctly, your arduino-based “digital picture frame” should show the pictures in all their glory. here is an example picture (tractor-like vehicle that i drew together with my son):

Video tutorial:

How to do statistics with an Arduino? (Arduino -> SD card -> R)

in this tutorial it is shown how to do statistics with data that comes from sensors which are connected to an arduino. for this purpose, i use the open source statistic program .  strictly speaking, r is a programming language targeting at statistical computing and graphics. moreover, it has a huge community that works on tons of packages providing all kinds of algorithms. in order to get the data from an arduino into an r i make use of an sd card reader/writer. sensor data (that is captured by the arduino) is written to an sd card, then read by a desktop pc and loaded into r.

the tutorial explains three aspects: (a) setting up an arduino (nano) with sensors and an sd card reader/writer to collect some data, (b) collecting data and transferring it to r, and (c) doing some statistics with the data.

List of materials:
– Arduino Nano [Search on | ]
– Jumper wires [Search on | ]
– Breadboard [Search on | ]
– Ultrasonic sensors [Search on | ]
– MicroSD Card Adapter [Search on | ]
– MicroSD card [Search on | ]
– Helping hand (very optional) [Search on | ]

A (1/2): Setting up an Arduino, some sensors and an SD card reader

3d开机号试机号schematic of the tutorial’s setup.

To be honest, the tutorial’s setup of an Arduino and sensors won’t make any real sense. It fulfills only one purpose: to collect some data that can be used to do statistics. I chose to use two ultrasonic sensors of type HC-SR04. In particular, an Arduino is plugged into the center of a breadboard. One ultrasonic sensor is plugged into the left part of the breadboard and the other sensor is plugged into the right part. As a result, the left sensor measures the distance to the left side and the right sensor measures the distance to the right side. I won’t cover the wiring in detail since I already wrote a tutorial that shows how to connect an HC-SR04 to an Arduino. In addition, I wire an SD card read/writer to the Arduino. Again, I won’t go into details here as I also wrote a tutorial about wiring an SD card reader to the Aruino.

Setup of the tutorial. The ultrasonic sensors measure the distance to the left and right side. The collected data is used to do some statistics.

setup of the tutorial. the ultrasonic sensors measure the distance to the left and right side. the collected data is used to do some statistics.

3d开机号试机号in my previous tutorial about the hc-sr04 ultrasonic sensor, i made use of an approach that uses the pulsein-function. this approach works well if you have only a single ultrasonic sensor in your setup. if you have two ultrasonic sensors that measure the distance at the same time, then this approach does not work anymore. in this tutorial, i make use of interrupts. these interrupts are triggered when the signal on the corresponding pin changes its state. on the arduino uno and arduino nano only digital pin 2 and 3 can be bound to interrupts. therefore, the echo pins of the ultrasonic sensors are connected to digital pin 2 and 3.

A (2/2): Programming

As just mentioned, interrupts are used to measure the distances. Besides that, everything else is similar to the code that was presented in my previous tutorials about the HC-SR04 and Micro SD card reader.
On each loop function call, the distances are measured and then written to the file. Moreover, the old file is deleted on each startup of the Arduino.

// (c) Michael Schoeffler 2018, <SD.h> //Load SD library// Pins of the ultrasonic sensorsconst int pin_echo_left = 2;const int pin_echo_right = 3;const int pin_trig_left = 6;const int pin_trig_right = 7;// variables that to track the duration of the echovolatile long echo_left_start = 0;volatile long echo_left_end = 0;int distance_left = 0;volatile long echo_right_start = 0;volatile long echo_right_end = 0;int distance_right = 0;// variables to write data to sd cardint chipSelect = 4; //chip select pin for the MicroSD Card AdapterFile file; // file object that is used to write the datavoid setup() {  pinMode(pin_trig_left, OUTPUT);  pinMode(pin_echo_left, INPUT);  pinMode(pin_trig_right, OUTPUT);  pinMode(pin_echo_right, INPUT);  attachInterrupt(digitalPinToInterrupt(pin_echo_left), echo_interrupt_left, CHANGE); // only pins 2 and 3 are useable for interrupts on Uno, Nano and Mini  attachInterrupt(digitalPinToInterrupt(pin_echo_right), echo_interrupt_right, CHANGE);  pinMode(chipSelect, OUTPUT);   if (!SD.begin(chipSelect)) { // Initialize SD card    Serial.println("Could not initialize SD card."); // if return value is false, something went wrong.  }    if (SD.exists("stats.csv")) { // if "stats.csv" exists, fill will be deleted in order to gather new data    Serial.println("File exists.");    if (SD.remove("stats.csv") == true) {      Serial.println("Successfully removed file.");    } else {      Serial.println("Could not removed file.");    }  }  // write headers  file ="stats.csv", FILE_WRITE); // open "file.csv" to write data  if (file) { // Next, the headers (first line) of the CSV file is written      file.print("DISTANCE_LEFT");       file.print(",");       file.print("DISTANCE_RIGHT");      file.println();      file.close(); // close file      Serial.println("Headers were written to file!");  } else {    Serial.println("Could not open file (writing).");  }  Serial.begin(9600);}// this function is called by an interrupt on each change of the echo pin of the left sensorvoid echo_interrupt_left() {  switch (digitalRead(pin_echo_left))  {  case HIGH:    echo_left_end = 0;    echo_left_start = micros();    break;  case LOW:    if (echo_left_end == 0) {      echo_left_end = micros();      long duration = echo_left_end - echo_left_start;      long durationOneWay = duration / 2; // divided by two, since duration is a roundtrip signal      // acoustic velocity of air at a temperature of 20°C => ~343.5 m/s      // => 0.03435 cm/us      distance_left = durationOneWay * 0.03435; // distance in cm    }    break;  }}// this function is called by an interrupt on each change of the echo pin of the right sensorvoid echo_interrupt_right() {  switch (digitalRead(pin_echo_right))  {  case HIGH:    echo_right_end = 0;    echo_right_start = micros();    break;  case LOW:    if (echo_right_end == 0) {      echo_right_end = micros();      long duration = echo_right_end - echo_right_start;      long durationOneWay = duration / 2; // divided by two, since duration is a roundtrip signal      // acoustic velocity of air at a temperature of 20°C => ~343.5 m/s      // => 0.03435 cm/us      distance_right = durationOneWay * 0.03435; // distance in cm    }    break;  }}void loop() {    // both ultrasonic are triggered to send an ultrasonic signal    digitalWrite(pin_trig_left, LOW); // turn off the trigger    digitalWrite(pin_trig_right, LOW); // turn off the trigger    delayMicroseconds(3);    digitalWrite(pin_trig_left, HIGH);// prepare to send "trigger" command to module    digitalWrite(pin_trig_right, HIGH);// prepare to send "trigger" command to module    delayMicroseconds(10); // wait for 10us (module sends signal only, if trigger had a HIGH signal for at least 10 us)    digitalWrite(pin_trig_left, LOW); // module sends signal now    digitalWrite(pin_trig_right, LOW); // module sends signal now    delay(1000); // we wait a second... interrupts should be called by now    // next we append the measurements to the CSV file.    file ="stats.csv", FILE_WRITE); // open "file to write data    if (file) {      file.print(distance_left);       file.print(",");       file.print(distance_right);      file.println();      file.close(); // close file      Serial.println("Values were written to file!");      Serial.print("Left:  ");      Serial.println(distance_left);      Serial.print("Right: ");      Serial.print(distance_right);      Serial.println();    } else {      Serial.println("Could not open file (writing).");    }}

B: Collecting data and transferring it to R

Arduino is moved to the left and to the right in order to collect some data.

3d开机号试机号arduino is moved to the left and to the right in order to collect some data.

3d开机号试机号next, some data is collected by simply switching on the arduino and then moving it to the left and to the right for a little while. after some time, the stats.csv file on the sd card should have enough distance values. in particular, the arduino program stores the distances measurements in a so-called comma separated value (csv) format. the first line of the stats.csv file represents the so-called header. the header contains the labels for the data. the next lines contain the actual measurements. most statistics programs offer a functionality to import csv files. moreover, since csv file can be found with slightly different formatting, statistic programs usually have some additional convenience functions to import a csv file. for example, some csvs have headers and others don’t have them. furthermore, some csv files separate the data entries by ‘comma’, others separate by ‘semicolon’.

C: Doing some statistics

so the next step is to plug the sd card from the arduino’s sd card reader to a desktop pc. then, the data from the sd card can be loaded to r. there exist many different graphical user interfaces for r. usually, i use  which makes r accessible especially for beginners. i won’t cover how to install rstudio. you can find more information about the installation on the rstudio website. keep in mind that rstudio is only a user interface for r. besides rstudio, you have also to install itself. moreover, this tutorial does also not cover an introduction to r. if you are not familiar with r, then you might want to take a look at an r tutorial for beginners in order to fully understand this tutorial.

rstudio workspace. in rstudio it is very easy to set the working directory.

If you have installed R (and a graphical user interface), start with loading the file “stats.csv” to your R environment. In R, the environment is a place to store variables. In this tutorial, I set the working directory of R to the folder which contains the “stats.csv”. Typically, user interfaces such as RStudio offer a option for setting the working directory. In order to store the CSV file to the R environment, you have to enter data = read.csv("STATS.CSV"); to the R console. As a result, you should see that a variable “data” has been added to your environment. This variable should contain two variables and some observations for both variables. The number of observation is dependent on how long you took distance measurements with the setup. 3d开机号试机号If you did not set the working directory, then you have to enter the full path to the CSV file into the “read.csv”-function.

Next, we want to calculate the mean values of our distance measurements. This can be done by entering mean(data$DISTANCE_LEFT)and mean(data$DISTANCE_RIGHT)3d开机号试机号to the R console. For the left distance I get 12.13043 and for the right distance I get 13.34783 [cm].

If you know only my mean values, you don’t know whether I actually moved my Arduino or not. I would be also possible that I just placed my Arduino in between the obstacles having a distance of about 12cm to the left and about 13cm to the right. In statistics, you can make use of the standard deviation which gives you some indication about the amount of variations of the observations. More strictly speaking, the standard deviation is the square root of the variance. Maybe you are asking yourself now “What is the variance?”. The variance is the average of the squared differences between each observation and the mean.  In R, the standard deviations of the left and right measurements are calculated by entering sd(data$DISTANCE_LEFT) and sd(data$DISTANCE_RIGHT). The result values are 3.876554 (left) and 7.036326 (right). Normally, one would expect that the standard deviants are about the same for the left and right distance measurements. The differences are a result of a non-symmetrical physical setup, measurement noise, skewed movements of the Arduino etc. In order to check whether both variables are related to each other, a correlation measure can be utilized. The Pearson product-moment correlation coefficient, denoted as r, is such a measure. This coefficient ranges from -1 to 1. A value of -1 indicates that the two variables perfectly disagree, a value of 0 indicates that the two variables are independent, and a value of 1 indicates that the two variables perfectly agree. In R, the Pearson product-moment correlation coefficient can be calculated by entering cor(data$DISTANCE_LEFT, data$DISTANCE_RIGHT). As you can see, the function has two arguments which correspond to the two variables of interest. Applying the function to my data returns 0.7782926. This indicates that the two variables rather disagree. This sound logical because if we move the Arduino to the left, the left distance measurement decreases. At the same time, the right distance measurement increases. If both distance measurements had increased at the same time, the correlation coefficient would be close to +1.

3d开机号试机号while moving the arduino, an obstacle is placed next to the right distance sensor. as a result, the correlation between the sensor data is very low.

Let’s modify our setup. This time, I place an obstacle (mini breadboard) next to the right sensor while moving the Arduino (see picture). Then, I repeat the whole process to get the new data into R.  Instead of storing the data values into the variable “data”, I create a new variable “data2”. The function call for reading the CSV file looks like this: data2 = read.csv("STATS.CSV");.
Next you can find the result values for calculating the mean values, standard deviations as well as the correlation coefficient:
mean(data2$DISTANCE_LEFT)= 11.94737
mean(data2$DISTANCE_RIGHT)= 3.421053
sd(data2$DISTANCE_LEFT)= 3.822066
sd(data2$DISTANCE_RIGHT)= 0.606977
cor(data2$DISTANCE_LEFT, data2$DISTANCE_RIGHT)3d开机号试机号= -0.2054429

3d开机号试机号from looking at the statistics results alone, one might guess that something happened to the right sensor. for example, the standard deviation is very low (0.6…). if an obstacle is in front of the sensor, it will measure – more or less – the same distance value. as a result, the standard deviation is close to zero. moreover, as one sensor measures the actual (varying) distance and the other sensor always measures the same distance, both sensor values are not correlated to each other any more. as a result, the correlation coefficient is close to zero.

you have seen that you can use statistics “to measure what is going on in the real world”. moreover, at least in my opinion, statistics can be as useful as, for example, a multimeter when it comes to finding malfunctions of a system or bugs in you code.

Video tutorial:

Arduino-Tutorial: How to use the RDM630/RDM6300 RFID reader

On the left hand side is the RM6300, which is a very affordable (1-3$) RFID reader. On the right hand side, is the RDM630. The RDM630 is more expensive (10-15$) but also more robust.

3d开机号试机号on the left hand side is the rdm6300, which is a very affordable (1-3$) rfid reader. on the right hand side, is the rdm630. the rdm630 is more expensive (10-15$) but also more robust.

seeedstudio’s rdm630 and the rdm6300 are two different types of rfid readers, even though they often get mixed up. besides the similar names, another reason for the confusion might be that they share the same pin layout and transfer protocol. according to my knowledge, besides the same technical functionality, they have nothing else in common (like same manufacturer, predecessor/successor version, etc.). usually, you should be able to purchase seeedstudio’s rdm630 for about 10-15$ and the rdm6300 for about 1-3$. in my opinion, the price difference can be easily justified as the rdm630 is more robust and allows much higher reading distances.

both readers work at a frequency of 125 khz and enable to read em4100-compatible tags. other tags (for example em4305 tags) do not (or might not) work with these readers.

in this tutorial, i demonstrate how to use the rdm6300 and the rdm630 with an arduino uno. luckily, both rfid readers use the same protocol via a serial connection. as a result, the same source code can be used to make both readers work. therefore, regardless of whether you own an rdm630 or rdm6300, this tutorial should be of use to you if you want to make it work with an arduino.

List of materials:
– Arduino Uno  [Search on | ]
– Jumper wires  [Search on | ]
– Seeedstudio RDM630* [Search on | ]
– RDM6300 [Search on | ]
– 125 kHz tags (check for EM4100 compatibility) [Search on | ]
* If you are looking for an RDM630, please keep in mind that many offers are wrongly labeled. You can find many products that are advertised as “RDM630”, although they are of type RDM6300. Therefore, take a close look at the pictures.

Pin layout RDM630 / RDM6300:

Pin layout of the RDM630. The RDM6300 has the exact same pin layout.

3d开机号试机号pin layout of the rdm630. the rdm6300 has the exact same pin layout.

in total, the rdm630/rdm6300 has 9 pins, where vcc and gnd exist two times. the vcc pin must be connected to a 5v dc. ant1 and ant2 are used to connect an antenna to the board. typically, the rdm630 as well as the rdm6300 already come with an antenna. nonetheless, it is possible to switch the antenna, for example to a custom-made antenna. tx is used to transmit data and rx is used to retrieve data. the led pin can be used to quickly lookup whether an rfid tag was successfully read. if rfid tag is not present, the led pin is at 5v (high). if an rfid was read, the led pin goes to 0v (low) for some moments (yes, it goes from high to low!).

Wiring to Arduino Uno:

Wiring between an Arduino Uno and a RDM6300. The same wiring can be applied to an RDM630.

wiring between an arduino uno and a rdm6300. the same wiring can be applied to an rdm630.

3d开机号试机号in this tutorial, four pins of the rdm630/rdm6300 are wired to the arduino uno. vcc has to be connected to the arduino’s 5v pin (red wire) and gnd to the arduino’s gnd (black wire). the tx pin has to be connected to digital pin #6 (green wire). basically, the rx pin is not required as we do not send data to the rfid module in this tutorial. for the sake of completeness, rx is connected to digital pin #8 (yellow wire). lastly, the antenna is connected to ant1 and ant2 (polarity does not matter).

Example source code:
As mentioned before, the same source code can be used with both models (I tested the code with both models). Basically, when an RFID tag was detected the RDM630/RDM6300 sends a frame with 14 bytes:  head [1 byte], data [10 byte],  checksum [2 byte], and tail [1 byte]. The head (or preamble) is always 0x02. Similarly, the tail is always 0x03. The data field contains ASCII-encoded HEX values. Sometimes, manufacturers tend to split the RFID tag data field into two parts: version and tag. Therefore, depending on your RFID tag type, the first two bytes of data might be the version and the other 8 bytes the actual RFID tag. I considered this in my source code. In order to calculate the checksum from the data field, one has to perform an XOR-operation over all data entries.

// (c) Michael Schoeffler 2018, <SoftwareSerial.h>const int BUFFER_SIZE = 14; // RFID DATA FRAME FORMAT: 1byte head (value: 2), 10byte data (2byte version + 8byte tag), 2byte checksum, 1byte tail (value: 3)const int DATA_SIZE = 10; // 10byte data (2byte version + 8byte tag)const int DATA_VERSION_SIZE = 2; // 2byte version (actual meaning of these two bytes may vary)const int DATA_TAG_SIZE = 8; // 8byte tagconst int CHECKSUM_SIZE = 2; // 2byte checksumSoftwareSerial ssrfid = SoftwareSerial(6,8); uint8_t buffer[BUFFER_SIZE]; // used to store an incoming data frame int buffer_index = 0;void setup() { Serial.begin(9600);   ssrfid.begin(9600); ssrfid.listen();   Serial.println("INIT DONE");}void loop() {  if (ssrfid.available() > 0){    bool call_extract_tag = false;        int ssvalue =; // read     if (ssvalue == -1) { // no data was read      return;    }    if (ssvalue == 2) { // RDM630/RDM6300 found a tag => tag incoming       buffer_index = 0;    } else if (ssvalue == 3) { // tag has been fully transmitted             call_extract_tag = true; // extract tag at the end of the function call    }    if (buffer_index >= BUFFER_SIZE) { // checking for a buffer overflow (It's very unlikely that an buffer overflow comes up!)      Serial.println("Error: Buffer overflow detected!");      return;    }        buffer[buffer_index++] = ssvalue; // everything is alright => copy current value to buffer    if (call_extract_tag == true) {      if (buffer_index == BUFFER_SIZE) {        unsigned tag = extract_tag();      } else { // something is wrong... start again looking for preamble (value: 2)        buffer_index = 0;        return;      }    }      }    }unsigned extract_tag() {    uint8_t msg_head = buffer[0];    uint8_t *msg_data = buffer + 1; // 10 byte => data contains 2byte version + 8byte tag    uint8_t *msg_data_version = msg_data;    uint8_t *msg_data_tag = msg_data + 2;    uint8_t *msg_checksum = buffer + 11; // 2 byte    uint8_t msg_tail = buffer[13];    // print message that was sent from RDM630/RDM6300    Serial.println("--------");    Serial.print("Message-Head: ");    Serial.println(msg_head);    Serial.println("Message-Data (HEX): ");    for (int i = 0; i < DATA_VERSION_SIZE; ++i) {      Serial.print(char(msg_data_version[i]));    }    Serial.println(" (version)");    for (int i = 0; i < DATA_TAG_SIZE; ++i) {      Serial.print(char(msg_data_tag[i]));    }    Serial.println(" (tag)");    Serial.print("Message-Checksum (HEX): ");    for (int i = 0; i < CHECKSUM_SIZE; ++i) {      Serial.print(char(msg_checksum[i]));    }    Serial.println("");    Serial.print("Message-Tail: ");    Serial.println(msg_tail);    Serial.println("--");    long tag = hexstr_to_value(msg_data_tag, DATA_TAG_SIZE);    Serial.print("Extracted Tag: ");    Serial.println(tag);    long checksum = 0;    for (int i = 0; i < DATA_SIZE; i+= CHECKSUM_SIZE) {      long val = hexstr_to_value(msg_data + i, CHECKSUM_SIZE);      checksum ^= val;    }    Serial.print("Extracted Checksum (HEX): ");    Serial.print(checksum, HEX);    if (checksum == hexstr_to_value(msg_checksum, CHECKSUM_SIZE)) { // compare calculated checksum to retrieved checksum      Serial.print(" (OK)"); // calculated checksum corresponds to transmitted checksum!    } else {      Serial.print(" (NOT OK)"); // checksums do not match    }    Serial.println("");    Serial.println("--------");    return tag;}long hexstr_to_value(char *str, unsigned int length) { // converts a hexadecimal value (encoded as ASCII string) to a numeric value  char* copy = malloc((sizeof(char) * length) + 1);   memcpy(copy, str, sizeof(char) * length);  copy[length] = '\0';   // the variable "copy" is a copy of the parameter "str". "copy" has an additional '\0' element to make sure that "str" is null-terminated.  long value = strtol(copy, NULL, 16);  // strtol converts a null-terminated string to a long value  free(copy); // clean up   return value;}

if you execute the source code and hold an rfid tag close to the antenna, the arduino ide’s serial monitor should output something like this:

Video tutorial:

Tutorial: Serial Connection between Java Application and Arduino Uno

in this tutorial, i demonstrate how to build up a serial connection between a java application and an arduino uno. the tutorial is divided into two parts: in the first part, it is explained how to send text (digits) from a java application to an arduino. moreover, the arduino will print out the digits to an lcd module (lcm1602 iic v1). in the second part, basically the same java application is used to send digits to the arduino – but this time with the help of a usb-to-ttl module. as a result, the arduino’s standard serial port can be used by the arduino ide to print the received digits to the serial monitor.

– I added all source codes files to a github repository: 

List of materials:
– Arduino Uno (for Example Part 1&2) [Search on | ]
– LCM1602 IIC V1 / LCD module (for Example Part 1) [Search on | ]
– USB-to-TTL Serial Adapter (for Example Part 2) [Search on | ]

Example Part 1

3d开机号试机号In this part, we have to wire an LCM1602 IIC V1 to the Arduino. The LCM1602 has four pins: VCC, GND, SDA, and SCL. The wiring is straightforward: VCC goes to the Arduino’s 5V. The other three pins have the exact same names on the Arduino: GND goes to GND, SDA to SDA, and SCL to SCL. Have a look at the fritzing file for more details:

Fritzing files that shows how to wire an LCM1602 IIC V1 module to an Arduino Uno.

fritzing files that shows how to wire an lcm1602 iic v1 module to an arduino uno.

Arduino Source Code
3d开机号试机号Next, we have to write some code for the Arduino Uno. Basically, the code just waits for bytes ready to be read by the serial port. If a byte was read, it is printed out to the LCM1602 IIC V1 module.

// (c) Michael Schoeffler 2017, <Wire.h>#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // 0x27 is the i2c address of the LCM1602 IIC v1 module (might differ)void setup() {  lcd.begin(16, 2); // begins connection to the LCD module  lcd.backlight(); // turns on the backlight  lcd.clear();   Serial.begin(9600);  while (!Serial) {    ; // wait for serial port to connect.  }  lcd.setCursor(0, 0); // set cursor to first row  lcd.print("Init done"); // print to lcd }void loop() {  if (Serial.available() > 0) {        byte incomingByte = 0;    incomingByte =; // read the incoming byte:    if (incomingByte != -1) { // -1 means no data is available      lcd.setCursor(0, 0); // set cursor to first row      lcd.print("I received: "); // print out to LCD      lcd.setCursor(0, 1); // set cursor to secon row      lcd.print(incomingByte); // print out the retrieved value to the second row    }  }}

Java Source Code
The Java application uses the to send text to an Arduino Uno via a standard USB connection. I made use of to set up the dependency between my Java project and the jSerialComm library. If you also use Maven for your project, then my POM file might be of use to you:

<project xmlns="" xmlns:xsi="" xsi:schemaLocation="">  <modelVersion>4.0.0</modelVersion>  <groupId>de.mschoeffler.arduino.serialcomm</groupId>  <artifactId>de.mschoeffler.arduino.serialcomm.example01</artifactId>  <version>0.0.1-SNAPSHOT</version>  <name>ArduinoBasicExample</name>  <build>    <sourceDirectory>src</sourceDirectory>    <plugins>      <plugin>        <artifactId>maven-compiler-plugin</artifactId>        <version>3.5.1</version>        <configuration>          <source>1.8</source>          <target>1.8</target>        </configuration>      </plugin>    </plugins>  </build>  <dependencies>    <dependency>     <groupId>com.fazecast</groupId>     <artifactId>jSerialComm</artifactId>     <version>1.3.11</version>  </dependency>  </dependencies></project>

the actual java source code is only a single class with a main method. a serial connection is established. then, five digits (0-4) are written to the serial port. finally, the serial connection is closed:

package de.mschoeffler.arduino.serialcomm.example01;import;import com.fazecast.jSerialComm.SerialPort;/** * Simple application that is part of an tutorial.  * The tutorial shows how to establish a serial connection between a Java and Arduino program. * @author Michael Schoeffler ( * */public class Startup {  public static void main(String[] args) throws IOException, InterruptedException {    SerialPort sp = SerialPort.getCommPort("/dev/ttyACM1"); // device name TODO: must be changed    sp.setComPortParameters(9600, 8, 1, 0); // default connection settings for Arduino    sp.setComPortTimeouts(SerialPort.TIMEOUT_WRITE_BLOCKING, 0, 0); // block until bytes can be written        if (sp.openPort()) {      System.out.println("Port is open :)");    } else {      System.out.println("Failed to open port :(");      return;    }		        for (Integer i = 0; i < 5; ++i) {			      sp.getOutputStream().write(i.byteValue());      sp.getOutputStream().flush();      System.out.println("Sent number: " + i);      Thread.sleep(1000);    }		        if (sp.closePort()) {      System.out.println("Port is closed :)");    } else {      System.out.println("Failed to close port :(");      return;    }      }}

The main important method call is SerialPort.getCommPort(...)3d开机号试机号.  The method has only one argument which has to be the device name of your Arduino Uno. Therefore, it is very likely that you need to change this argument value. You can find out the device name of your Arduino Uno by having a look to the Arduino IDE. In Tools->Port you find all connected devices. In order to upload code to an Arduino, you have to select the correct device name of the corresponding Arduino. Luckily, the same device name is needed by the jSerialComm library. So simply copy the device name from your Arduino IDE to the Java source code.

When you have uploaded the source code to the Arduino and started the java application, you should see that the digits 0-4 appear on the LCM1602 IIC V1 module. Sometimes, I have problems executing this code, if I use cheap Arduino clones. Luckily, it always executes perfectly on my original Arduino Uno from Italy ;)

Example 2

in the second part of this tutorial, the digits (coming from the java application) are printed to the default serial connection of the arduino. as a result, the received digits can be viewed from the arduino ide’s serial monitor (tools -> serial monitor). unfortunately, as a consequence, the standard usb connection cannot be used by the java application since the serial monitor will already catch the serial port as soon as we open it. therefore, we make use of a usb-to-ttl serial adapter.

Typically, a USB-to-TTL adapter has at least four pins: VCC, GND, RX (receive data), and TX (transmit data). As we will use this adapter only to send data from the Java application, we can ignore the RX pin. VCC must be connected to the Arduino’s 5V pin, GND must be connected to the Arduino’s GND pin, and TX must be connected to the Arduino digital pin #5 (also other digital pins can be used).

Fritzing file that shows how to connect a USB-to-TTL serial adapter to an Arduino Uno.

3d开机号试机号fritzing file that shows how to connect a usb-to-ttl serial adapter to an arduino uno.

here you see how my setup looks like (including the serial adapter):

USB-to-TTL serial adapter connected to an Arduino Uno.

3d开机号试机号usb-to-ttl serial adapter connected to an arduino uno.

Arduino Source Code:
3d开机号试机号The Arduino program makes use of a so-called software serial. When a software serial object is initialized, it requires the pin numbers of the receive and transmit pin. As we do not plan to transmit text from the Arduino Uno, we can set the transmit pin to any number. Here, I simply set it to 6.

// (c) Michael Schoeffler 2017, <SoftwareSerial.h> SoftwareSerial sserial(5,6); // receive pin (used), transmit pin (unused)void setup() {  Serial.begin(9600); // used for printing to serial monitor of the Arduino IDE  sserial.begin(9600); // used to receive digits from the Java application  while (!Serial) {    ; // wait for serial port to connect.   }}void loop() {  if (sserial.available() > 0) {    byte incomingByte = 0;    incomingByte =;    if (incomingByte != -1) {      Serial.print("I received: "); // print out to serial monitor      Serial.println(incomingByte); // print out to serial monitor    }  }}

Java source code:
The Java application is basically the same than the one used in part one of this tutorial. The only exception is the device name of the USB-to-TTL device. Conveniently, you can again make use of the Arduino IDE as it will show you the name of the serial adapter, too.

If everything was successfully executed, the serial monitor of the Arduino IDE should show five received digits.

Shows the result of a serial connection between a Java application (Eclipse IDE) and an Arduino Uno (Arduino IDE / serial monitor).

3d开机号试机号shows the result of a serial connection between a java application (eclipse ide) and an arduino uno (arduino ide / serial monitor).

Video Tutorial:


DIY: Y-Adapter Jumper Wire

3d开机号试机号in a lot of situations, it would be useful to have a y-shaped jumper wire to split signals. for example, many variants of the arduino uno have only a single 5v pin. unfortunately, most breakout boards require to connect their gnd and 5v pins to the arduino. if you do not use a breadboard, this can become very annoying due to the very limited amount of only a single 5v pin. moreover, if you want to share a signal with an arduino uno and an oscilloscope, a y-adapter for your pin could come in handy, too.

When I was looking for such Y-shaped jumper wires on shopping portals, I was a bit surprised that I could barely find any offer. Therefore, I decided to make my own Y-shaped jumper wire. If you are new with crimping connectors, it makes sense to have a look at my previous crimping tutorial.

List of Materials and Tools:
– Wire (e.g., 28AWG/0.5mm²) [Search on | ]
– DuPont connector [Search on | ]
– DuPont connector shell [Search on | ]
– Engineer NS-04 Micro nippers [Search on | ]
– Engineer PA-14 Wire Stripper [Search on | ]
– Engineer PA-09 connector pliers [Search on | ]


3d开机号试机号first, i took two wires and cut them to the same length:

next, for each wire, i stripped off the insulation of both ends:

3d开机号试机号then, i did the actual crimping. the main difference between crimping conventional jumper wires and my y-adapter is that two wires are crimped to a single connector on one end:

the remaining other two ends are crimped as usual:

then, the housings must be put on each connector. the connector with two wires just fits to the housing. in case the housing does not slide in easily, i recommend to use the help of a pair of pliers.

and here is the result:

i made four times the same y-adapter type (1x male to 2x female). basically, you can make any type of y-adapter that you want. the only thing you need is a sufficient amount of female- and male connectors, connector housings, and wire. now, i’m able to easily split the signal coming from a breakout board without the need of a breadboard. here is an example where i split the signal of a joystick breakout between an arduino and an oscilloscope:


3d开机号试机号by the way, another possibility of splitting a signal without a breadboard is to use pcb terminals. a pcb’s pin fits perfectly to the female pin of an arduino uno:

Video Tutorial: