Nano TTY

Small serial terminal for debugging your robots

Similar projects worth following
Even smaller than the µtty, ntty is the next step in the evolution of small serial displays for debugging robots. Apart from being smaller, it's more convenient to use and has a bigger buffer. And it's also light, so no problem attaching it to your robot while it moves.

Once upon a time I found a Nokia display in my drawer, and figured out I need to try to use it in a project. So I went and built the simplest thing -- a small serial display, that I can connect to my robots for debugging. That's how #µtty was born. It is actually very useful, but a little bit cumbersome to use. So I decided to try and improve the design a little bit.

Nano TTY is following the same idea -- a small screen that lets you see the serial traffic from your project. However, there are some improvements:

  • much smaller and lighter
  • high-contrast OLED display
  • fast, smooth scrolling, using a scroll wheel
  • large scroll buffer

There may be further improvements, depending on how well this goes, but this is the minimum plan.

  • 1 × 128x32 OLED SPI Display
  • 1 × Arduino Pro Mini 3.3V
  • 1 × Rotary Encoder
  • 2 × Buttons

  • First Mock of the Interface

    deʃhipu04/15/2016 at 16:15 0 comments

    Now that I have all the parts, it's time to put this thing together. I had some Arduino Pro Mini that I tried to modify into a "postal stamp" castellated module, by cutting its edges. That didn't work very well, and it went to my junk box. Today I fished it out from there, removed the LED and reset button, cut off that part entirely, and glued to the back of the OLED module. The encoder got glued next to it, through some kapton tape, to not short the OLED module's pins. A pin header on the ftdi port of the arduino and that's it... at least mechanically.

    I'm not very proud of doing this to the poor Pro Mini, but hey, recycling!

    Next I got the code for scrolling and for encoder together, and made this quick mockup of how it's supposed to work when it's ready:

    It looks like it's working, but don't be fooled. It's only scrolling one way, and pausing to wait for the encoder. No real buffer scrolling yet, that has to be implemented. But it's a start, and it's actually quite convenient.

  • Encoders

    deʃhipu04/15/2016 at 14:01 1 comment

    The encoders arrived today, and I actually had to take a moment to read about them to understand how they work. Those are EVQWKA quadrature encoders, with an additional button activated by pressing on the wheel -- which makes them perfect as an interface for all sorts of menus or scrolling:

    You can easily google for a datasheet for these, which will give you all the dimensions and the pinout. But it doesn't say anything about the protocol used. Turns out that the protocol is so standard, that nobody even mentions it anymore in the datasheets.

    Inside of them there is a star-shaped contact, and two contacts that touch the prongs of the star. When you rotate the wheel, the star rotates too, and touches the two contacts. The order in which the contacts are touched tells you the direction of rotation. That's it. This particular model has one pring per "click", so you will get 10, 00, 01, 11 on rotation one way, and 01, 00, 10, 11 on rotation the other way. You can easily detect those with the pin interrupts in Arduino, but I choose to use a library from

    It works flawlessly. Now to program and assemble the whole thing...

  • Smooth Scrolling on a SSD1306

    deʃhipu03/25/2016 at 13:44 3 comments

    The OLED display that I'm using doesn't have much room in it -- only 4 lines with 21 characters in each. That means that to be useful and convenient, it has to have good scrolling. For the scrolling to be fast and smooth, it's best to implement it in hardware.

    Luckily, the SSD1306 supports vertical scrolling by using the SSD1306_SETSTARTLINE command, which basically tells it where it should start reading its image buffer. Since the buffer wraps around, that lets us scroll it pixel-by-pixel. Neat.

    The second piece of the puzzle is that the display I have is 128×32 pixels, and that chip was made for 128×64 pixels display -- so I have twice the amount of buffer space than the screen. I can do double buffering and other tricks!

    First I tried to use the display with the Adafruit SSD1306 library library in I²C mode, but I couldn't quite get it to work. Turns out that the breakout I have uses SPI not I²C, even though the pins are labeled SCL and SDA... Turns out that SCL is simply just SPI SCK, and SDA is MOSI. There are also DC and RST pins, which actually gave me a hint that this is not I²C. Madness.

    Anyways, after playing with that library a little bit, I started to look for something more efficient, and found the SSD1306Ascii library, which only does text output, but allows you to use custom fonts. Exactly what I need. It also has relatively small memory footprint, which leaves more room for my serial buffer.

    I only needed one small hack. In order to get access to the whole image buffer, I needed to trick the library into thinking that I actually have 64 rows of pixels, not 32. Fortunately, you pass a screen definition to it at initialization time, so that was trivial. Several hours of playing with the commands gave me this simple scrolling demo:

    With this simple code:

    #define OLED_RST 8
    #define OLED_DC 9
    #define OLED_CS -1
    #include <SPI.h>
    #include "SSD1306Ascii.h"
    #include "SSD1306AsciiSpi.h"
    SSD1306AsciiSpi oled;
    // A version of the Adafruit128x32 display with 64 lines of buffer.
    static const DevType MEM_TYPE Adafruit128x32x64 = {
        Adafruit128x32init, sizeof(Adafruit128x32init), 128, 64, 0
    void setup() {
        int scroll = 0;
        oled.begin(&Adafruit128x32x64, OLED_CS, OLED_DC, OLED_RST);
        for (int line = 0; line < 20; ++line) {
            oled.print("Line ");
            if (line >= 4) {
                for (int i = 0; i < 8; ++i) {
                    oled.ssd1306WriteCmd(SSD1306_SETSTARTLINE | scroll % 64);
            } else {
            if (oled.row() >= 7 && scroll >= 32) {
            if (scroll >= 64) {
                scroll = 0;
    void loop() {}
    Next, I will try to get the encoder to work, so that I can do the scrolling with a convenient scroll wheel. Unfortunately, I'm still waiting for the encoder to arrive, so that will be some time later.

View all 3 project logs

Enjoy this project?



Lorenzo Egli Grandi wrote 02/09/2017 at 05:14 point

Hello, where to buy those encoders with push button? Love them.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates