Tuesday, March 28, 2023

NAS file system repair Terra-master F5-422 NAS

I'm writing this incase anyone else runs into the problem I had with the F5-422 NAS last week.

The Terra-master 50TB RAID1 F5-422 NAS  here experienced its first power failure, probably while in active use and did not take it well.

While I had to reboot this a few times since it was deployed in 2020, it's always back up normally. This time was different.

Two thing that went against it this time:

  • Actual power failure vs a reboot via pressing the power button
  • Actively writing files during the power failure event

The immediate symptom was that mount requests from client devices were refused and the WEB UI was indicating a factory-reset state (was asking for a email address etc to starting configuration).

Fortunately both telnet and ssh to root user on port 9222 with the previously set admin password worked.

I tried Terra-master support, and got exactly the level of support I expected. They suggested I reboot. I explained I did. They suggested I reboot again. And again. And again. Ok, enough of this. I'm on my own.

BTRFS is the file system used in this NAS. Attempting to manually mount the file system from command line resulted in a superblock error:

mount -t btrfs -o ro,usebackuproot /dev/mapper/vg0-lv0 /mnt/jdraidrecovery/
mount: /mnt/jdraidrecovery: can't read superblock on /dev/mapper/vg0-lv0.

I tried doing a read-only check:

btrfs check  /dev/mapper/vg0-lv0

That quickly failed due to RAM exhaustion. It came with 4GB RAM and it would seem that is no where enough to check a 50TB RAID. There is supposed to be a low mem checker mode, but that didn't appear to be available on the installed btrfs utilities. That would explain why a reboot wasn't recovering the NAS. From the logs it looks like recovery was started but was quickly killed by the OS for exhausting RAM.

The fix:

Mount an external SATA SSD via USB adapter and create a 16GB swap file and then manually set the OS to swapon that.

btrfs check --clear-space-cache v2 /dev/mapper/vg0-lv0 

btrfs check --repair  /dev/mapper/vg0-lv0


This took 5 hours+ to complete. However when competed I was able to manually mount the RAID device. Then reboot and all was normal.

Generally I'm quite pleased with this device. It offered a 10Gbps ethernet port at a very competitive price point. However the price you pay for that cheapness is having to figure problems like this on your own.


Thursday, April 25, 2019

Raspberry Pi 4 predictions

I’ve been thinking about what’s wrong about the Raspberry Pi lately and my wish list for the Pi 4. So I thought I’d put some of my thoughts and predictions about the Pi 4 down in a blog post. I have absolutely no inside knowledge: this is 100% speculation.

In the announcement blog post of the Pi 3A+ in November 2018 it was admitted that the current generation of Raspberry Pi had reached the end of the road and that anything new will require a fairly radical redesign. The Pi is by far the best selling single board computer ever having sold over 23 million since its launch in 2012 to end 2018. So they are in no hurry and are likely to take their time and come up with a good architecture that will set them up for painless and regular incremental improvements for years to come.

Rasbperry Pi hardware release timeline 2012 - 2019

The only thing I can predict with near certainty is that the the primary peripheral bus will USB3.  One of the most common criticisms of the current generation of Pi is its reliance on the USB2 bus with its theoretical maximum bandwidth of 480Mbps. This is particularly problematic for the ethernet port which is implemented as a USB peripheral. 1G ethernet is now the norm, but the Pi until the very last iteration came equipped with a 100Mbps ethernet port. Even the last Pi 3B+ which did come with a 1G ethernet port can only achieve about have of that bandwidth because of the USB2 bottleneck. The Pi4 will most likely also feature 1Gbps ethernet but through USB3 or direct to the SoC (the System-on-Chip, the heart of the Pi) so that the full ethernet bandwidth can be realized. 10Gbps ethernet is also an option, but it’s still very expensive and uncommon, so not likely.

The form factor and expansion header pinout and related software APIs are very unlikely to change significantly. There is far too many products and tutorials out there relying on that not changing.

The RAM is due an upgrade. The original 2012 Pi 1B featured 256MB which over the years kept doubling to the current 1GB. That’s arguably enough for the ‘mission’: a education and prototyping tool. But many of its direct competitors now have 2GB standard. I think 2GB RAM is probable but not a certainty. But as mentioned before the architecture and board layout will be such that they can increase RAM to 2, 4 or maybe even 8 or 16GB without any drastic re-engineering. Pi RAM will always be soldered on board. Modular RAM like on laptops and desktops would push the bill-of-materials way beyond the $35 target.

The SoC is also likely to be significantly different to the current generation. My hunch is that they’ll abandon the Videocore processor used in the SoCs used to date (Broadcom BCM2835, BCM2836,  BCM2837, BCM2837B0) and go for the more mainstream ARM Mali GPU. A little known fact about the Pi SoC is that it’s a Videocore processor with ARM co-processors. It’s Videocore first, ARM second. The first thing that runs when a Pi is powered up is the Videocore firmware (often referred to as the ‘binary blob’). This is closed source code running on undocumented hardware. It configures the video system, external RAM and the ARM processors and then hands over control to the ARMs and the next stage bootloader which in turns boots the Linux kernel. The Videocore firmware is also responsible for converting the raw video from the camera MIPI interface into a H.264 MPEG stream for the operating system.

