I'm a software developer with majority of my career being on the web domain. The PAN1780 roadtest had got me thinking how to combine two disciplines (hardware and web software) together into something useful.


One of the more recent technologies that is starting to become readily available in the web domain is web bluetooth. It is, as the name implies, the ability to control bluetooth low energy devices through a webpage. I've always wanted to learn and try this technology out on a project, and the PAN1780 roadtest gave me the perfect opportunity to do so!

I do want to let you know that (in the interest of full disclosure) the PAN1780 evaluation kit was sent to me as part of Element14’s Road Test program, and I’m very grateful to them for the opportunity to road test the product.


The other products in this review (unless otherwise noted) were purchased by me using my own funds.


All the opinions you are about to read are all my own; nobody is paying for this review, nor has anyone reviewed or approved the content before it was posted.


I will also be approaching this road test from the point of view of a hobbyist that has had some experience with similar products, but have yet to deal with them in a professional setting.

Parts and Software

Web Browser

Web bluetooth is still relatively in its infancy, with the Web Bluetooth Community Group (which oversees the specifications drafting process) launched in 2014 and Google Chrome (which is the only major browser vendor aside from Firefox and Safari) only implementing the API in release 56.


This is still an experimental feature on desktop browsers, so if you would like to follow along, you would need to enable this in the Chrome flags:

Alternatively, you can also use Google Chrome on Android, which already has this enabled by default.


Unfortunately, 3rd party browsers are not allowed on iOS devices; you might think you're using Google Chrome on your iPhone when in fact you are using iOS Safari under the hood (Apple policies) and Safari has no indication of adding support web bluetooth as of this time.


Lightbulb / Neopixels

I am not a licensed electrician so I didn't really want to try and modifying the usual mains-powered LED bulbs.


I also wasn't able to find any BLE-enabled lightbulbs that had addressable RGB locally. Buying one from overseas wasn't really an option due to the uncertainties involved in shipping, and I wanted to make sure I can finish the road test reviews on time.


So in this case, I bought a USB-powered LED light fashioned in the shape of a small lightbulb and modified it with a 7-pixel addressable RGB board (commonly known as neopixels). I'll explain more details about it in the build section below.


PAN1780 Firmware

Like the previous project, we'll be using Espruino and writing the program via Javascript.


Espruino has had a number of changes, and I had to troubleshoot and debug a small issue with regard to the nRF52840 Espruino build not being able to drive neopixels through I2S. The fix has now been merged into master, but in any case I'm attaching the Espruino firmware in this post if anyone wanted to follow along.



Modifying the Lightbulb to run Neopixels

I pried out the pcb that contained the original white LED along with the USB male connector, being careful not to damage too much the plastic tabs that keep the USB connector from being pushed further inside the bulb.

I made a small "shield" to support a female USB Type A breakout so that I don't have to mess around with loose wires.

In order to source power for the Neopixels, I added a jumper to connect the 5v VUSB rail to the pin header marked as 5v.

It was at this point when I realized there's a big issue with regard to the evaluation kit's design of the pin headers: they are symmetric, and as you can probably imagine above you can easily get disoriented and attach them the wrong way around.


While this isn't necessarily a problem (for example, some 2x5 JTAG headers don't have any keying and have the same issue of being physically symmetrical) it is a huge issue for the PAN1780 Eval Kit: the power rails (5v 3v3 and GND) are all on the ends of the header rows.


This means if you ever accidentally insert in the shield backwards, you would be subjecting the circuit with reverse polarity! Even worse is if you're using something like a robust power bank that can output up to 3 Amps of current; that's an almost guaranteed fried circuit for you because the 5v pin shouldn't really be labeled as 5v; it should be labeled as VIN because it's a direct connection between VUSB and that pin header.


Noting this, I then soldered wires onto a round Neopixel pcb (it looks very similar to the Adafruit Neopixel Jewel) using the standard colors for Neopixels: Red for 5v, White for GND, and Green for Data In. Usually it's also Green for Data Out but I didn't want to confuse myself, so I used a light blue color instead.


