Monday, November 18, 2013
Tuesday, November 12, 2013
At the end of September, we released a set of slides that got a lot of attention. Probably, a lot of this was due to its somewhat inflammatory title: “The End of Web Development (as we know it)”. However, because the slides were designed as visual aids for some tech talks Jon gave, they didn’t tell the whole story without him speaking in front of them. I thought this would be a good opportunity to respond to one reaction we received:
“Why do you think electrical engineering is hampering the internet of things?”
It’s not that electrical engineering is hampering the internet of things; pervasive computing would not be possible without the dedication of electrical engineers. However, the key point presented in the slideshow is that electrical engineers are not equipped to create the connected world in the same way as software developers, for a few reasons:
Electrical engineering is really hard. Even for a seasoned electrical engineer, the speed of development for embedded hardware projects is very slow. There are delays in ordering parts, in soldering components together, in debugging a circuit only to find that one of the chips is fried. We wanted to abstract away this whole complicated process so that the makers of the internet of things can focus on their product ideas– what they are and whether they’re worth pursuing– before they have to think about designing embedded circuits.
Software developers are used to a different standard of deployment and analytics. When software developers are dissatisfied with the development tools available to them, they can create better ones. And they can track how well their software is performing after its deployment in order to further improve. Electrical engineers, on the other hand, have to work with design tools in software that are inflexible, proprietary, closed source, and prohibitively expensive, and have no analytics suites to use on embedded devices in the field. Tessel’s development environment seeks to leverage the best software tools and developments available– and those tools are made for software.
The software community is already instilled with the values of open source and community creation. The pace of innovation is fast in software partially because there are so many projects open to be copied, forked, and improved upon. This community doesn’t exist in the same way with hardware. Although the Open Source Hardware movement is growing, it isn’t as established as in software, and few tools currently exist to centralize the movement or share hardware designs. Technical Machine wants to speed up the pace of innovation in hardware by not only open sourcing the hardware and software of Tessel, but also by making a system that a community can capitalize upon: modular components and open components from the get-go.
The creation of the next generation of connected devices requires both software and electrical engineering expertise. Since very few individuals have both of those required skillsets, the barrier to entry for entrepreneurs in the space can be prohibitively high. Technical Machine wants to make that barrier to entry as low as possible by abstracting away the complexities of electrical engineering at the prototyping stage, and ushering in lean, entrepreneurial, innovative software developers to start with the tools they already know how to use.
Monday, November 11, 2013
Device Firmware Upgrade (DFU) allows a device’s firmware to be changed over USB. The alternative is having to use an external device such as a JTAG programmer. Setting up an external programmer is costly so we wanted to expose a DFU method for upgrading Tessel’s firmware.
In order for DFU mode to actually work, the device has to:
Tessel had USB boot mode enabled about 3 revisions ago because we knew we would eventually want DFU. The current revision of Tessel goes into USB boot mode if the two pins by the RAM chip are bridged. In this mode, Tessel enumerates as a USB device and is ready for host communication.
So great, #1 is already solved. 50% of the way there! Time for a celebratory browse of /r/aww.
Except that it didn’t work.
Confused and a bit annoyed, I scrounged around a bit and found this thread where NXP support says:
When the LPC18xx and LPC43xx family of parts boot up over USB they send a DFU descriptor up to the host but they do not support the full set of DFU functions. They can only download an image into RAM and jump to it. That’s it.
To implement a DFU driver you will need to create an image that contains this driver and download and run it as a second stage
Oh. Well. That sucks. Then it goes on to say:
The utility that downloads the image when the parts are booting up over USB is a C# application that sits on top of WinUSB. Source code to this application can be obtained with an NDA. Contact your FAE to do this.
What? I have to sign an NDA? No way.
But it did give me 2 important pieces of information – there is a protocol specific way to write to flash, and that there’s already an existing (though proprietary) tool which works on Windows.
So breaking it down, the proper way to write new firmware over USB is:
I didn’t know what LPC’s first stage DFU ROM does, but I did know that it had to accept messages over USB somehow. I didn’t know much about USB, so I went and checked out how USB packet transfers work. The cliffnotes version can be summed up in this image:
A USB device can have multiple configuration types (though having more than 1 is rare). Each configuration type has multiple interface descriptors. Each interface as multiple endpoints. Endpoints are what you actually talk to the USB device over.
Now I just have to check out what endpoint I need to talk over, write to that, and presumably the LPC DFU ROM will write that information to flash. So I whipped up a quick Python script that gave me all this information:
import sys import usb import usb.core import usb.util # find our device dev = usb.core.find(idVendor=0x1fc9, idProduct=0x000c) # was it found? if dev is None: raise ValueError('Device not found') # set the active configuration. With no arguments, the first configuration will be the active one dev.set_configuration() for cfg in dev: print "bLength", cfg.bLength print "bDescriptorType", cfg.bDescriptorType print "wTotalLength", cfg.wTotalLength print "bNumInterfaces", cfg.bNumInterfaces print "bConfigurationValue", cfg.bConfigurationValue print "iConfiguration", cfg.iConfiguration print "bmAttributes", cfg.bmAttributes print "bMaxPower", cfg.bMaxPower for (counter, intf) in enumerate(cfg): print "\t Interface number ", counter print "\t bLength", intf.bLength print "\t bDescriptorType", intf.bDescriptorType print "\t bInterfaceNumber", intf.bInterfaceNumber print "\t bAlternateSetting", intf.bAlternateSetting print "\t bNumEndpoints", intf.bNumEndpoints print "\t bInterfaceClass", intf.bInterfaceClass print "\t bInterfaceSubClass", intf.bInterfaceSubClass print "\t bInterfaceProtocol", intf.bInterfaceProtocol print "\t iInterface", intf.iInterface
It gave out the following:
Wait what, there’s no endpoints? How do I talk to it then? At this point I went and watched an episode of Adventure Time because goddammit what does this mean?
I then re-read that USB site I linked to earlier and saw that
Endpoint descriptors are used to describe endpoints other than endpoint zero. Endpoint zero is always assumed to be a control endpoint and is configured before any descriptors are even requested
Nice. So I want to talk over endpoint zero because that’s the only possible endpoint that’s available. This meant that writing to firmware over USB was now:
At this point I booted into Windows and downloaded the proprietary LPC tool for DFU. The setup for it looks like this
Here we have the first stage ROM (Algo), and the second stage program (a 160 byte length of repeating 0xDEADBEEFs). The address field is for the location in flash memory that we’re writing to. The microcontroller used on Tessel is the LPC1830. The 1830 doesn’t have any internal flash, which means all of our code is stored on Tessel’s SPIFI flash chip. The SPIFI flash is memory mapped at 0x1400 0000.
The input fields for this tool told me a lot. I should expect at least 4 DFU transactions (one for the Algo, one for erasing the flash, one for writing the flash, and one for reading the flash back to me). Somehow the protocol had to embed 0x1400 0000 (probably during flash writing and reading) and 0x00020000 (probably during erase).
I opened up a software based USB packet analyzer and tracked the packets as I ran the Windows tool. There were a few boring setup packets, but here’s the first interesting one
That 0x14 byte looks promising. Looks like that section are the bytes that tell it where to erase. And the 0x02 area is the size of a region to erase. Immediately following this came a reply
The next 2 DFU commands had these in the payload
See that 0xA0 byte? 0xA0 in decimal is 160. So during a write command it sends over the number of bytes it needs to write every time. The only other major difference is the beginning 0x08 byte vs 0x07 for erase. So the first byte is probably which command to execute.
And the reply from the device
Last was the read call:
And the device response:
And following this was another packet that had the 160 byte 0xDEADBEEF data in it.
Now with this information we can pretty much figure out that the protocol is sending a packet of 16 bytes which has the format
aa 00 00 00 bb bb bb cc cc cc 00 0B 01 43 18
Where aa is the protocol (0x07 for erase, 0x08 for writing, 0x09 for reading), bb is the memory location and cc is the length.
I then switched back to my Mac and sent over payloads that looked exactly the same with the exception of a payload of 16 bytes of 0xDEADBEEF. Checking the memory location over JTAG gave me this:
Success! All this just so I didn’t have to contact NXP and sign a freaking NDA. Worth it.
Friday, November 8, 2013
It’s nearly 4 AM. My hands and eyes are dry and tired, and my fingers probably smell like a mix of isopropanol and flux. I’m dehydrated and have been inhaling fumes for the last six hours, but it’s been a good day. Today we built all the modules which will be going out to our first round of Beta backers in less than two weeks. They’re shiny, they’re red, and they represent a hard day’s work in the lab. If my sleep schedule weren’t inverted, I’d probably be crashing about now (unless I caught the second wave), but it very nearly *is* inverted, so
< hour-long break where I read some articles, sign some paperwork, and browse Facebook >
it looks like I have a blog post and maybe some firmware ahead of me. With any luck, I’ll get up in time for a meeting around lunchtime. … Part of me wants to blame the startup life, but part of me knows my own habits get all the credit. Swap “credit” and “blame” as you see fit.
Hey readers! Eric here. We hinted in a recent blog post that we’d tell the tale of our RFID module sometime this week, so here goes.
Our story begins with the second round prototype. I knew that this version of the RFID board and the hardware we had bought from Adafruit differed in something that was subtle but also quite important. It wasn’t anything about the schematic or PCB layout per se (I had essentially forked my designs for both off of Adafruit’s), so I had to dig deeper and think a little harder.
I started by simulating the RF (radio frequency, anything operating above a few hundred kilohertz) TX/RX (transmit/receive) chain in LTSPICE (my circuit simulator of choice). The RF chain is made up of a network of passives (resistors, capacitors, and inductors), so I plugged in the values I had on the schematic, did a frequency sweep, and found that, surprise, the circuit had a resonant peak near 13.56 MHz. This is what that looks like in simulation:
A quick note on how to read the charts and what matters:
The top graph is called a Bode plot. It shows what happens to a sinusoidal waveform as it passes through my circuit. Frequency, in Hertz, is on the x-axis. Magnitude, in decibels, and phase shift, in degrees share the y-axis.
The solid lines show the magnitude of the frequency response of the circuit, which tells us if portions of the signal at any given frequency are amplified or attenuated as they travel through the system.
The dashed lines show the phase shift of the output waveform with respect to the input waveform, in this case measured in degrees. We don’t care about it so much in this case, but phase is really important in control systems design.
The bottom is the schematic I’m simulating. I’ve named all my components and nodes (places where components are connected) so that it’s easier for me to read the graphs, which in turn help me tune the values on the schematic, which, well, you get the idea.
In this case, I wanted to see a spike upwards around 13.56 MHz, which would tell me that the system resonates around that frequency. In layman’s terms, this means that the system is good at storing energy that comes in at that frequency. In the case of RFID, we mostly care about the current through the last inductor, I(L2), and in the very special case of the board we built, this inductor is actually a long, winding trace on the PCB. In any case, current through an inductor is related to the strength of the magnetic field and therefore the distance at which we can read an RFID tag. I included V(V_1) (the voltage at node V_1) as well to get a general sense of what inductor L1 and capacitor C1 do to the signal; it just so happens that the input section of a system often has a disproportionately large impact on output signal quality.
As I hoped, the system resonated at roughly 13.56 HMz. However, the system as simulated is a purely theoretical one, and it turns out that that is part of the problem.
I wanted to know how the real boards compared to my simulations, so I soldered a few wires onto both the boards (to nodes V_1, V_out, and ground) so that I could drive (provide input to) the antenna circuitry and measure the response. I then proceeded to beg my old wireless communications professor to let me use some of his lab equipment to characterize the system. Armed with a swank signal generator and spectrum analyzer (a poor man’s network analyzer, but still $35,000 in test equipment), I did frequency sweeps and collected some data:
This is another Bode plot (well, the magnitude portion), which shows the frequency response of our board (red) and Adafruit’s (blue) on top of one another. The fact that the curves look like gradients (as opposed to just lines) stems from how I took the measurements (like I said, poor man’s network analyzer), but the shape of the upper limits of the curves is what’s important in this case.
We care most about the response at 13.56 MHz, but the takeaways from this graph are mixed.
These graphs should look like the ones from SPICE, but definitely don’t. Hmm…
Our amplitude is slightly higher than Adafruit’s at 13.56 MHz (win! This means we’re more sensitive to signals at 13.56 MHz, which means we should be able to read RFID tags from further way)…but this finding is not actionable because we were apparently already doing fine.
Not instantly sure what’s going on on our board with the huge null around 17MHz, but because it’s outside the band of interest we don’t actually care.
The fact that the slope at 13.56 MHz is more gradual suggested to us that the LC resonant tank created between C3 and L2 (with R2 in the way) might be less ideal on our board than on Adafruit’s. Translation: Adafruit picked a few key parts to splurge on which might make all the difference. Time to figure out which ones.
One of the things I learned to do early on in my engineering career was simulate things. It’s often easier to have a computer run the numbers than to run the test yourself (be it a circuit, mobile app, or load test for a large mechanical assembly). The blessing and the curse of simulations, however, is that they can only ever be as accurate as you care to make them. In other words, if real resistors, capacitors, inductors, and transistors were all perfect, ideal, purely mathematical devices, the board’s performance would match simulation’s, we’d be able to read RFID tags from a good distance away (and angels would sing on high as we did).
It turns out that these parasitic characteristics (think “this resistor should not be here because i’m supposed to be an inductor, not a resistor”) and other “nonidealities” (deviations from the pure mathematical models in the form of nonlinearities, dependence on temperature or voltage, hysteresis, etc.) are part of what separate not only real components from ideal ones, but also high quality real components from low quality ones.
Armed with the knowledge that the fundamental design I had in hand was good, I looked through the datasheets for the components we had used on our board and plugged in some values of series resistance to SPICE. The results, below, are quite different from what I had originally found.
Everything is smoother (this is bad: we want nice sharp resonant peaks), V_1 now has a null near 14.5 MHz (look familiar?), and the output voltage and current drop by around 20 dB (a factor of 10). Clearly the components we were using were no good.
I suspected then, that the inductor L1 was the primary offender, so I popped the corresponding part off of the Adafruit board and swapped it for what we had on ours. It helped, but did not completely solve the problem: RFID communication distance jumped from a millimeter (read: contact) to about a centimeter. I spent half an hour on Digi-Key “specing” (hunting for a part that not only has the right value, but also the right package, is economical in quantities of 100 and 1000, meets other required specifications, etc.) inductors to replace the ones we currently had on our board, ordered a few samples, and then turned my sights to the PCBs themselves.
I took the boards up to the lab and used a LCR meter to measure the inductance of the PCB antennas (L2 in my sim). I found that they were actually remarkably similar, but that the Adafruit board had a higher Q factor, which implied that it had a smaller resistance.
Next, I set up an ultra-precise four point resistance measurement and found that Adafruit’s antenna had a series resistance of about 0.37 Ohms. Ours clocked in at about 0.53 Ohms. Although the difference there is small, it’s the ratio that matters: their antenna was about 30% less resistive than ours, which was consistent with their higher Q factor.
These days, PCB mills are out of style. Well, they may be coming back into style for personal use, but the fact remains that most boards that are made in any volume are printed. For two-layer boards (the process is more complex with more layers), you start with a piece of copperclad: a sheet (generally fiberglass-based) with a thin layer of copper on the top and bottom. A series of processes lay down chemicals that become corrosion resistant when properly treated, and the remaining exposed copper is bathed in nasty chemicals and dissolved away. Afterwards the surface may be treated with some combination of metal plating, a nonconductive layer called the soldermask, and a layer of paint called the silkscreen.
As you can imagine, every step in this process can be customized, and the thickness of the copper is no exception. It’s specified in terms of ounces per square foot (which typically just gets shortened to “oz.”, or oz./ft. if you have the time) and corresponds to “if you took x ounces of copper and mashed it over one square foot…well, that’s how thick the copper is on each side of your board”. Most boards use one-ounce copper (at least for the outer layers) and “heavier” boards are typically only needed for high power applications (the highest I’ve held is 4 oz., but I’m sure the sky’s the limit).
Finally, I grabbed a pair of calipers and set to measuring the thickness of the copper plating on the PCB. I measured the “bare” board first, then the board with the antenna trace. The differences were not the same: Adafruit’s copper was, in fact twice as thick as ours, putting it at two ounces.
I let out a sigh, emailed Jia, and told her to find me a PCB house that would do two ounce copper in a reasonable amount of time. At this point, it was late, I was tired, and it would be better to continue to match Adafruit’s working design as best we could, rather than chase down more rabbit holes.
Fast forward a week or so, and there I was in the lab with two boards in front of me, fresh back from the oven. They were two ounce copper, had the funky fresh inductors I had picked out, and were ready to test. I plugged one in, loaded some code, watched the RFID chip enumerate, pulled out my CharlieCard (Boston’s RFID-enabled subway fare card), and held my breath.
I brought the card close, and watched as my screen displayed a very familiar, but lately aloof, four byte sequence: my identifier in the eyes of the MBTA.
It had worked, and at a distance of roughly three inches, so naturally I threw my hands in the air in celebration. In my hurry to capslock the success to the rest of team over HipChat, I lost my Charlie card somewhere on my desk. I’m sure it’ll turn up eventually.
Wednesday, November 6, 2013
The Technical Machine team is hard at work designing, assembling, programming and testing all the components of Tessel and its modules (see our status page for details). Personally, I’ve been spending a lot of time getting the Bluetooth module ready for release.
In a previous post, we talked about what goes into the hardware design and assembly of a module. But that’s only the beginning. After we put the module together, there’s a long process of testing the hardware works and writing the entire library.
The first step is to make sure that hardware works like it’s supposed to. The chances of it working 100% right with the first revision is infinitesimally small, so we make it easier on ourselves by breaking out any questionable connections with headers so that we have more flexibility when we start testing. Headers give us the option of easily changing connections (with jumpers or soldering on wires) or verifying the signals on those lines with a logic analyzer. We use and love Salae’s logic analyzer which will decode any signals we send over the wire so we can be sure our communications are working as expected. On our first Bluetooth module, we broke out a block of headers (see picture below) for all the communication signals so that we can easily test the receive, transmit and wakeup lines on the BlueGiga chip.
The BlueGiga Chip is what’s known as a System on a Chip (SoC), which means it has a microcontroller as well as a Bluetooth chip (the TI CC2540) and all the passive hardware like capacitors and resistors to make it all work reliably. The smaller group of headers at the bottom of the module exists so that we can program the BlueGiga chip with their proprietary toolchain. That’s right, we not only have to program the Tessel to communicate with the Bluetooth module, but we have to program the Bluetooth module itself to be able to respond. But don’t worry, if we need to update the firmware on the BlueGiga chip once we ship out the module, we can update it from the Tessel.
The next step is to make sure we can communicate with the module. Tessel initially supported only the SPI and I2C communication protocols, but the BlueGiga chip that we’re using communicates over UART. Each communication protocol has its pros and cons but these three are by the far the most common. To be able to interact with the BLE chip, we threw a SPI to UART bridge onto the module. I began making sure communication worked with the bridge over SPI, but soon after, we decided to add UART support to Tessel modules, rendering the bridge useless. Luckily, the fact that we add headers on all the communication channels meant that I could bypass the UART bridge by just adding some wires from Tessel’s UART to the header block, so we didn’t have to pay to manufacture more test module boards.
Now we’ll need to update the Tessel Node Package with the new UART function calls that we’ve made. The Tessel command line tools automatically inject the Tessel library as a dependency when we push code, so we don’t have to worry about updating any references.