User Tools

Site Tools


oak:tutorials:serial_through_arduino

This is an old revision of the document!


Oak: serial communication through an Arduino

The Oak uses a 3.3V serial interface on pins 3 (RX) and 4 (TX). This interface is useful for communicating wth serial-enabled peripheral devices, transmitting debug messages and program data, receiving messages, and flashing firmware. This last use case is an essential component of the Oak factory restore procedure.

One can communicate directly with the Oak through a 3.3V USB/UART adapter (ex: 1, 2) if available, or through a 5V UART with special considerations for level conversion and/or current limiting.

This article describes an alternative method which uses an Arduino as a USB serial converter. This method is particularly convenient for those of us who don't have a 3.3V USB UART on-hand but do happen to have a spare Arduino.

Components used

Part Quantity
Oak with soldered headers 1
Arduino 1
Breadboard 1
Jumper wires 7-10
1 kOhm resistor* 1
2 kOhm resistor* 1

* Note: The resistor values above are not critical.
See Voltage Divider Resistor Selection
and example resistor combinations below.


Jump to:

* Procedure for building the circuit (voltage divider method)


A Word about Counterintuitive Arduino UART Connections

Normally, we connect one device's Tx pin to another's Rx pin, and vice versa. For example, if we were to connect the Oak to a computer, either through a native serial interface or through a USB-TTL dongle, the signal paths would be as follows:

Computer          Oak
--------          ---
UART TX --------> RX
UART RX <-------- TX

or 

Computer         USB-TTL Converter           Oak
--------         -----------------           ---
USB Tx --------> USB Rx -> UART Tx  --------> Rx
USB Rx <-------- USB Tx <- UART Rx  <-------- Tx

However, the Arduino pin labeling does not follow this convention.

We will be operating our Arduino in pass-through mode. We force this mode by shorting the reset pin to ground, which essentially turns off the ATmega main processor and allows direct access to the usb-serial interface via the Arduino's “Tx” and “Rx” pins. A word of caution: in the mode in which we will operate our Arduino, the pins labeled “Tx” and “Rx” act opposite of their labels: the “Rx” pin transmits and the “Tx” pin recieves.

Although counterintuitive, these seemingly backward labels are not an error. The reason for this convention has to do with the Arduino architecture. The Arduino features an internal usb-serial interface which dual purposes as a TTL UART when a user sketch is running, and acts as a pass-through when tri-stated, which is how we plan to use it. The Arduino pin labeled “Rx” mirrors signal received from the computer over USB, while the pin labeled “Tx” mirrors signal to be transmitted to the computer over USB. Wierd, right?

Computer         Arduino                       Oak
--------         --------------------           ---
USB Tx --------> USB Rx -> PIN0 "Rx"* --------> Rx
USB Rx <-------- USB Tx <- PIN1 "Tx"* <-------- Tx

     *NOTE: The Arduino "Rx" pin mirrors signal received over USB, 
      while the "Tx" pin stages signal to be transmitted over USB.
      
    **NOTE 2: this is NOT a wiring diagram.  Connecting the Oak Rx 
      pin directly to the Arduino "Rx" pin is not advised.



Schemes for connecting the Oak to an Arduino

Four methods for connecting an Arduino UART to an Oak are described here:

  1. Using a logic level converter to cut Oak Rx input voltage to 3.3V
  2. Using a voltage divider resistor network to cut Oak Rx input voltage to 3.3V
  3. Using a current limiter resistor
  4. Direct connection (not recommended)

Warning regarding direct connection to 5V UART

I'll leave the below for posterity, but the answer is pretty simple… the ESP8266 (and hence the Digistump Oak, as the ESP8266 is the microcontroller the Oak is based on) has 5v tolerant I/O pins. You should NOT put 5v on the VCC connector, as that WILL kill the Oak, but due to confusion resulting from mistranslation of the original Chinese datasheet which has been cleared up in later releases, and also by the CEO of Espressif (shown below), the I/O pins of the ESP8266 have snapback diodes that protect the chip from over-voltage up to 5.8v, and also from reverse voltages.

