Category Archives: Development

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 “R”.  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 Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Breadboard [Search on Aliexpress | Amazon]
– Ultrasonic sensors [Search on Aliexpress | Amazon]
– MicroSD Card Adapter [Search on Aliexpress | Amazon]
– MicroSD card [Search on Aliexpress | Amazon]
– Helping hand (very optional) [Search on Aliexpress | Amazon]

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

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.

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, http://www.mschoeffler.de
#include <SD.h> //Load SD library

// Pins of the ultrasonic sensors
const 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 echo
volatile 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 card
int chipSelect = 4; //chip select pin for the MicroSD Card Adapter
File file; // file object that is used to write the data

void 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 = SD.open("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 sensor
void 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 sensor
void 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 = SD.open("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.

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

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 RStudio 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 R 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. 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)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.

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)= -0.2054429

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.

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 Aliexpress | Amazon]
– Jumper wires  [Search on Aliexpress | Amazon]
– Seeedstudio RDM630* [Search on Aliexpress | Amazon]
– RDM6300 [Search on Aliexpress | Amazon]
– 125 kHz tags (check for EM4100 compatibility) [Search on Aliexpress | Amazon]
* 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.

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.

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, http://www.mschoeffler.de
#include <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 tag
const int CHECKSUM_SIZE = 2; // 2byte checksum

SoftwareSerial 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 = ssrfid.read(); // 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.

Notes:
– I added all source codes files to a github repository: https://github.com/mschoeffler/arduino-java-serial-communication
I made also a video tutorial

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

Example Part 1

Setup
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
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, http://www.mschoeffler.de
#include <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 = Serial.read(); // 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 jSerialComm library to send text to an Arduino Uno via a standard USB connection. I made use of Maven 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="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <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 java.io.IOException;
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 (www.mschoeffler.de)
 *
 */
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(...).  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.

Execution
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.

Setup
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.

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.

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

Arduino Source Code:
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, http://www.mschoeffler.de
#include <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 = sserial.read();
    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.

Execution:
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).

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

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 Aliexpress | Amazon]
– DuPont connector [Search on Aliexpress | Amazon]
– DuPont connector shell [Search on Aliexpress | Amazon]
– Engineer NS-04 Micro nippers [Search on Aliexpress | Amazon]
– Engineer PA-14 Wire Stripper [Search on Aliexpress | Amazon]
– Engineer PA-09 connector pliers [Search on Aliexpress | Amazon]

Instructions:

First, I took two wires and cut them to the same length:

Next, for each wire, I stripped off the insulation of both ends:

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:

 

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:

 

 

Example Application: GY-521 module (MPU-6050 breakout board) and Arduino Uno

Example application that shows how to use the raw values of the GY-521 to blink LEDs based on the position of a breadboard.

Example application that shows how to use the raw values of the GY-521 to blink LEDs based on the position of a breadboard.

In a previous blog post, I wrote a short tutorial about the GY-521 module (MPU-6050 breakout board). In addition to the blog post, I made a video tutorial that had basically the same content. At the end of the video tutorial, I presented a small example application that was not described in the blog post. Due to a request, I decided to share the setup and code of the small example which is presented in the following:

The example is very simple. Four LEDs are put in holes at the four corners of a breadboard. In the center of the breadboard is a small breadboard. The GY-521 is used to detect which side of the small breadboard is moved to the top. In order to indicate the “highest side”, two corresponding LEDs are switched on. This example is shown at around 7:15 in the video tutorial.

Wiring:

Fritzing file of the GY-521 example application.

Fritzing file of the GY-521 example application.

Source code:

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de

#include "Wire.h" // This library allows you to communicate with I2C devices.

const int MPU_ADDR=0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.

int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data

#define LED_LB 2 // LED left bottom
#define LED_RB 3 // LED right bottom
#define LED_RT 4 // LED right top
#define LED_LT 5 // LED left top

char tmp_str[7]; // temporary variable used in convert function

