NanoPi Duo

The FriendlyArm NanoPi Duo turned up for me today – well, in fact, more than that, a complete kit comprising motherboard, heatsink, SSD and more turned up – read all about it below:


So the NanoPi Duo comes in 2 flavours – 256MB and 512MB of RAM. For my purposes I have here the 512MB verson as a preliminary test suggested that “the script” may not be that happy with a 256MB device – depending on your requirements that may or may not apply.

The board itself handles a microSD (not supplied) and operating system images are readily available from the Friendlyarm site. I’ve included a WIKI link which has all of that and more.

This board is somewhat different to the rest of the FriendlyArm range, being intended (I assume) as a small breadboard-compatible control board (about the same size as some of the ESP-32 boards around right now), running on WIFI. It is cheap and it is very small. What they have done however is made full hardwired Ethernet, 4 USB ports, microphone and even a 64GB SSD drive option available on a base board which you can purchase separately or as part of a complete (more cost-effective) kit.

So for example if you have a need for a number of minimal embedded Linux controllers – then the development kit and a number of DUOs might be the way to go.

In the large photo above you see the baseboard which appears to fit into a Raspberry Pi case, the slim DUO plug-in board in the centre and to the right that square board is the 64GB SSD drive. The microphone and the debug serial connector are hidden underneath. Below, you see the Duo itself.

tmp53DI plugged everything together and flashed a microSD drive with FriendlyArm’s UbuntuCore image – “Ubuntu 16.04.2 LTD 4.11.2” to be precise.

As I could not be bothered to plug in the serial I used Advanced IP Scanner on my PC to seek out the IP address which as it turns out was  SSH, root and pi access are already set up as is the case with the other FA boards (I wish others would do that – some do, some don’t) and so WinSCP quickly connected to the board (using hardwired Ethernet for now) and as usual I immediately changed the passwords.

There is no video out on this board and hence no desktop.  Everything is done via the command line – or of course once you’re all set up with programs, possibly via a web interface – but it is all very familiar to those who’ve used Debian or Ubuntu and not LOT different to a Raspberry Pi command line (unsurprisingly).

All of the login information and how to set up wifi is conveniently located in the slip of paper that comes with the board, incidentally, along with other useful information – but the major source of information is their WIKI. – I checked the command for WIFI and sure enough both of my WIFI access points showed up with decent signals. For setup however where possible I prefer to use hardwired Eithernet.

I failed to find information on using the SSD – I would have expected to see something in the menu of npi-config (their own command-line config program) – but nothing.  I looked briefly on the web – nothing. Please do note however that the SSD is not a standard fitting so I may be looking in the wrong place.

The base board is kind of self-documenting as on the underside are all the pin-outs clearly marked.

Incidentally (and I’d never noticed this before) – once you’ve installed Ubuntu, FA have installed NanoPi-Monitor at port 8888 which in a browser gives you a nice overview of the processor.  It has a couple of minor bugs which I’ve reported. It looks like simply a modified RPI-Monitor.


I started running “the-script” to install my stuff on the board, starting temperature 50c and after 1hr 27 minutes the temperature was 60c (I’ve not mounted the heatsink).  I suspect this is because the H2+ isn’t the fastest and I’m using an ancient SD card I happened to have lying around as I plan to immediately move everything to SSD.

All seemed well as the script appeared to run without issue… however – after a reboot it became obvious that the one thing which would not run – was Node-Red.

Serial, SQLITE and Orange Pi GPIO npm modules would not load up properly – bearing in mind that these are part of the standard package and have been for some/.  I tried re-installing the modules – and the installs went ok – but Node-Red would not accept them.

As these always work, at this point both Antonio who’s been following this and myself are at a loss as to why this is happening – more on this as things develop.

For reference - here's Node-Red starting up with this installation.

[pcsh lang="bash" tab_size="4" message="" hl_lines="" provider="manual"]

pi@duo:~$ node-red
26 Sep 21:00:58 - [info]

Welcome to Node-RED