I never give this closed-source nature a second thought until a few years ago when I attempted to use a Raspberry Pi for a commercial project. We wanted to use an Omnivision OV5640 (in theory backward compatible with the supported OV5647). But since all this was handled in the closed source ‘binary blob’ there was no way to tell the Pi to recognized the OV5640 even though it’s interface was identical. (We did ask the Pi Foundation if it was possible to pay for a custom modification to the firmware, but we were told ‘no’, and using the OV5647 wasn’t an option either because it was impossible to source).  So a move to a more open video / GPU system supporting a wide range of camera modules would be greatly welcomed. Proper 4K monitor support would also be expected.

Of course since the Raspberry Pi Foundation don’t make silicon their SoC choices will be constrained by what their hardware partner (currently Broadcom) are willing to provide. But they are now a large customer and I’m sure their wishes will be listened to. And maybe, just maybe, they are big enough to have a custom SoC made for them.

What else for this SoC? Probably still quad core (but with an upgrade plan to support 8 or more cores without re-engineering). Definitely ARM 64 bit Cortex-A like the current Pi.

I have a strong hunch the storage system will be overhauled. The microSD card bandwidth is another common criticism of the Pi. The new (2019) microSD express standard supports bandwidths up to 985MB/s is far more suited to the access patterns of an operating system than the original SD card which is more suited to cameras and smartphones.

The last few iterations of the Pi hardware introduced some bonus peripherals: built in WiFi, Bluetooth, Power-over-Ethernet. I think we can expect another bonus peripheral in the Pi 4. One tantalizing possibility is a GNSS (GPS) receiver. I doubt they’d ever add a discrete GNSS chip to the board, but it’s becoming common to have this function integrated with mobile device SoCs.  If present it’s just a matter of routing out the antenna to a small U.FL antenna connector. In addition to positioning applications (up to cm level with RTKLib if raw GNSS data is provided!) GNSS also provides a super-accurate time standard for the system clock. Environment sensors are also strong candidates (accelerometer, gyro, compass, pressure, temperature, humidity). Maybe even a mic!

What else? Power management is rather weak on the Pi: it’s just not battery friendly. A completely idle Pi still uses 100s of mA of current. It really should be possible to put it into a sleep mode using tens of mA like Android phones which use similar technology.

The OS? same as before Raspbian and NOOBS being the primary choices. At some point Raspbian needs to take the leap into ARM 64 bit  (the official Raspbian distribution remains 32bit for backward compatibility with older hardware). Also expect Microsoft to release Windows 10 for it and maybe finally we’ll see a decent port of Android (I believe the proprietary Videocore mentioned above is preventing a quality Android port). Apple won’t feature (or care).

Cost? I can’t seem them deviating from the usual $35 price range, but I think they can now get away with pushing that just a little. An extra $5 or $10 won’t cause too much grief, especially if they provide a ‘Model A’ with the ‘cherries’ removed.

When? On average they’ve been doing one major hardware iteration once per year and that usually comes in the early months. Early 2020 would seem to be in keeping with their release cadence.

Friday, April 29, 2016

The first person to describe an Inertial Measurement Unit (IMU)

Navigation equipment from the NASA Apollo space program.
The spherical shaped device is the IMU.
While reading an interest book recently ("Inventing Accuracy - A Historical Sociology of Nuclear Missile Guidance" [1]) I came across an interesting bit of historical trivia:

Irish man Joseph John Murphy [2] writing to Nature magazine in 1873 in reply to a letter from Charles Darwin on the topic of animal navigation wrote:

"if a ball is freely suspended from the roof of a railway carriage it will receive a shock sufficient to move it, when the carriage is set in motion: and the magnitude and direction of the shock … will depend on the magnitude and direction of the force with which the carriage begins to move … [and so] … every change in … the motion of the carriage … will give a shock of corresponding magnitude and direction to the ball. Now, it is conceivably quite possible, though such delicacy of mechanism is not to be hoped for, that a machine should be constructed … for registering the magnitude and direction of all these shocks, with the time at which each occurred … from these data the position of the carriage … might be calculated at any moment." [3]
... and thus became the first person to describe a device that took over half a century to realize: the Inertial Measurement Unit (IMU). The fist IMUs where rather large, heavy mechanical devices like the one pictured above from the Apollo space programme. Nowadays they can be implemented in silicon using a technique called MEMS [4] and there's one in every smartphone!

[1] https://mitpress.mit.edu/books/inventing-accuracy
[2] http://www.newulsterbiography.co.uk/index.php/home/viewPerson/2097
[3] https://en.wikipedia.org/wiki/Animal_navigation
[4] https://en.wikipedia.org/wiki/Microelectromechanical_systems

Update: I've been unable to find any photograph Joseph John Murphy. If anyone knows if one exists please let me know.

Wednesday, February 18, 2015