char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
  sprintf(tmp_str, "%6d", i);
  return tmp_str;
}

void setup() {
  Serial.begin(9600);
  pinMode(LED_LB, OUTPUT);
  pinMode(LED_RB, OUTPUT);
  pinMode(LED_RT, OUTPUT);
  pinMode(LED_LT, OUTPUT);
  digitalWrite(LED_LB, LOW);
  digitalWrite(LED_RB, LOW);
  digitalWrite(LED_RT, LOW);
  digitalWrite(LED_LT, LOW);
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
}
void loop() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
  Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
  
  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
  accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
  gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
  gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
  gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
  
  // print out data
  Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
  Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
  Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
  // the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
  Serial.print(" | tmp = "); Serial.print(temperature/340.00+36.53);
  Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x));
  Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y));
  Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z));
  Serial.println();
  
  if (accelerometer_x < 1000 && accelerometer_y < -8000) {
    digitalWrite(LED_LB, HIGH);
    digitalWrite(LED_RB, HIGH);
    digitalWrite(LED_RT, LOW);
    digitalWrite(LED_LT, LOW);
  } else if (accelerometer_x < 1000 && accelerometer_y > 8000) {
    digitalWrite(LED_LB, LOW);
    digitalWrite(LED_RB, LOW);
    digitalWrite(LED_RT, HIGH);
    digitalWrite(LED_LT, HIGH);
  } else if (accelerometer_x > 8000 && accelerometer_y < 1000) {
    digitalWrite(LED_LB, LOW);
    digitalWrite(LED_RB, HIGH);
    digitalWrite(LED_RT, HIGH);
    digitalWrite(LED_LT, LOW);
  } else if (accelerometer_x < -8000 && accelerometer_y < 1000) {
    digitalWrite(LED_LB, HIGH);
    digitalWrite(LED_RB, LOW);
    digitalWrite(LED_RT, LOW);
    digitalWrite(LED_LT, HIGH);
  } else {
    digitalWrite(LED_LB, LOW);
    digitalWrite(LED_RB, LOW);
    digitalWrite(LED_RT, LOW);
    digitalWrite(LED_LT, LOW);
  }
  
  // delay
  delay(10);
}

 

 

Arduino Tutorial: HX711 Load Cell Amplifier (Weight Sensor Module) + LCM1602 IIC V1 LCD

In this tutorial, it is shown how to utilize an Arduino Uno, a HX711 breakout board, and a load cell in order to measure weight. Moreover, an LCD module of type LCM1602 IIC V1 is used to display the measured weight.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– HX711 Load Cell Amplifier [Search on Aliexpress | Amazon]
– Load Cell [Search on Aliexpress | Amazon]
– LCM1602 IIC V1 (LCD) [Search on Aliexpress | Amazon]
– Small squared timber and screws

A load cell (left hand side) and an HX711 breakout board (right hand side).

A load cell (left hand side) and an HX711 breakout board (right hand side).

The HX711 is a 24-bit analog-to-digital converter which fits perfectly to weight scale applications. Fortunately, there exist many breakout boards for the HX711. Therefore, it is very easy to use it in combination with a so-called load cell. Load cells are transducers that convert pressure/force into an electrical signal. As the electrical signal has typically only a few millivolts, it has to be amplified. And that’s where the HX711 breakout board comes in:  as it amplifies the weak signal to a few volts so that we can read the signal with the help of an Arduino Uno.

Preparations for Wiring:
In order to easily connect the load cell to the pins of the HX711 module, you can add DuPont connectors to the wires. This step is totally optional. You can use whatever you want to connect the wires to module’s pins. If you use DuPont connectors, keep in mind that such load cells often have thin single-strand wires. I used the help of some solder to attach the thin wires more tightly to their connectors.

Preparation of crimping tools, raw connectors, and shells in order to add DuPont connectors to the wires of the load cell. As a result, the load cell can be easily connected to the HX711 breakout board.