26 Sep 21:00:58 - [info] Node-RED version: v0.17.5
26 Sep 21:00:58 - [info] Node.js  version: v6.11.3
26 Sep 21:00:58 - [info] Linux 4.11.2 arm LE
26 Sep 21:01:00 - [info] Loading palette nodes
26 Sep 21:01:25 - [info] Dashboard up and running
26 Sep 21:01:33 - [info] Dashboard version 2.5.1 started at /ui
It looks like serialport didn't compile properly. This is a common problem and its fix is well documented here https://
The result of requiring the package is:  undefined
26 Sep 21:01:37 - [warn] ------------------------------------------------------
26 Sep 21:01:37 - [warn] [rpi-gpio] Info : Ignoring Raspberry Pi specific node
26 Sep 21:01:37 - [warn] [Orange Pi] Error: Could not locate the bindings file. Tried:
 → /home/pi/.node-red/node_modules/epoll/build/epoll.node
 → /home/pi/.node-red/node_modules/epoll/build/Debug/epoll.node
 → /home/pi/.node-red/node_modules/epoll/build/Release/epoll.node
 → /home/pi/.node-red/node_modules/epoll/out/Debug/epoll.node
 → /home/pi/.node-red/node_modules/epoll/Debug/epoll.node
 → /home/pi/.node-red/node_modules/epoll/out/Release/epoll.node
 → /home/pi/.node-red/node_modules/epoll/Release/epoll.node
 → /home/pi/.node-red/node_modules/epoll/build/default/epoll.node
 → /home/pi/.node-red/node_modules/epoll/compiled/6.11.3/linux/arm/epoll.node (line:1)
26 Sep 21:01:37 - [warn] [In] Error: Could not locate the bindings file. Tried:
 → /home/pi/.node-red/node_modules/epoll/build/epoll.node
 → /home/pi/.node-red/node_modules/epoll/build/Debug/epoll.node
 → /home/pi/.node-red/node_modules/epoll/build/Release/epoll.node
 → /home/pi/.node-red/node_modules/epoll/out/Debug/epoll.node
 → /home/pi/.node-red/node_modules/epoll/Debug/epoll.node
 → /home/pi/.node-red/node_modules/epoll/out/Release/epoll.node
 → /home/pi/.node-red/node_modules/epoll/Release/epoll.node
 → /home/pi/.node-red/node_modules/epoll/build/default/epoll.node
 → /home/pi/.node-red/node_modules/epoll/compiled/6.11.3/linux/arm/epoll.node (line:1)
26 Sep 21:01:37 - [warn] [arduino] Missing serialport dependency
26 Sep 21:01:37 - [warn] [serialport] Error: Could not locate the bindings file. Tried:
 → /home/pi/.node-red/node_modules/serialport/build/serialport.node
 → /home/pi/.node-red/node_modules/serialport/build/Debug/serialport.node
 → /home/pi/.node-red/node_modules/serialport/build/Release/serialport.node
 → /home/pi/.node-red/node_modules/serialport/out/Debug/serialport.node
 → /home/pi/.node-red/node_modules/serialport/Debug/serialport.node
 → /home/pi/.node-red/node_modules/serialport/out/Release/serialport.node
 → /home/pi/.node-red/node_modules/serialport/Release/serialport.node
 → /home/pi/.node-red/node_modules/serialport/build/default/serialport.node
 → /home/pi/.node-red/node_modules/serialport/compiled/6.11.3/linux/arm/serialport.node (line:6)
26 Sep 21:01:37 - [warn] [sqlite] Error: Cannot find module '/home/pi/.node-red/node_modules/sqlite3/lib/binding/node-v
26 Sep 21:01:37 - [warn] ------------------------------------------------------
26 Sep 21:01:37 - [info] Settings file  : /home/pi/.node-red/settings.js
26 Sep 21:01:37 - [info] User directory : /home/pi/.node-red
26 Sep 21:01:37 - [info] Flows file     : /home/pi/.node-red/flows.json
26 Sep 21:01:37 - [info] Creating new flow file
26 Sep 21:01:37 - [info] Starting flows
26 Sep 21:01:37 - [info] Started flows
26 Sep 21:01:38 - [info] Server now running at


You will note in the above that the serial issue is well known (apparently) so off I went to the GIT repository and one of the options for install was this..