These were then soldered in to the original USB male connector with Data In being USB D+ and Data Out being USB D- (data out isn't used for this project, but I added it in anyway for possible future mods).


I then used the original while LED pcb as some sort of platform for attaching the neopixels. It also serves as a light mask (so light doesn't cause the wires to cast a shadow inside the bulb) and also helps reflect the light outwards.


After reassembling everything, the light bulb looks almost exactly like it did before the modifications, but this time hiding a more "colorful" secret.


Programming the PAN1780

Espruino was flashed onto the PAN1780 using nRF Connect just like how we did it last time.


This time though, the program running on the PAN1780 is a bit more complicated. Here's an embedded gist of the source code.

The Bluetooth Special Interest Group (SIG), in all their infinite wisdom, has shortform UUIDs for heart rate, battery level, and even environmental sensing like temperature and humidity, but don't have any UUIDs reserved specifically for lighting.


At this point I didn't really want to make my own custom UUID just for the LED service, so I used a service that's not normally used by registered bluetooth devices: the User Data service (0x181C) and the characteristic being as generic as it can be: the String characteristic (0x2A3D).


You can see the service being defined in lines 28 to 40.


The characteristic can receive an array of three bytes, representing the values of red green and blue, and in turn changes the colors of the neopixels to that 24-bit color.


In order to help with debugging, I also set the program to light the neopixels with a shade of grey whenever something connects to it, and turn off all neopixels when the client disconnects (lines 42 to 50).


Programming the Web Browser

Now that the build for the device to be controlled is done, it's time to do the actual controller.


The Web Bluetooth is a chain of Promises that mimics the hierarchy of Bluetooth devices, services and characteristics.

  • First, you "scan" for devices using navigator.bluetooth.requestDevices which will take a set of options to filter which devices get shown (so as not to overwhelm the user)
  • Then you connect to the device.
  • Then you call getPrimaryService passing it the UUID of the service you are interested in.
  • Then you call getCharactersitic passing it the UUID of the characteristic you are interested in.
  • Then you call writeValue to send data to the device via that characteristic.


Here's a gist of the source code (it's just an HTML file so if you want to follow along, just save the gist as html and open in Google Chrome; alternatively later in the Demo section I'm hosting the same file on a website):

To make things interesting, I added a color picker UI to the page and set it up so changing the colors will automatically write to the characteristic and change the color of the lightbulb. This only works on the desktop version of Google Chrome though; the Android version requires that you set the color before the light bulb changes (as it seems to not fire the oninput and onchange handlers on user interaction) but with a custom color picker, it should be able to do achieve the same results.




The light bulb is at the left, the web browser running the Web Bluetooth API javascript program is on the right.


The same html file is hosted at and you can easily view the source from that page if you want to.


I was pleasantly surprised at the transfer speed; the light bulb was able to change and keep up in real time while I was dragging the cursor along the color picker.


I'm even more impressed at what Web Bluetooth can enable. While experimenting with the API, I was not only able to connect to the PAN1780 but virtually any device I have at home that runs Bluetooth Low Energy.


This means that I don't even need to install an app to connect to physical devices; all I need is a browser and a computer or an Android phone. The barriers to entry for these types of "smart device" development has been lowered considerably.


  • The pin headers that breakout the nRF52840's GPIO are symmetrical, and what's worse the power rails are on the tail ends of the headers. Special care must be taken when attaching shields so that are not inserted the wrong way around. This is unlike the Arduino UNO or the Featherwing pin header layouts with intentional uneven pin counts (and in the case of Arduino UNO, an unintentional fabrication mistake that turned out to be a good thing) which visually reminds the user the polarity of the shield, or the 2x5 JTAG which do not have the power rails on opposite ends, making it less likely for an accidental reverse polarity situation to happen.
  • The 5v pin header is directly connected to the VUSB; at least in the Arduino UNO when a pin is labeled 5v it is considered to be regulated 5v. It would probably be better if that pin is marked as VIN instead of 5v to reinforce this (since VUSB can range from 5v25 down to 4v4 and still remain within spec) especially with devices that expect regulated 5v power.
  • The JLink led that keeps blinking whenever there's no computer communication is (just like the last time) quite annoying. I wish there was a way to physically disconnect the jlink or otherwise power the PAN1780 that doesn't route  power to the jlink.


Web Bluetooth was even better than I expected; I already thought it was cool to be able to control BLE devices just through your browser (which is ubiquitous and available to almost anyone) but what made it even more amazing was the ease I felt while using the API.


The PAN1780 Eval kit facilitated my exploration of Web Bluetooth by being easily flashable via nRF Connect (due to its built-in jlink programmer, albeit very annoying sometimes because of the flashing red LED that can't be turned off) and making the nRF52840's GPIO easily accessible.


There were some safety concerns with regard to the layout of the headers, but as long as you always keep this in mind, it was easy to make custom shields for the board.


The PAN1780 module itself was small enough that it could eventually be designed into an actual lightbulb, with power sourced either from USB or from mains. I even prototyped something like this a few months ago with an nRF52832 chip. The PAN1780 is even smaller, and with the nRF52840's ability to accept up to 5v5 in high voltage mode, even less circuitry is required (there's no need for an LDO or a buck converter if being powered from VUSB for example).