Preparation of crimping tools, raw connectors, and shells in order to add DuPont connectors to the wires of the load cell. As a result, the load cell can be easily connected to the HX711 breakout board.

Preparation of crimping tools, raw connectors, and shells in order to add DuPont connectors to the wires of the load cell. As a result, the load cell can be easily connected to the HX711 breakout board.

Load cell with DuPont connectors.

You will retrieve consistent pressure values from the load cell, if you mount the load cell on something that is solid and heavy. I used a part of an old squared timber for this task:

Load cell mounted on squared timber.

Load cell mounted on squared timber.

Wiring:

Fritzing file that shows how to connect the load cell to the HX711 module. Moreover, it is shown how to connect the HX711 module and the LCM1602 IIC v1 (LCD) module to the Arduino.

Fritzing file that shows how to connect the load cell to the HX711 module. Moreover, it is shown how to connect the HX711 module and the LCM1602 IIC v1 (LCD) module to the Arduino.

First, the load cell is connected to the HX711 module. The load cell has four wires, which must be connected to the first four pins of the HX711 module: Red wire to E+, black wire to E-, white wire to A-, and green wire to A+. The remaining pins, B- and B+, can be used if a second load cell has to be connected to the HX711 module.
Next, the HX711 module is connected to the Arduino Uno. The module’s GND pin must be connected to the Arduino’s GND pin. DT and SCK must be connected to digital pins of the Arduino. In this tuorial, DT is connected to digital pin #4 and SCK is connected to digital pin #5. The remaining pin VCC must be connected to the 5V pin of the Arduino. As the LCM1602 module requires also a connection to the 5V pin, a breadboard is used in-between to split the Arduino’s 5V signal.
As a last step, the LCM1602 module’s SDA and SCL pins must be connected to the corresponding SDA and SCL pins of the Arduino Uno. Moreover, the GND pin must be connected to one of the Arduino’s GND pins and the VCC pin has to be connected to the 5V signal of the breadboard.

Example source code:

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de
#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C library

HX711_ADC LoadCell(4, 5); // parameters: dt pin, sck pin<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
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() {
  LoadCell.begin(); // start connection to HX711
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(999.0); // calibration factor for load cell => strongly dependent on your individual setup
  lcd.begin(16, 2); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
}

void loop() {
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Weight[g]:"); // print out to LCD
  lcd.setCursor(0, 1); // set cursor to secon row
  lcd.print(i); // print out the retrieved value to the second row
}

 

Calibration

The last step is to calibrate the weighing scale. This steps becomes very easy if you have some calibration weights. Unfortunately, I do not have such weights. Therefore, I used an alternative approach to calibrate my weighing scale. First, I grabbed another weighing scale and put something on it (dc motor):

Then I put the dc motor on my weighing scale. Next, I adapted the parameter of the setCalFactor method (see setup function) until the correct weight was shown on my weighing scale. Keep in mind, each load cell and setup needs a different calibration factor. Therefore, it makes no sense to tell you mine.

In order to check whether my calibration factor is working, I did the same thing again with something else (screwdriver):

Overall, I’m satisfied with the accuracy:

Video Tutorial:

Arduino Tutorial: IR Distance / Line Tracing / Line Tracking Sensor (MH Sensor Series/KY-033/TCRT5000)

IR distance sensor (MH Sensor Series, KY-033, TCRT5000).

IR distance sensor (MH Sensor Series, KY-033, TCRT5000).

In this tutorial, it is shown how to use an IR distance sensor with an Arduino Uno. The todays sensor comes in many names: MH Sensor Series, KY-033 (variant with 3 pins), TCRT5000, etc. Moreover, it is often advertised as IR distance sensor, line tracing sensor or line tracking sensor.
In addition to the IR distance sensor, this tutorial makes use of an LCD module called “LCM1602 IIC V1” which is utilized to show sensor values. The main advantage of the LCM1602 IIC V1 is that it is very easy-to-use. For example, it can be controlled by setting up an I2C connection.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Mini breadboard [Search on Aliexpress | Amazon]
– MH Sensor Series [Search on Aliexpress | Amazon]
– LCM1602 IIC V1 (LCD) [Search on Aliexpress | Amazon]