NXP LPC8xx EEPROM emulation

Screen grab from terminal of demo showing
the reprogramming of a byte in 'EEPROM'
(actually a page in flash memory).
Summary: The NXP LPC8xx series of MCU lack traditional EEPROM capability to preserve settings across power cycles, but this functionality can be emulated using in-application flash programming. I've written a demo program to show this in operation.

The LPC8xx series is a popular range of of ARM Cortex-M0 MCUs from NXP. One feature that I find indispensable is the ability to preserve settings across power cycles.

Many MCUs feature a small EEPROM bank for this purpose. But the LPC8xx does not have EEPROM. However it does allow the flash memory to be reprogrammed in 64 byte pages from within the application. This can be used to emulate EEPROM functionality.

I found an example [1] which worked after some initial trouble [2]. The example however fails to address one important question: how to allocate a space in flash that's safe to read/write for this purpose.

I posted a query to stackexchange.com [3] and received a few good suggestions on how to achieve this. One suggestion was to use the uppermost flash page. However that required prior knowledge as to the particular part being used (LPC810 has 4kB flash, LPC812 16kB etc). An alternative suggestion which I preferred was to use this:

const uint8_t eeprom_flashpage[64] __attribute__ ((aligned (64))) = {0};

This is probably specific to the GCC compiler, but other compilers will have an equivalent for directing a 64 byte alignment of the allocation. I found the "={0}" assignment necessary, otherwise the array was allocated in RAM.

I implemented all this in a little demo program which has been tested on a LPC812, but should work on all LPC8xx series of MCU. You can find the code on GitHub: https://github.com/jdesbonnet/LPC8xx_Flash_EEPROM/

Flash vs EEPROM

There are some downsides to using flash. First, it does wear out eventually (as does EEPROM, but EEPROM endurance is typically an order of magnitude greater than flash: (in the order of 100 kcycles vs 10 kcycles). [4]

The other problem which can be seen in the screen shot above: a whopping 101ms to complete a write. That's forever! (typically EEPROMs have write times in the order of a few milliseconds). What happens if the power fails during a write? (I actually don't know!)

References:

[1]  http://www.lpcware.com/content/forum/eeprom-emulation

[2] I was initially attempting to test by writing some constants defined in the program (and therefore were stored in flash). The iap_copy_ram_to_flash() function must receive the source data from RAM. Flash to flash copy is not possible during this operation. Ref UM10601 22.5.2.2 Copy RAM to flash (IAP).

[3]  http://electronics.stackexchange.com/questions/153424/how-to-automatically-allocate-a-page-of-flash-for-in-application-storage-of-sett

[4] The LPC81XM datasheet, section 12.1 specifies flash endurance typically at 100 kcycles, erase time for 64 bytes typically 100ms and write time for 64 bytes typically 1ms.

Sunday, February 8, 2015

A hack to easily measure electrical current use of a battery powered device

This is a little hack to measure the current use of a battery powered device. I used this in a recent Lidl LED nightlight teardown. These nightlights came with plastic spacers which kept the battery disconnect until it was ready for use.

I covered both sides with copper foil tape, soldered wires each side and reinserted between the battery and battery contact. I then connected the two wires to an ammeter. Voila!


Lidl PIR nightlight teardown and hack

Summary: I picked up some low cost (E8) battery powered / PIR triggered nightlights that were on sale in Lidl. The heart of the device is a common PIR IC. One of the IC pins can be tapped to drive digital IO line for occupancy detection or an intruder alarm. Given that PIR sensors alone in small volumes can often exceed €10/$10 this represents good value for money.

The device (Livarno Lux brand (Lidl), model Z31685C)  comprises 8 white LEDs, a  PIR (Pyroelectric Infrared) sensor with a polyethylene plastic fresnel lens [1] and a photodiode (which suppresses the illumination of the LEDs during the day). It is powered by 8 x AAA alkaline cells (supplied) arranged in two sets of 4 in series.

The device can be mounted on a wall or ceiling by attaching a mounting plate with screws or an adhesive strip (also supplied).

Teardown:

The top cover comes off easily enough: seems to be held on by friction alone. Then an aluminiumized plastic reflector can be pulled of revealing a single sided PCB secured to the base with three screws. On the top surface of the PCB is the PIR sensor, a light sensing photodiode and two electrolytic caps.

Underside of nighlight PCB.
 (the thin red and yellow wires soldered to the main IC were
added by myself to facilitate interfacing with MCU).
Click to expand image.
The fun is on the underside. At the heart is a 16 pin PIR IC marked "HS0001". Googling this didn't yield any useful results, but I found several PIR ICs that had similar marking codes: LP0001 [3] and BISS0001 [4]. The datasheets for these have a reference design which look very similar to the layout of this PCB. After some probing, I can say with certainty that the HS0001 used on this board is functionally identical to the LP0001 and BISS0001.

The board is powered by the two parallel banks of 4 x AAA alkaline cells. Each bank supplies approx 5.5V. A diode in series with each bank prevents one bank from driving the other in reverse (which can cause alkaline cells to leak). A linear regulator provides a 3.3V rail to the PIR IC.
Reference design schematic from LP0001 datasheet.