Several users (1, 2) have reported success wiring an Oak's Tx/Rx pins directly to an Arduino's 5V UART. The ESP8266 data sheet describes over-voltage protection on all GPIO pins (pg 17+), suggesting the Oak should be able to safely read 5V TTL signal directly. However, it is not well known whether operating in this way degrades the life of the ESP8266. Inserting a resistor (300+ Ohm, typ. 1K) between the Arduino's 5V transmit pin and the Oak's Rx pin will help to limit current into the Oak, although the signal level received by the ESP8266 will still be 5V at the Oak Rx pin, and the same caution regarding the longevity of your Oak still applies. If you choose to connect your Oak to a 5V serial signal, either directly from an external 5V UART or through a current limiting resistor, do so at your own risk.

The recommended solution is to bring the external UART's 5V Tx line down to 3.3V for the Oak, using either a logic level converter if available, or a voltage divider circuit. This recommendation applies whether the external UART is an Arduino or any other 5V UART. The rest of this tutorial focuses on the voltage divider option since it uses common components which many Oak users have on-hand.

Option 1: Using a bi-directional logic level converter (if available)

  Arduino 5V  ----------- HV  Level Converter LV  ---------- Oak 3.3V
  Arduino "Tx"* --------- HV1 Level Converter LV1 ---------- Oak Tx
  Arduino "Rx"* --------- HV2 Level Converter LV2 ---------- Oak Rx
  Arduino Gnd ----------- Gnd Level Converter Gnd ---------- Oak Gnd
  
     *NOTE: The Arduino "Rx" pin mirrors signal received over USB, 
      while the "Tx" pin stages signal to be transmitted over USB.

Option 2: Voltage-divided input line

  Arduino "Tx"* ------------ Oak Tx
  Arduino "Rx"* ---R1--+---- Oak Rx
                       |                  
                       R2                 
                       |
    Arduino Gnd -------+---- Oak Gnd

     *NOTE: The Arduino "Rx" pin mirrors signal received over USB, 
      while the "Tx" pin stages signal to be transmitted over USB.

Your mileage may vary: Current-limited 5V to Oak

  • Limits current into Oak Rx pin, should be safer than direct connection.
  • Leaves input signal at 5V. Impact to ESP8266 life is not well documented.
  Arduino "Tx"* ---------- Oak Tx
  Arduino "Rx"* ----1K---- Oak Rx      <-- 5V input - do so at your own risk
  Arduino Gnd   ---------- Oak Gnd
  
     *NOTE: The Arduino "Rx" pin mirrors signal received over USB, 
      while the "Tx" pin stages signal to be transmitted over USB.

Not recommended: Direct connection

  • Reported to work by multiple users.
  • Leaves input signal at 5V. Impact to ESP8266 life is not well documented.
  Arduino "Tx"* ---------- Oak Tx
  Arduino "Rx"* ---------- Oak Rx      <-- 5V input - do so at your own risk
  Arduino Gnd   ---------- Oak Gnd
  
     *NOTE: The Arduino "Rx" pin mirrors signal received over USB, 
      while the "Tx" pin stages signal to be transmitted over USB.



Voltage Divider Resistor Selection

Since each maker's resistor collection is different, this article describes design considerations which allow flexibility in resistor selection, rather than specifying one set of resistance values. Read on for a brief explanation for selecting resistors, or skip to example resistor combinations.

The resistors are needed to create a “voltage divider.” There are many explanations and tutorials around this topic, which you are encouraged to take a look at, such as the one found on SparkFun. The short summary for the purposes of this tutorial is that the input voltage can be dropped to a desired output like so:

    Vin (input voltage) (5V TTL from Arduino transmit line)
     |
     R1
     |
     +-----o  Vrx (3.3V TTL to Oak Rx)
     |
     R2
     |
    Gnd

If the resistances of R1 and R2 are small relative to the input impedance on the Oak's ESP8266 Rx pin (megaohm range), the voltage at the junction will be similar to that of an ideal voltage divider with no load attached to the junction:

Vrx = Vin * R2/(R1+R2)
  or, solving for R2:
R2 = R1 * Vrx/(Vin-Vrx)

In our case, we need Vrx to be near 3.3V, while Vin will be 5V from the Arduino's Tx pin. We can combine this information with the voltage divider equation above to solve for a relationship between the resistance values that we'll select: R2 = 1.94 * R1. However, the ESP8266 will interpret anything above 2.5V as a high signal, so we have some wiggle room on the resistor relationship. Since we're trying to keep this voltage near the design point of 3.3V (in theory, ESP8266 can accept up to 6V, but potential degradation is not well documented), we'll limit Vrx_max to 3.6V:

  Vrx_min 2.5V   -->   R2 >= R1
  Vrx_max 3.6V   -->   R2 <= R1*2.5   (staying near 3.3V design point; in theory can be higher)
  
  R1 <= R2 <= 2.5*R1

Neat! This gives us a range of resistance values to work with. For example, if we dig into our bucket of resistors and pull out a 1K and call this R1, then R2 can be anything between 1K and 2.5K.

The relationship between R1 and R2 is not enough information to select a pair of resistors. Also keep in mind that R1+R2 needs to be low relative the input impedance of the ESP8266 Rx pin (MOhm range). If the total impedance is too low (<250 Ohm), then you'll risk damaging the Arduino. Typical values for R1 and R2 are in the 1K-50K range.

Example Voltage Divider Resistor Combinations

R1 R2 Range
500 500 - 1.2K
1K 1K - 2.5K
2K 2K - 5K
4K 4K - 10K
8K 8K - 20K
16K 16K - 40K



Building the Voltage Divider Circuit

This tutorial focuses on the voltage division method for connecting the Oak to an Arduino UART. To build this circuit, you'll need to select two resistors per the guidance provided above.


Procedure for Connecting Oak to Arduino with Voltage Divider

  • Jumper the Arduino RESET pin to ground.
  • Connect the Arduino ground line to one row in the breadboard.
  • Connect the Oak ground line to the Arduino ground line via the breadboard.
  • Insert the larger resistor into the breadboard, connecting one lead to ground and inserting the other lead into an unused row.
  • Insert the smaller resistor into the breadboard in series with the larger resistor
    • Connect one lead of the smaller resistor to the open lead from the larger resistor.
      • This connection point will be called the “junction”.
    • Insert the other lead into an open row in the breadboard.
  • Connect the Arduino “RX” pin to the smaller resistor, on the side that is not connected to the junction.
  • Connect the Oak Rx pin to the junction.
  • Connect the Oak TX pin directly to the Arduino Tx pin.
  • If you are using this procedure to restore the Oak, connect pin 2 of the Oak to ground
  • If you are going to power the Oak with the Arduino, connect the 3.3V pin on the Arduino to Vin on the Oak. Otherwise, insert a micro USB cable into the Oak, leaving the other end unplugged
  • Once these connections are complete, both the Arduino and Oak may be powered on

Example

This user's setup uses 220 ohm and 1k ohm resistors for the voltage divider and jumps pin 2 to ground for restoring the Oak:

oak_restore_arduino_serial



Example Sketch for Oak Serial Communication

Using the circuit above (with pin 2 not grounded) with an added potentiometer, we can read a value and send it to the computer via serial communication. Here is the modified circuit:

// define a variable to hold the value
int pot = 0;

void setup()
{

  // start the serial interface
  Serial.begin(9600);

}

void loop() {

  // read the value of pin A0, store it in the variable, "pot"
  pot = analogRead(A0);

  // print that value to the serial interface
  Serial.println(pot);

  // wait 500 milliseconds
  // this just slows down the rate of data being sent
  // so that it's easier to see in the serial monitor
  delay(500);
  
  // since this is within loop(), the program will
  // return to the top and begin again by reading pin A0

}

The code turns serial on with Serial.begin() in the setup() section. Next, it begins to run the loop() section again and again, reading the value of pin A0 (the Oak's only analog pin), storing it in the variable pot. Lastly it is sent over serial with the Serial.print() command to the computer.

Flash the sketch, and then open the Arduino IDE. Set the correct port (Tools → Port) and then open the serial monitor (Tools → Serial Monitor) to begin listening. Make sure the baud rate (lower right hand of the serial monitor) is set to 9600. You should see a string of numbers that changes when you rotate the potentiometer:

Conclusion

You now know how to connect to the Oak via serial through an Arduino if you don't have a USB UART device. If you ever need to restore your Oak, you are now able to do so by following the instructions here, and you now know how to read the values from an input such as a potentiometer or sensor. Do you have other sensors could you try to read? Using microcontrollers often relies on a condition, followed by an action. For example, “if it gets dark outside, turn on my outside lights.” If you were using a photocell to read the brightness outside, what value translates to “dark enough to turn the lights on”? Now you can connect your sensor and read the value from the photocell in real time so you know what to use.

oak/tutorials/serial_through_arduino.1515300891.txt.gz · Last modified: 2018/01/06 20:54 by pfeerick