Remark: Some variants of the module type, such as the KY-033, have only three pins. Typically, the A0 pin is missing. Moreover, the D0 pin is often labeled as S. If you own such a variant, this tutorial is still of use to you. Just ignore the part related to the A0 pin.

Pin layout:

The scheme shows how to wire the MH Sensor Series and the LCM1602 IIC V1 to an Arduino Uno.

The IR sensor and the LCM1602 module have only four pins. The GND pins of both modules must be connected to the Arduino’s GND pins. The same applies to the VCC pins which must be connected to the Arduino’s 5V pin. As the Arduino Uno has only a single 5V pin, a mini breadboard is used to “split” the 5V pin. Next, the A0 and D0 pin of the IR sensor must be connected to the Arduino. The A0 pin is the raw analog value (0-1023) of the measured distance between the sensor and an obstacle. In this tutorial, A0 is connected to the Arduino’s A0 pin. The D0 pin is a digital pin that goes to HIGH state if the analog value is greater than or equal to a specific threshold. The threshold can be adjusted by the blue trimpot of the IR distance sensor. Here, D0 is connected to the Arduino’s pin 8.
As a last step, the LCM1602 module’s SDA and SCL pins must be connected to the corresponding SDA and SCL pins of the Arduino Uno.

Example source code

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // initializes the LCM1602 IIC V1 (LCD module)
// 0x27 is the I2C address. This address might be different.

const int IN_A0 = A0; // analog input
const int IN_D0 = 8; // digital input

void setup() {
  pinMode (IN_A0, INPUT);
  pinMode (IN_D0, INPUT);
  lcd.begin(16, 2); // begins connection to the LCD module
  lcd.backlight(); // turns on the backlight
}

int value_A0;
bool value_D0;

void loop() {

  value_A0 = analogRead(IN_A0); // reads the analog input from the IR distance sensor
  value_D0 = digitalRead(IN_D0);// reads the digital input from the IR distance sensor
  
  lcd.setCursor(0, 0); // sets the cursor of the LCD module to the first line
  lcd.print("A0:");
  lcd.setCursor(3, 0); // sets the cursor of the LCD module to the fourth character
  lcd.print(value_A0); // prints analog value on the LCD module
  
  lcd.setCursor(0, 1); // sets the cursor of the LCD module to the first line
  lcd.print("D0:");
  lcd.setCursor(3, 1); // sets the cursor of the LCD module to the fourth character
  lcd.print(value_D0); // prints digital value on the LCD module
  
  delay(1000);
}

 

If the code has been compiled and transmitted to the Arduino Uno, the LCD module should show the distance between the IR distance sensor and an obstacle. Keep in mind that the distance is indicated by a analog value between 0 and 1023. Unfortunately, it is very challenging to convert the analog value to a metric unit of length, such as meter or centimeter. The reason is that the measured analog value is strongly influenced by the obstacle’s material. For example, black surface does reflect far less light than white surface. As a consequence, the measured analog value will differ. Interestingly, this characteristic can be used in order to use the IR distance sensor as a “black or white” detector. This application can often be found in “car assembly kits” where multiple IR sensors are mounted on the undercar. As a result, the car is capable of following a black line that is drawn on white ground.

The following pictures show distance measurements with black and white material. Although the distance is about the same, the measured analog value (A0) differs strongly:

The IR distance sensor measures black material. The analog sensor value is much higher than when measuring white material (A0 = 949).

The IR distance sensor measures white material. The analog sensor value is much lower than when measuring black material (A0 = 525).

Video tutorial

Seven Ways To Supply Power to a Breadboard

When doing prototype work with breadboards for a project, the question comes up “how to power the breadboard?” at the very start. Therefore, a power supply must be chosen that fulfills the requirements of the specific project. There exist a wide range of different alternatives to provide power to a breadboard. Each alternative has different characteristics. In this article, seven alternatives are presented ranging from low-cost USB-based power supplies to AC/DC power supply units.

Alternative 1 (cheap): Microcontroller [Search on Aliexpress | Amazon]

It seems natural to use a microcontroller to power the other components on the breadboard, if you utilize a microcontroller anyway. The advantage is that you require only a single USB cable (or DC plug) to provide power to the microcontroller and all the other components on the breadboard. However, this alternative has at least two drawbacks: First, a typical microcontroller features only very few voltage options. For example, an Arduino Uno has pins for 3.3V and 5V. Second, the current is often limited. For example, when utilizing an Arduino Uno, you can safely draw about 400mA from the 5V pin. In case your microcontroller does not have any output pins to provide power, this alternative is off the table.

 

Alternative 2 (cheap): Breadboard power supply [Search on Aliexpress | Amazon]

Breadboard power supplies are specifically designed for applications involving a breadboard. As a result, they fit perfectly on a breadboard in order to supply power to the “plus and minus lines”.
Moreover, most breadboard supplies have multiple convenience features: For example, the possibility to plug in different power connectors, such as USB or DC plugs. Furthermore, a switch to ‘switch on’ or ‘switch off’ the power as well as an LED to show whether the power supply is enabled or disabled. In addition, you often can choose whether to supply 3.3V or 5V to the “plus and minus” lines.
In comparison to using microcontrollers for powering,  breadboard power supplies often allow you to draw more current than microcontrollers. Unfortunately, most of them are also limited to outpout only 3.3V or 5V. If you require higher voltages, this alternative might not be an option for you.

 

Alternative 3 (cheap): Batteries [Search on Aliexpress | Amazon]
+ battery holder [Search on Aliexpress | Amazon]
+ PCB terminal [Search on Aliexpress | Amazon]

If you already own a pack of batteries, you can also use them for powering. Especially if you own multiple batteries, you can chain them in order to obtain, e.g., a voltage supply having more than 5V. This alternative becomes even better, if you also own a battery holder and a PCB terminal. Then, it becomes very easy to connect the batteries to a breadboard.
For example, if you require more than 5V, you can connect two 3.7V Li-Ion batteries in series to obtain about 7.4V. A major downside of this alternative is that the provided voltage of batteries is dependent on their charging level. As a consequence, this alternative is not suited if a constant voltage is required to power the components. Nonetheless, if you plan to use batteries as power supply for the final version of your project, it might makes sense to use this type of power supply also in the prototype phase.

 

Alternative 4 (cheap): USB DC-DC Step-up Cables [Search on Aliexpress | Amazon]

Compared to connecting batteries in series, utilizing USB DC-DC Step-Up cables is a more convenient alternative to obtain higher voltages. The principle is very simple, these cables have a USB connector on the one end, a DC connector on the other end, and in-between a Step-up module. The Step-up modules transform the 5V coming from the USB connector to a higher voltage, such as 9V or 12V. With the help of a female power jack connector, it is quite simple to bring 9V or 12V to the breadboard. Due to their compact construction, the current you can draw from these Step-up cables is often limited to 750mA or 1000mA.

 

Alternative 5 (reasonably priced): DC Transformer [Search on Aliexpress | Amazon]

In order to draw more power from a 9V or a 12V power supply, a DC transformer can be used. DC transformers are quite common for providing 12V LEDs with power. Alternatively, they can also be used to supply power to breadboards. In comparison to USB DC-DC Step-up cables, they are much more bulky. However, mainly due to their size, they can provide much more power to a breadboard. There exist many different variants, such as 10W DC transformers or 100W DC transformers. Typically when working with breadboards, very high power values are not required. Nonetheless, if, for example, an external power-hungry device has also to be provided by the same power supply as the breadboard, a dc transformer might be a good choice.

 