Most of the passive components on the board are resistors and capacitors used to set various tunable parameters of this IC [list pins]

The VO (pin 2) line from the IC drives the gate of a (FET?) transistor which switches the lighting LEDs (driven by the 5.5V direct from the batteries).

So how power efficient is this? Using a little hack I measured the quiescent current at about 90uA and the current with LEDs on at 70mA. Unfortunately the supplied AAA cells don't have any product code, but typically AAA alkaline cells have capacities in the range from 800 - 1200 mAh. Let's say 1000mAh. And as there is two sets in parallel that's a total of 2000mAh capacity. If you assuming the LEDs are never triggered, that's an approximate battery lifetime of 2000mAh/90uA = 22222 hours or 2.5 years. In reality if the LEDs are on at least a few minutes a day so that brings the battery lifetime down to under a year.

Driving a MCU

So can this cheap nightlight be used as a PIR sensor for another application? 
So this is what the OUT2 (output of second stage opamp) pin of the PIR IC looks like on an oscilloscope when I walk into the room (about half way though the trace).  So it seems OUT2 tends to about half the supply voltage (1.6V) when there is no activity. Then when a person enters its field of view OUT2 oscillates between 0 and 3.3V.  So if you connect this directly to a digital IO input, all you need to do is detect a transition (high to low or low to high). Apply classic switch debounce logic (except on a multisecond time scale) and you have a occupancy / intruder detection mechanism!

To facilitate my hack, I soldered some think (30AWG) wire to OUT2 , GND / battern -ve and the 3.3V rail (to draw power for my MCU application).


Oscilloscope trace from the OUT2 pin showing a person enter the room at about the half way mark.

Conclusion:

If you can find these in Lidl (it's a very hit and miss thing with them) this can be converted into a nice neat PIR sensor for less money than ordering a dedicated PIR sensor [2]. Plus you get the LED night light functionality and 8 AAA alkaline cells!

References:

[1] Focusing devices for pyroelectric infrared sensors
http://www.glolab.com/focusdevices/focus.html

[2] Adafruit PIR (motion) sensor  ($10)
http://www.adafruit.com/products/189

[3] LP0001 datasheet
http://akizukidenshi.com/download/ds/sctech/LP0001.pdf

[4] BISS0001 datasheet
http://www.seeedstudio.com/wiki/images/2/2f/Twig_-_BISS0001.pdf


Thursday, December 18, 2014

Experiments with the RFM69 433MHz digital transceiver module

Summary: 

This post is an overview of an board I'm developing which encapsulates the RFM69 radio module with a MCU to expose a simple UART API which can be tailored for specific applications. This simplifies embedding a radio into existing applications with very little additional expense in terms of hardware or power budget. The API is implemented by a light weight radio OS (currently just 5KiB) which is open source and the bill-of-materials for the board can be as little as $8 / €7.

Background to project:

WRSC2014 contestant Team FASt from University of Porto.
The World Robotic Sailing Championship 2014 was held in Galway Ireland (my home town) in September this year. It was originally anticipated that each contestant would use a RFM69 radio module to relay real time positioning information back to a central hub for recording the race and scoring. It was also hoped that the race organizers could use the same radio network to broadcast race waypoints, starting times, obstacles etc. However given the short time available it became clear that race contestants would not have sufficient time to incorporate this module into their hardware and write the associated supporting firmware.

Based on the experience of WRSC 2014 I believe the best solution for such competitions is to develop a low cost ready made 'black box' which is given (ready made and programmed) to each contestant. The black box would expose a very simple API to the boat's software which should not take long to integrate. Or if it's a case the contestant simply does not have time to make any changes to their software the radio can be mated with a GPS module and it will send real time position, speed and heading back to the race organizers.

This project is the first step in such a system.  An entire race system will incorporate other elements such as base station software, real time visualization tools, race protocols etc. This blog post only discusses the radio board.

RFM69 family of modules:

The RFM range of modules are made by HopeRF and based on the Semtech radio ICs. The RFM69 comes in several varieties. The one I've been using is the higher power version: the RFM69HW [1] which is based on the Semtech SX1231H [2]  chip.

Feature highlights:
  • Digital SPI interface
  • Operates on 433MHz unlicensed ISM band
  • Continuous or packet mode (66 byte FIFO)
  • Built in AES encryption and CRC-16 engine
  • Configurable bit rates up to 300kbps
  • Configurable power settings
  • Line-of-sight ranges in excess of 1km
  • Sleep current < 1µA
  • Only $4 in small quantities

The radio board:

This is the general architecture of the board: a MCU acts as the go between the application hardware and software and the RFM69 radio module. The MCU takes care of all the complex register configuration of the RFM69 and takes of low level functions (such as responding to pings, remote configuration commands etc) without ever bothering the application. The application talks to the MCU thru a standard UART interface using a very simple protocol.
In addition to the core API there is also the option to compile in application specific functions (for example I've build in support for a rain tip-bucket and a temperature sensor: more on that later).


Prototype mk1:

Unfortunately these modules have a 2mm pad pitch making them difficult to use directly with standard 2.54mm spacing prototype board or breadboard. So for the first prototype I glued the module onto a prototype board and used thin 30AWG wire to link the module pads to pads on the protoboard.


Reasonably need looking from above...



The problem is on the underside...




Even though it's only a hand full of wires, cutting, stripping and soldering these is very time consuming and error prone (well in excess of three hours per board).

For the first prototype I used a LPC810 ARM Cortex-M0+ MCU as the controller.  The ARM Cortex-M range is my MCU of preference these days due to the ease of 32 bit programming, open source and well supported tools and a wide range of vendors (NXP, TI, Freescale etc).

This 8 pin DIP, 4KiB program memory device was adequate for initial tests, but I quickly ran up against the 4KiB program limit. The 8 pin DIP package also had the advantage that I could socket it and try different versions of firmware just by swapping out the device.

With two of these modules I did some range tests. I soldered 17cm wire (quarter wave at 433MHz) to both sides of the board just at the RFM69 antenna output pad. I was able to achieve two way communication of about 1km along the (line-of-sight) length of the Doughiska Road in east Galway city.


Prototype mk2:

For the next prototype I moved to the LPC812: in many ways identical to the LPC810 but with more IO pins and more memory (16KiB program memory, 4KiB SRAM). Rather than use time consuming protoboard I decided it was worth spending some money on a PCB. I designed a two layer board using the free version of CadSoft Eagle and used Eurocircuit's standard FR4 pool to fabricate. This job cost €80, but for that I got 20 boards. The turn around time was nominally 10 working days, but I had them in a week.



The board in the photo actually comprises two boards:  one for the RFM69 discussed here and another for a similar (better?) module the RFM98 which I'll discuss in another blog post. The two halves are separated with a hacksaw.

One very handy feature of the LPC81x range of MCU is the switch matrix which allows many of the MCU functions to be mapped to an arbitrary pin.  This makes PCB layout a lot easier.

After populating with the MCU, module and 3 other components (LED, resistor and decoupling capacitor for MCU) this is what the board looks like. There is the option to use a wire as antenna, or alternatively splash out on a SMA connector (probably the most expensive component on the board!). This photo shows a SMA connector with a 433MHz stub antenna obtained from Farnell [3].



On the left is the UART connector for the radio API, pins for Serial Wire Debug (SWD) for debugging and reprogramming. Left top is the power connector (3.3V nominal, but will work down to 1.8V).

There is also a LED at the very top-left. This is a general purpose indicator that's under control of the MCU. I use this to flash a sequence after boot up tests are complete and flash it each time a packet is sent or received.

In the center there is an option for another connector which will give direct access to the RFM69 SPI port for debugging, or simply using the PCB as a breakout board for the radio module (leaving the MCU pads unpopulated).

The bill of materials is PCB €2;  LPC812M101JD20 €1.50; RFM69HW €3 ; passives, pin headers €0.50; SMA connector (optional) €3.50 ; stub antenna (optional) €5. That's a total of €7 without the SMA connector option. Those prices with the exception of the PCB are for single quantities from Element 14's catalog.  Significant discounts are usually available when ordering 20+. Also components can often be sourced at a much lower cost from Chinese retailers (eg Alibaba and Deal Extreme). The PCB cost is more complex: many fabricators have a fixed job charge (it was about €50 for Eurocircuits) and they then charge per PCB after that. So if you make a lot of them the price per board goes down quickly. If you make just one it will be very expensive.


The radio OS firmware:

My firmware is written in C and currently uses the LPCXpresso IDE to build. This uses the GCC compiler under the hood. The main purpose of the firmware is to expose an simple UART API which the host application uses. The API protocol is simple: a single character command/response code followed by parameters separated by spaces followed by a carriage-return to end the command. All parameters are in hexadecimal. Example:

application to radio:
T 44 5232

'T' means transmit a packet. It takes two parameters: the to-address and the packet payload.

radio to application:
p FF 42 7A14051F003D AD

The 'p' response code is transmitted to the application whenever a packet is received. There are four parameters: the to-address (FF hex being the broadcast address),  from-address, the packet payload and the RSSI (received signal strength indicator). 

Other commands include 'R' and 'W' to read/write RFM69 radio configuration registers. 'M' to switch operating mode from an active awake/listening (20mA current use) to a sleep-polling mode using an average of about 140µA.

Some advanced experimental commands are remote register read/write, allowing a remote radio to be reconfigured. Remote watchdog timer configuration which will reset the radio to default configuration should there be a prolonged loss of communication. Remote command execution (which can be used for remote configuration and to relay packets), remote battery voltage measurement.


Test application:

As mentioned earlier the intended application is for robot sailboat telemetry. But I'm conducting initial tests by using one of these radios with a rain tip-bucket and temperature sensor in my garden. I've got the radio board in an IP66 enclosure with a small PV panel and LiPo battery (and associated charger). 

The tip-bucket causes a magnet to fly past a reed-switch each time the bucket tips. I use this in conjunction with one of the spare LPC812 pins and an interrupt channel to count each time this happens. I've also got a DS18B20 temperature sensor on another spare pin. 

I run this in low power polling mode. Every 30 seconds the MCU comes out of deep sleep mode, makes a temperature measurement and fires up the transmitter and sends a status packet with the tip bucket counter, current temperature, and battery voltage [4]. It listens for about 100ms for a response packet. If none is received it goes back into deep sleep mode. 

If I need to communicate to the out door unit I must wait for a poll packet and then immediately send my command. If multiple commands need to be issued, the first command is to switch the radio into active listen mode, issue all the necessary commands and then put back into low power mode.

So far tests have been successful with the only communications disruptions attributed to either running out of battery charge (it's winter here and the days are short: unless  it's a sunny day there is not enough stored charge to keep it going through the night) or a problem with the USB/Serial cable at the receiving end.

This is 48 hours of some sample data. The disruptions are due to problems with the USB/Serial cable at the receiving end: the radio worked flawlessly. Also note the elevated temperatures are due to the sun falling directly on the IP66 box. 


Current and future work:

I'm currently working an a web browser based application/UI to interact with these radios. The application will allow configuration of the local and remote radios, performing experiments with various radio settings. Monitoring network performance etc.

Also I'm planning to make a third prototype. This will be smaller than the current board, perhaps putting the MCU on the underside of the board. I'm also considering moving to the recently announced LPC82x MCUs [ref] which feature more program flash, more SRAM, a full ADC and other new features.

Features for future firmware include mesh networking, encryption, remote program execution and over-the-air firmware upgrades.


Conclusions:

So far I'm very impressed with these radio modules. At only $4 they're a steal. I've verified two way communication at over 1km distance line-of-sight and I've heard reports of success well in excess of 1.5km line-of-sight. With the addition of an LPC812 MCU with my radio OS and simple UART API, embedding this radio into an application is far simpler than building the radio driver directly into the application software. The entire bill of materials is about $7 with the option of a SMA connector which might bring it to $10. My PCB layout is available under the BSD licence on GitHub [5] and the firmware is also available on GitHub [6].


Footnotes:

[1] RFM69 Datasheet
http://www.hoperf.cn/upload/rf/RFM69-V1.3.pdf

[2] Semtech SX1231H product information and datasheet
http://www.semtech.com/wireless-rf/rf-transceivers/sx1231h/

[3] Farnell/Element 14 SKU 2305893, €4.86 in single quantities.

[4] One feature I miss in the LPC81x range of MCU is a full ADC. There is however a comparitor which can be used with a voltage ladder to make crude voltage measurements. I use this for battery voltage measurement (Vcc thru voltage ladder on one comparitor input, and the built in 0.9V voltage reference on the other). In my tests it can detect low battery voltage condition, but due to the coarse resolution I get a warning only about a hour before the voltage drops below the cutoff threshold.

[5] https://github.com/jdesbonnet/RFMxx_LPC812

[6] https://github.com/jdesbonnet/RFM69_LPC812_firmware

Updates:

11 Feb 2015: Added link to firmware repository on GitHub.

Sunday, August 31, 2014

Open IC Register Description Language (a proposal)

Summary: Many modern digital ICs are interacted with through memory mapped registers. Writing maintainable code demands a header file with well structured constants for register addresses, bit field masks, field values etc. But even that on its own doesn't guarantee readable code. It is often desirable to have a summary of the register function, and values in a comment block above the code. But this can be very onerous, involving lots of cutting/pasting/formatting from the datasheet. My proposal is a standard machine-readable way to describe a ICs registers using an open format. These descriptions can be used to generate constant header files for any language, automatically document code and provide useful plugins for IDEs. I also propose to crowd-source an open source data repository of such description files for popular ICs. 
I've been writing some embedded C recently, and trying to document my code as I go along. When I access an IC register I include the following information above the code block:
  • The datasheet document name and revision number
  • The relevant section / table number/ page number in the datasheet
  • A short description of the register / bit field being accessed and allowed values
This can get quite tedious cutting/pasting text from the datasheet. Any time something is cut/paste more than twice is a strong indicator that you are doing something wrong.

I went looking for any standard machine-readable way to document IC registers and found nothing (so far). So I'm proposing an open standard and open database to document IC registers.

This will have several benefits for developers:
  • automatically generate header files for what ever language is being used with register addresses, bit masks, field values etc. Automatic generation guarantees a consistent format.
  • automatically generate data structures for large/complex registers
  • automatically document code by making a single reference to a register / bit field
  • allow tight integration with IDEs (eg debugger can display annotated register values along with the actual meaning of that value)
I'm not a big fan of XML, but it does seem to be the standard for this kind of thing. So my proposed IC register description will look something like this:

<?xml encoding="utf-8">
<device name="RFM69">

<description>
HopeRF RFM69/RFM69HW radio module
</description>

<register>
<sname>OpMode</sname>
<name>Operation Mode</name>
<address>0x01</address>

<bitfield bit="7" rwmode="rw">
<sname>SequencerOff</sname>
<description>Controls the automatic Sequencer (see section 4.2)
<value val="0"></value>
<value val="1">Mode is forced by user</value>
</bitfield>

<bitfield bit="6" rwmode="rw" type="onoff">
<sname>ListenOn</sname>
<description>Enables Listen Mode, should be enabled whilst in Standby mode.</description>
</bitfield>

<bitfield bit="4:2" rwmode="rw">
<sname>Mode</sname>
<description>Tranceiver's operating mode</description>
<reference>section 6.2</reference>
<fieldvalue><value>0</value><sname>SLEEP</sname><name>Sleep mode</name></fieldvalue>
<fieldvalue><value>1</value><sname>STDBY</sname><name>Standby mode</name></fieldvalue>
<fieldvalue><value>2</value><sname>FS</sname><name>Frequency Synthesis mode</name></fieldvalue>
<fieldvalue><value>3</value><sname>TX</sname><name>Transmitter mode</name></fieldvalue>
<fieldvalue><value>4</value><sname>RX</sname><name>Receiver mode</name></fieldvalue>
</bitfield>

</register>


<register>
<sname>DataModul</sname>
<description>Data modulation settings</description>
.... etc....
</register>

</device>


Some notes about the schema: Along with a human friendly register name, I've got a short-name. This will conform to C identifier specification and is used in header file generation.

The resulting header files can be generated from rules (which can be changed according to house style). For example my rule is: <IC>_<REG> for register address, <IC>_<REG>_<FIELD>_MASK for bit field masks, and for each field value <IC>_<REG>_<FIELD>_<FIELDVALUE>. So from the XML example above I get something like this for the C language header file:

#define RFM69_OPMODE (0x01) /* Operation mode register */
#define RFM69_OPMODE_MODE_MASK (7 <<2)
#define RFM69_OPMODE_MODE_SLEEP (0<<2) /* Sleep mode */
#define RFM69_OPMODE_MODE_STDBY (1<<2) /* Standby mode */
#define RFM69_OPMODE_MODE_FS (2<<2) /* Frequency synthesiser mode */
#define RFM69_OPMODE_MODE_TX (3<<2) /* Transmitter mode */
#define RFM69_OPMODE_MODE_RX (4<<2) /* Receiver mode */

Code documentation.

Comment annotations can instruct a code post-processor to insert/update the necessary documentation. For example:

/**
 * Set transceiver mode to transmit
 * @register RFM69_OPMODE.MODE
 */

Will get expanded to something like this:

/**
 * Set transceiver mode to receive
 *
 * @register RFM69_OPMODE.MODE
 *
 * RFM69_OPMODE.MODE autodoc. Do not edit. ****
 * RFM69 datasheet, section 6.3
 * OPMODE MODE (bits 4:2). Read and write allowed. Values:
 * SLEEP (0) : Sleep mode ;  STDBY(1) : Standby mode ;
 * FS (2): Frequency synthesis mode ; TX (4): Transmitter mode;
 * RX (4): Receiver mode
 * End RFM69_OPMODE.MODE autodoc
 */

Note the auto generated sections are delimited by a marker. While this may generate verbose source code it will be easier to read (especially for someone new to the hardware) and can be easily maintained/updated or removed as required.

This can also be helpful for non-english speaking developers. Any text element in the register description can have a lang (language) attribute. So a developer can switch out the english descriptions for one in their native language (either permanently or temporarily with an IDE plugin).

The open database:

I propose that these IC description files are uploaded and maintained on something like GitHub repositories. For ease of maintenance, it might be an idea to split the description file into a separate file for each register. A suitable licence must be used to ensure the generated header files and documentation do not cause any licencing restriction on developers.

Other features/ideas:
  • Chip variants or silicon revisions can be accommodated by linking to a root document and then including only items that have been changed.
  • IDEs can generate convenience routines eg in the example above function rfm69_mode_set (mode); rfm69_mode_get(); etc
  • IDEs can use this description to visually annotate register bit fields in the debugger
  • Complex configurations and sequences can be documented by the manufacturer in a machine-readable but language neutral way.
  • Support i18n, allowing a language attribute for any text fields.
  • Editing XML directly is tedious and error prone. A web app could be used as a front end for editing and maintaining such a database.
  • What I've proposed is only for registers, but other common information could also be included (pin outs, voltage/current ratings etc)
I've stared writing some utilities to implement some of these ideas for an internal project which I'll release as an open source project soon (probably under a BSD style licence). I'd be delighted to hear from anyone who is aware of any similar efforts (I really don't want to reinvent the wheel here), or would like to critique or contribute.

Updates:

3 Sep 2014: I've created a GitHub respository for this project at https://github.com/jdesbonnet/ICRDL

Tuesday, June 10, 2014

Weight charts from wwdiary, part 2

In part 1 [1] I described a way of generating nice weight charts from the data stored in the wwdiary [2] weight loss app.

I record a daily weight measurement, usually first thing each morning. As one would expect this can vary a lot from day to day for all sorts of reasons. To get a better handle of the trends a smoothing filter can be applied to the data. There are many methods of doing this, eg Moving Averages. The one I've opted to use here is the Leaky Integrator [3] due to its simplicity.

The unsmoothed chart looks like this.


The following is a GnuPlot chart that applies the Leaky Integrator smoothing to the data (assumed to be in file weight.dat, see part 1 on how to extract this from the wwdiary database):

# GnuPlot script to plot smoothed weight from datafile in format
# uuuuuuuuuu ww.w
# Where uuuuuuuuuu is date in unix epoch time
# and ww.w is weight (in kg here, but trivial to change to other units).
# One record per line. 
# 
# Smoothing is acomplished with the Leaky Integrator
# http://en.wikipedia.org/wiki/Leaky_integrator
# 
# Joe Desbonnet, jdesbonnet@gmail.com, June 2014.
#
set xdata time
set timefmt "%s"
set format x "%m/%Y"
set xtics font "Arial, 10" 
set title "Smoothed Weight Loss Curve using Leaky Integrator λ=0.8"
set xlabel "Time"
set ylabel "Mass (kg)"
set grid
set key off
set term pngcairo size 800,400
set output "weight.png"
# Lambda (0 ≤ λ < 1.0) determines smoothing. Higher values for more smoothing.
lambda=0.8
ym1=0
leaky_integrator(x) = (ym1 = ym1==0 ? x : (1-lambda)*x + lambda*ym1)
plot 'weight.dat' using 1:(leaky_integrator($2)) with linespoints, \
     'weight.dat' using 1:2 lt 3


After applying the smoothing filter (and plotting the original points in blue for reference):


You can adjust the 'strength' of the smoothing filter by changing the value of lambda. Lambda can vary from 0 to 1. The closer to 1 the higher the smoothing effect.

References:

[1] http://jdesbonnet.blogspot.ie/2014/06/weight-charts-from-wwdiary-part-1.html
[2] https://play.google.com/store/apps/details?id=com.canofsleep.wwdiary
[3] http://en.wikipedia.org/wiki/Leaky_integrator

Monday, June 9, 2014

Weight charts from wwdiary, part 1

I've been using an excellent Android app called wwdiary [1] for over two years to lose (and then manage) my weight. The app allows you to record your daily weight, but unfortunately has no inbuilt charting [2]. So I wrote a script to extract the data and make my own charts.

Here is my chart:

Here's how to make your own:

This recipe requires a few command line tools. I'm using Linux, but to the best of my knowledge all these tools are available for Windows and Mac and should work exactly the same way described below. You'll need SQLite (there are several implementations), and GnuPlot.

wwdiary uses the SQLite database engine for storage, and you can grab a copy by going into the app settings and saving a copy of the database to SD Card. Copy this file to your computer using whatever file transfer tools you have to hand (I often just email it to myself using the gmail app file-attach option). Let's call this file wwdiary.database.

First you need to extract the weight from the SQLite database in a format that's easy for GnuPlot to parse.  Create a SQLite script file. Let's call it extract_weight.sqlite:

.separator "\t"
select date/1000,weight*0.453592 from weightlog;
.quit

Note the "/1000" is to convert the unix epoch timestamp in milliseconds to seconds and the "*0.453592" is to convert imperial pounds used internally in the app [3] to kg. Run the script and send the output to weight.dat:

sqlite3 wwdiary.database < extract_weight.sqlite > weight.dat



The contents of weight.dat should look something like this:

1379890800 76.2999384291992
1379977200 76.0999346446533
1380063600 75.6999409180908
1380150000 75.5999355651855
...

Create the plot script, call it say weight.gp:

# GnuPlot script to plot weight in format
# uuuuuuuuuu ww.w
# Where uuuuuuuuuu is the unix epoch time in seconds
# and ww.ww is weight (I use kg, but use what you like).
# 
# Joe Desbonnet, jdesbonnet@gmail.com, June 2014.
#
set xdata time
set timefmt "%s"
set format x "%m/%Y"
set xtics font "Arial, 10" 
set title "Weight Loss Curve"
set xlabel "Time"
set ylabel "Mass (kg)"
set grid
set key off
set term pngcairo size 800,400
set output "weight.png"
plot 'weight.dat' using 1:2 with linespoints


And now run it:

gnuplot weight.gp

All going well, you should find a PNG image file called weight.png in the same folder with your weight chart.

In part 2 I'll show you how to apply a smoothing filter to the chart.

References

[1] https://play.google.com/store/apps/details?id=com.canofsleep.wwdiary
[2] There is a subscription service available where a chart can be viewed on an online dashboard.
[3] Oh please if you're designing software use SI (metric) units under the hood. Convert to antiquated Olde Worlde/American units at the user interface if you must. Even the Apollo moon avionics software from 1960s USA calculated in SI, converting to feet, furlongs, hundred-weight etc only at the last second at the user interface. (See http://dodlithr.blogspot.ie/2011/10/apollo-guidance-computer-agc-software.html)