sudo npm install serialport --unsafe-perm --build-from-source

I did this in the .node-red directory – where I install all my nodes – and, well, how can such a simple thing take SO MUCH compilation.. however – it no longer gripes about serial and when I short serial in and out together on the baseboard – and run a debug into the serial in mode in Node-Red and attach the serial out node to a debug – it all works just as you’d expect.  In the actual DUO the SECOND serial port is available – but that is not brought out to the base board.


I seemed to be getting no-where with Node-Red (everything else in the script works – and Node-Red itself did after a second successful attempt to install the I2c code – leaving only the stuff you see above not working – but not stopping Node-Red coming up.

To keep from getting depressed (or possibly make things worse) I decided to try to get the SSD working – it looks like SDA and so I reasoned it might act like any other hard drive. It did. I used the code here  to transfer the data (copy) to the SSD and set it up as the main drive – it worked a treat and I’m now doing the remainder of my experimenting on the hopefully faster SSD.  Of course – booting for now is still done via the original SD – but that’s no big deal (though I’d much rather do away with it altogether). FriendlyArm intended that people would use this for data only as clearly the DUO on it’s own has no SSD – but hey – I like to push things.


With serial working I tried removing the rpi-gpio node – Node-Red ignored me but that’s no problem as it ignores the node anyway… however right now I am left with no Orange Pi node (which works on other similar boards and showed no issues on install) and no sqlite3 node even though SQLITE is actually running. Again no apparent issues on installing the node.

I pondered at this point if I might be using too early a version of node for some reason – I checked and it was version 3.x – so a quick update to version 5 and I tried installing SQL again – I could see an uninstall and reinstall going on – all looked well. I saw this time a message to say that pre-built binaries were not available – falling back to source compile with node-gyp… that all looked well though it took some time to compile.

BAD idea – now all the nodes that DID work – don’t… I tried re-running the script at this point – but it was too late.  Thankfully having put the whole lot onto SSD – I still had the original on the SD!

At this point I had the Orange Pi node (which isn’t for Orange Pi) and the SQLITE node not working…

I really stumbled on a solution – I can’t really take credit for it. I noted that elsewhere rather than install sqlite – some had installed sqlite3

npm install sqlite3

Well, blow me it worked.  I dropped the SQLITE node into Node-Red and passed a query to it – and it worked. 

Now down to one node that does not work – sadly it’s an important one as this is how to access GPIO..not that there are many GPIO pins on this board available….

Well, it turns out that if you run node-red manually (node-red-stop  then just node-red) something called epoll was missing.  In the Node-Red directory I ran:

npm install epoll

And despite an error in the install – the next time I ran Node-Red – the errors went away. But would it work?

Well, it probably would but this was a pivotal moment – one in which I realised… the DUO doesn’t actually HAVE any IO pins – well, not if you’re using I2c etc.. there just are not any IO lines left!!! Well, there is one – IOG11 – but that said it was locked. It probably would have been easier if I’d investigated this earlier.

At this point – there was only one solution – my Nano peripheral – would the I2c work?

sudo i2cdetect –y 0

Well, that kind of worked – but slowly – I reasoned that for some reason they didn’t put pullup resistors on the board… I plugged in one of my OLED displays with pullups and voila – device 3c showed up. Off I went to install the driver. I used the same code I used for the NEO2.  Aside from changing the location of the thermal zone from 1 to 0, it worked a treat!

On the subject of serial - here’s a question I’ve never really resolved – and I’ve come across this before on similar boards..  Tie the serial in and serial out together – and you can send info out – and have it come back in – totally reliably. However, with the two connected together, sometimes when rebooting – the board does not come out of reboot. Remove the link and try again and the board reboots – does anyone have a definite reason for this? I’ve seen this on other boards…. 


Well, that was hard work – but I got there in the end and it is all documented here… for you to decide whether this is financially worthwhile but I think it is very cute and now I have a working setup I can see the little DUO ending up in the odd project. For now I’m enjoying the 64GB SSD!

tmp4D6EOh – and though I’ve not tested it yet, see TKAISERs comments below – might be a way to squeeze more speed out of this little board.

Talking of which – here’s a screenshot from the SSD


34 thoughts on “NanoPi Duo

        1. The xpt2046 is the resistive touch controller (which I support in that library). The display controllers that it supports are the ST7735 (128x160), ILI9341 (240x320) and HX8357 (320x480). I added my own GPIO wrapper functions which use the /sys/class/gpio driver and have pin translations for a bunch of boards from Orange Pi, Raspberry Pi and NanoPi.

    1. I was able to briefly get composite video out working on the NanoPi-Duo. I used a working OrangePi Zero sdcard (same CPU). It booted up and worked for a few minutes, but then overheated and hung. I'm going to try the latest Armbian nightly build for the OPZ next. I couldn't find any documentation from FriendlyElec on how to enable video out (it's disabled by default). Anyone know how to do it from a FriendlyElec Linux build?

  1. Wrt 'NanoPi-Monitor' this is just a normal RPi-Monitor installed by default using Armbian's templates for H3 boards I created already ages ago but FriendlyELEC forgot to include the daemon that is necessary to run in the background for some data collection. Same with the motd stuff (the information you are provided with when you log in). Also taken from Armbian but an old and inefficient version that wastes too much time on every login. And it would be great if FriendlyELEC would also keep up with other settings since currently their OS images miss proper so called IRQ affinity settings (all interrupts are processed on the first CPU core).

    It should be noted that Ethernet can also be used without the Shield (you just need a MagJack, see the photo in link below) and there's 16 Mb SPI NOR flash on the board to store at least a bootloader (so 'SD card free' operation with the shield is possible as soon as the bootloader is put into the SPI flash and the operating system resides on any attached USB storage, an mSATA SSD being one example).

  2. Wrt' hopefully faster SSD: no need to hope, just test it! Please! 🙂

    apt install iozone3 smartmontools
    cd $HOME
    iozone -e -I -a -s 100M -r 4k -r 16k -r 512k -r 1024k -r 16384k -i 0 -i 1 -i 2
    smartctl -d sat -x /dev/sda

    And then please copy all of the output to an online pasteboard service. Thank you!

      1. Thank you but smartctl output is missing (I'm interested in this the most since I don't think SMART readouts are trustworthy) and the iozone test must have happened on the SD card since numbers are way too low for any SSD out there. I assumed you transferred your installation already over to the SSD, true?

  3. Here you go - at the time I WAS on the SD - but SDA is definitely the SSD - and I copied your info directly!

    Here's the output of Smartctl

    and here is a rerun of iozone - done now while I'm actually sitting on the SSD...

    Would appreciate a couple of headline figures when you've had a chance to read... that software looks like it might be useful for comparison but I could not make head nor tail of most of it.

    1. Thanks a lot! Yes, this must be now on the SSD which is bottlenecked by the USB2 connection and most probably also insufcient so called cpufreq settings. How does the output of

      cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

      looks like? If something different than performance you could give it another try after doing a

      echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

      Most probably then numbers increase (max throughput from 32 MB/s to maybe 38MB/s but the random IO performance especially with small block sizes might benefit even more).

      'Performance' as expected bottlenecked by USB2 and random IO performance at least with FriendlyELEC's settings not that great especially compared to your SD card which looks like a very good one (SanDisk Extreme Pro/Plus? Samsung EVO/EVO+?)

      Based on the firmware version 'P0831A' the SSD should be based on a Silicon Motion SM2246XT controller (at least I found some reports about failing KingSpec and KingDian SSDs with this firmware version which all mentioned SM2246XT) and at least thermal readouts seem not to be faked (common problem with cheap SSDs from China). Well, since I deal with data losses for a livng I only trust in certain SSD brands anyway 🙂

      The readings on both controller and memory chips would be interesting.

      1. No problem.

        So - for your CAT question - "ondemand" is the output.

        I'll try changing that later, right now I have bigger fish to fry, despite my best attempts which include getting the serial node to work in Node-Red, I still have two bits of code which are simply not having it....

        Node-Red is running but the Orange Pi (it's not really Orange Pi) GPIO node and the SQLITE node are not playing ball..

        27 Sep 13:42:33 - [warn] [Orange Pi] Error: Could not locate the bindings file. Tried:
        → /home/pi/.node-red/node_modules/epoll/build/epoll.node
        → /home/pi/.node-red/node_modules/epoll/build/Debug/epoll.node
        → /home/pi/.node-red/node_modules/epoll/build/Release/epoll.node
        → /home/pi/.node-red/node_modules/epoll/out/Debug/epoll.node
        → /home/pi/.node-red/node_modules/epoll/Debug/epoll.node
        → /home/pi/.node-red/node_modules/epoll/out/Release/epoll.node
        → /home/pi/.node-red/node_modules/epoll/Release/epoll.node
        → /home/pi/.node-red/node_modules/epoll/build/default/epoll.node
        → /home/pi/.node-red/node_modules/epoll/compiled/6.11.3/linux/arm/epoll.node (line:1)
        27 Sep 13:42:33 - [warn] [In] Error: Could not locate the bindings file. Tried:
        → /home/pi/.node-red/node_modules/epoll/build/epoll.node
        → /home/pi/.node-red/node_modules/epoll/build/Debug/epoll.node
        → /home/pi/.node-red/node_modules/epoll/build/Release/epoll.node
        → /home/pi/.node-red/node_modules/epoll/out/Debug/epoll.node
        → /home/pi/.node-red/node_modules/epoll/Debug/epoll.node
        → /home/pi/.node-red/node_modules/epoll/out/Release/epoll.node
        → /home/pi/.node-red/node_modules/epoll/Release/epoll.node
        → /home/pi/.node-red/node_modules/epoll/build/default/epoll.node
        → /home/pi/.node-red/node_modules/epoll/compiled/6.11.3/linux/arm/epoll.node (line:1)
        27 Sep 13:42:33 - [warn] [sqlite] Error: Cannot find module '/home/pi/.node-red/node_modules/sqlite3/lib/binding/node-v48-linux-arm/node_sqlite3.node' (line:5)
        27 Sep 13:42:33 - [warn] ------------------------------------------------------

        When I get those sorted out - and stick the heatsink on (currently getting up to 60c at times, don't really want to push it too far) I'll check out that potential improvement.

        You asked for "readings on both controller chips and memory chips" - you're assuming too much knowledge - give me lines of code to punch in and I'm happy to do it while I'm sitting here.

        1. Since you have quite some influence on FriendlyELEC you should ask them to copy this piece also from Armbian:

          (improves IO performance on all their boards compared to running 'ondemand' with default settings and is even prepared for their octa-core devices too -- 2nd CPU cluster there).

          And the 'reading' was related to real world (maybe needing magnifying glasses since the markings of the chips on the SSD might be pretty small?)

          1. SSD markings in updated blog as request. Everything is working. Before I try that mod of yours - can you point me as to which figures I should be checking before and after.... and once made is the mod permanent (until reversed).

            1. Changing the cpufreq governor as outlined above is not permanent but will revert to defaults after the next reboot.

              And 'performance' only means the CPU cores always clock at the upper allowed speed (1200 MHz) while 'ondemand' uses a strategy that tries to use a lower clockspeed when idle and only increase clockspeeds 'on demand'. The whole algorithm is considered broken and without some tweaks especially IO performance sucks since IO activity does not count for activity.

              It's long known now that ondemand without io_is_busy=1 leads to unnecessary low filesystem access (based on some other parameters, especially minimum allowed clockspeeds) and it's also a long tradition that vendor supplied OS images always miss this simple adjustment 🙂

              So if you switch to performance temporarely just execute the iozone call again -- I would assume performance with small block sizes (which is what happens mostly) will benefit the most. When you benchmarked before you got ~1400 random IOPS with 4K blocksize and with better cpufreq settings maybe twice as much are possible if the SSD is fast (IOPS --> IO operations per second).

              Anyway: doesn't matter that much on these kind of devices but it makes me always a bit sad that such simple adjustments aren't default everywhere in the meantime, since no disadvantages and better performance.

              BTW: controller/memory markings are hidden by those fancy and meaningsless KingSpec stickers so to know what this hardware is really made of they need to be peeled off 🙂

              1. Tkaiser....

                Adding that one-liner

                echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

                had no effect at all on speed as indicated by current CPU speed - which sits around 300-500Mhz normally - min and max are set at 120Mhz and 1008Mhz respectively. As it doesn't survive reboot I'm not sure what to try next.

    1. Well, I can't recommend running with performance permanently (even though it doesn't hurt that much but the SoC will then be fed with 1.3V instead of 1.1V and both consumption and temperatures are higher than needed).

      Reasonable cpufreq settings are to be preferred (unsurprisingly I can only recommend Armbian settings since these are the results of days of work done on the subject over the past years).

      IMO reasonable settings for such a H2+ board are the tweaks from added to /etc/rc.local, then installing the cpufrequtils package and creating /etc/default/cpufrequtils with the following contents:


      BTW: the following is a 'refreshing' example for vendor ignorance and how not caring about such essential settings totally destroys performance:

      (and it's almost everywhere the same, the only vendor exceptions are Hardkernel and maybe the RPi people)

      1. Tkaiser

        I did exactly what you suggested - firstly removing my own entry from rc.local and adding the highlighted section from your file.

        I then installed cpufrequtils - that went fine.

        I then added a file /etc/default/cpufrequtils and added the content you suggested.

        I rebooted. No difference... what it says now is...

        speed 240Mhz, min 240Mhz, max 1008Mhz - i.e. exactly as before.

        Any typos in the above instructions???

        1. Ha! You did everything right and the change in minimum frequency confirms that. The reason the maximum cpufreq doesn't change is due to the whole Linux embedded world obviously being posessed by doing copy&paste over and over again with numbers that were there by accident in the beginning 🙂

          FriendlyELEC chose to stay with 1008 MHz max due to device tree contents:

          These 1008 MHz are the results of Ondrej starting to code the cpufreq stuff last year and developing on Orange Pi PC and One and being a little bit cautious. So he chose 1008 MHz and not 1200 MHz. Then his code got rejected for months, picked up by Icenowy without changes to these values some while ago and now we have values in all those H2+ and H3 device tree files that are there just by accident 🙂

          The not so TL;DR variant and also explanation what we (most probably Armbian team since no one else seems to care) have to tweak can be found here:

          I'll prepare an email for FriendlyELEC's Weidong (kernel dev) soon -- just too lazy right now since dealing with this stuff as a software guy when vendors should do this work is soooo weird 🙂

            1. That's the correct behaviour. When the system is idle it should clock the CPU cores down. The tweaks are only about how (fast) to increase cpufreq in which situations. And if you applied the stuff correctly so that especially io_is_busy is set to 1 then if you now repeat the iozone test on the SSD numbers should be better if NanoPi Duo's setting were the bottleneck before.

              If you check the following with cat and it's 1 then please repeat the iozone test on the SSD and provide new numbers 🙂


              (if there's a 0 or an error message instead then there's something wrong and tweaks are not applied)

                1. Thank you for testing/confirming. Yeah, especially with small chunks of data the SSD is now almost twice as fast. And with large sequential transfers it gets closer to the 40MB/s barrier (~32MB/s before, 37MB/s now).

                  Now imagine the whole cpufreq settings everyone uses with mainline kernel would be finetuned like we (community) did with H3 legacy kernel last year and you would get another nice performance boost for free most probably even with lower overall consumption 🙂

                  It's both nice and scary how much optimized settings matter on these small gems and how less most hardware vendors and kernel/distro people care.

                  If I could get past my lazyness I would start replacing this here with that

                  Still not optimal but a first step in the right direction and combined with the other optimizations above (part of every Armbian OS image) good for an overall performance increase of +100% especially together with USB storage like the mSATA SSD here 🙂

  4. I've mapped the GPIO (I'll update my SPI_LCD project today). I tested SPI and it's strangely slow (around 3Mhz instead of the standard 30Mhz). Anyone else seeing awful SPI performance with FriendlyElec's ubuntu image?

  5. Is there a way to Putty right into WiFi by setting up wpa_supplicant.conf in the image?

    And if so, what would the localhost name be?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.