Alternative 6 (cheap): DC-DC Adjustable Boost Module [Search on Aliexpress | Amazon]

The previous alternatives share the same disadvantage that the provided voltage is typically not adjustable. So-called DC-DC adjustable boost modules overcome this drawback by featuring a potentiometer that can be adjusted by a screwdriver. In particular, the potentiometer controls the provided output voltage. Moreover, many of these modules feature also a USB input. The disadvantage of such module is that they are often limited to 1 or 2 Amperes that can be drawn. Therefore, there range of applications is limited.

 

Alternative 7 (reasonably priced to expensive): DC power supply unit [Search on Aliexpress | Amazon]

The highest degree of flexibility is offered by DC power supply units. In comparison to the other alternatives, this is the most bulkiest and also most expensive alternative. Though, size and prices can differ a lot between different types of DC supply units. The main advantage of DC power supplies is that the provided voltage can be adjusted very precisely. Moreover, they often provide more power than DC-DC Adjustable Boost Modules. If a DC supply unit is chosen as power supply for a breadboard, you should not forget to look out for a plug that connects the DC supply to the breadboard (e.g. “Banana-to-DuPont-connector”).

 

Related video:

Tutorial: How to crimp DuPont/Mini-PV connectors [Engineer PA-09 connector pliers]

This tutorial is about crimping Mini-PV connectors with a generic crimp tool (Engineer PA-09). Mini-PV connectors are also known as DuPont connectors, especially in the context of “breadboard prototyping” where the corresponding wires are often referred to as “DuPont jumper wires”.

You might ask yourself why do people use two different names for the same type of connectors? To put it simple: Mini-PV/DuPont connectors were originally made by a company called Berg Electronics which was part of DuPont Connector Systems. Later, Dupont Connector Systems sold Berg Electronics to Hicks, Muse, Tate, and Furst (private equity company). In 1998, Berg Electronics Corporation was acquired by FCI (Framatome Connectors International, Inc.). Then, FCI was aquired by Amphenol Corporation in 2016. Today, Amphenol Corporation lists the connectors under the name “Mini-PV Basics”.

Mini-PV can be considered a as proprietary connector type. Therefore, there exist also an official tool to crimp Mini-PV connectors. Originally, only female Mini-PV connectors were available. The original crimp tool for these female Mini-PVs is called HT-0095 (HT-95). This tool was sold since the beginning and therefore, you can also find used ones also with a DuPont branding. Today, there exists also an official crimp tool for male connectors: the HT-102. Unfortunately, both tools are very expensive and cost far more than 1000$. Depending on the country you are in, you can find used tools much cheaper on eBay. In this tutorial, I make use of the Japanese PA-09 “generic” connector pliers. Compared to the original HT-95 and HT-102, the PA-09 can be considered as cheap (30-50$). Nonetheless, the crimps made with the PA-09 turn out very suitable for most applications. One more remark: Engineer, the manufacturer of the PA-09 pliers, does not advertise the PA-09 to be compatible with Mini-PV/DuPont connectors. Still, you can find many video, articles and pictures, in which people are using them to crimp Mini-PV and seem also satisfied with the quality.
Of course, the PA-09 is not required for this tutorial, any generic crimp tool that provides sufficient quality can be used. Moreover, it is only shown how to crimp female connectors. Fortunately, you can apply the same procedure in order to crimp male connectors.

List of Materials:
– Wire (e.g., 28AWG/0.5mm²) [Search on Aliexpress | Amazon]
– DuPont connector [Search on Aliexpress | Amazon]
– DuPont connector shell [Search on Aliexpress | Amazon]

Materials required for this tutorial: some wire, DuPont/Mini-PV connectors, and connector shells.

Materials required for this tutorial: some wire, DuPont/Mini-PV connectors, and connector shells.

List of tools that I use in this tutorial:
– Engineer NS-04 Micro nippers [Search on Aliexpress | Amazon]
– Engineer PA-14 Wire Stripper [Search on Aliexpress | Amazon]
– Engineer PA-09 connector pliers [Search on Aliexpress | Amazon]

Tools that I use in this tutorial: NS-04 Micro Nippers, PA-14 Wire Stripper, and PA-09 Connector Pliers (any other set of suitable tools can be used).

Tools that I use in this tutorial: NS-04 Micro Nippers, PA-14 Wire Stripper, and PA-09 Connector Pliers (any other set of suitable tools can be used).

1) The first step is to cut off some wire. The length is totally up to you.

2) Next, the wire must be stripped.

If you are not sure how many insulation you should strip off, then have a look at the next picture. The picture shows were you have to make the crimps. If you use also the PA-09, then you have to make two crimps: the “insulation crimp” and the “wire crimp”. As you can see on the picture, only a small part of the wire has to be stripped off.

3) Then, the first crimp has to made. It is totally up to you, whether to start with the insulation or the wire crimp. I personally prefer to start with the insulation crimp:

4) If the first crimp was successful, the other crimp has to be made. As I started with the insulation crimp, I have to do the wire crimp next.

If you did both crimps, your connector should now look like this:

As you can see, the wire crimp looks fine but the insulation crimp looks a bit sloppy. In particular, the connector has been “drilled” through the insulation. If an original crimp tool was used, the insulation would be coated by the lower part of connector. The “damaged” insulation cannot be avoided if such generic crimp tools are used. The crimp mechanism of the original tools is more complex, e.g., two coils are used to perfectly coat the insulation by the lower part of the connector. Nonetheless, the achieved crimping quality should be sufficient for many applications.

5) The final step is to add a shell to the connector:

6) The same steps have to be applied to the other end of the wire. If everything is executed correctly, the final result should look like this:

Video Tutorial:

 

Another related video about red and black jumper wires:

[Tutorial] How to repair broken USB cables (Micro USB including data transfer)

In this tutorial, I want to show how to repair broken USB cables. In particular, it is shown how to repair a Micro USB cables including the data transfer wires. I made also a video tutorial about this topic. However, in the video, only a charge-only USB cable (with two wires) is repaired. You find the video here:

Just for the sake of completeness — List of Materials:
– Micro USB cable[connector must be broken ;)] [Search on Aliexpress | Amazon]
– Micro USB plug [Search on Aliexpress | Amazon]

Typically, when a USB cable stops to work, the cable and the wires are often still intact. Instead, the USB connector got probably broken. Recently, the connector of one of my USB cables became loose. Moreover, it totally stopped working after some time.

Broken Micro USB plug.

Broken Micro USB plug.

I decided to repair it and ordered a pack of USB connector replacements (also called plugs, tails, or sockets) from Aliexpress. These USB connector replacements are available in many variants (different colors, different lengths, etc.).

My connectors consist of four parts:

Micro USB connector replacement.

Micro USB connector replacement.

1) The first step is to cut off the broken connector:

2) Then, the outer jacket must be removed (e.g. with a wire stripper):

3) Next, the inner wires must be stripped:

4) The cable must be moved through the two parts of the connector replacement’s outer shell:

5) Now, the soldering (almost) starts. Luckily, the wire colors are standardized and used across many manufacturers. Typically, a micro USB cable has five wires: GND (black), 5V (red), Data+ (green), Data- (white), and the (outer) Drain Wire, which should be connected to the GND.

Unfortunately,  different types of USB connector replacements might also have a different layouts. Therefore, have a look at the datasheet or the store’s website to find out which pin has to be connected to which wire. The following picture shows the pin layout for the connectors that I bought:

If you are sure about where to connect which wire, you can start soldering:

6) After the soldering, make sure that the wires are properly isolated. I used some tape for this task as well as for strengthen my solder joint:

7) The last step is to put everything together. I used the help of some pliers to press all parts together:

If you have done all these steps correctly, you should have a working USB cable that can be used for charging as well as for data transfer again: