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.
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.
* Procedure for building the circuit (voltage divider method)
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.
Four methods for connecting an Arduino UART to an Oak are described here:
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 on the right), 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.
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.
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.
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.
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.
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.
R1 | R2 Range |
---|---|
500 | 500 - 1.2K |
1K | 1K - 2.5K |
2K | 2K - 5K |
4K | 4K - 10K |
8K | 8K - 20K |
16K | 16K - 40K |
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.
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:
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:
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.