Since it costs almost nothing to run another test while I’m in bed…
I found another Tenergy battery that had never been used as far as I could tell.  It had the solder tags on the ends.  I charged it up and ran another test.

The fresh battery measured at 4.2V.  The battery measured 1.42V when the test finished after 14465 seconds/ranges.   Towards the end of the test (around 14300) the ranges started getting progressively longer, ending up in the 1.7m region by death.  But that’s just during the final 3 minutes, or almost 4 hours.

Results

14300 decent ranges.
3575 3D location fixes.
Assuming each range is the median of four samples, then we get 894 fixes.

Thoughts from David

1) The 5V to 3.3V regulator on the EVK1000 is a TI TPS73601DRB analog regulator with a 0.075V dropout voltage. It won’t make any accommodation for battery voltage less than the operating voltage of the DW1000.
2) The lithium batteries are getting old and might have high internal resistance so when the DW1000 is ranging it might be drawing down the battery voltage a lot. But maybe not. The capacity might not be (certainly isn’t ) what it was when the batteries were new.
3) The Eval board is drawing other power, like for the display. The board probably isn’t designed for lowest power consumption.
4) The coulomb counter wasn’t counting coulombs because current wasn’t flowing through the sense resistor so the 11000 number isn’t valid. The display read less because the battery voltage was lower – so the situation is actually worse. Probably most of the 21000 coulombs is gone. But since the battery is at least partially worn out some of the coulombs that went is weren’t available to come out, because the energy was lost as heat (probably).
If we want to do a “real” power test we need the modules working with a proper switching supply powered by these supercaps I have. This is another reason to fab a PCB.

Conclusions from Mik

This clearly wasn’t a well-controlled test, in almost any respect, but it gave me a feel for the challenges we are up against using the DW.     The little lithium that David bought for the TS06 has 240mAh capacity, so we are only talking 225 location fixes.  
Of course, allowing the battery to recover a bit between fixes, and not needing to sample over 4 fixes could make 4x  difference.
That’s not an actual show-stopper if one can choose the ranging opportunities with care.  How many times in a day do we actually settle?

Today I thought I’d do a rough and ready experiment to see how long it takes for one of the TS05b rechargeable batteries to run down.  I’m hoping this will give me some clue about how many new-style range events I can perform on one battery.

I have set the program to range once/sec, and I’m going to count how many seconds it is until the battery powered unit stops responding.

I put it into the TS05b to charge and measure it with the gas guage.  It measured 4.2V and 22157 Coulombs in the tank, when I transferred it to the DW EVK, at 6.18pm.

I don’t have an on-board RTC to print out the time when it stops, so I’m simply incrementing a 1Hz counter each time there is a successful range operation.

Results

The 900mAh battery pooped out at 3h 41m.  I put it back into the TS05b to measure it rather than using the Fluke(Doh).  It showed 3.5V.  The gas gauge said it had 10610C left in it.  That’s 1 Coulombe/range – an easy, but probably meaningless statistic?

Just as interestingly, about 20 minutes beforehand the range estimates increased by 20 cms.  So clearly I have to keep an eye on that detail.  Why does it increase though?  Clock slow?

So bottom line is that we can get about 12000 good range estimates.  That’s 3000 3D fixes at 4 ranges per fix.

But let’s assume we need to take the median of 4 ranges to get a good fix.  Then it falls to 750 fixes/battery.  That’s about 1 good fix per 1mAh!  Oh jeez, I have a problem 🙁

N.B. In the following, the first number is the number of times the software polls the DW between ranges, not particularly important.  The last two numbers are <elapsed seconds>: <range>

136733 Me:0 Other:100999205E37F8FD 11253: 1.02
136784 Me:0 Other:100999205E37F8FD 11254: 1.10
136717 Me:0 Other:100999205E37F8FD 11255: 1.05
136844 Me:0 Other:100999205E37F8FD 11256: 1.05

136714 Me:0 Other:100999205E37F8FD 12007: 0.96
136735 Me:0 Other:100999205E37F8FD 12008: 1.04
136754 Me:0 Other:100999205E37F8FD 12009: 1.00
136726 Me:0 Other:100999205E37F8FD 12010: 1.05
136802 Me:0 Other:100999205E37F8FD 12011: 1.08
136884 Me:0 Other:100999205E37F8FD 12012: 1.09
136830 Me:0 Other:100999205E37F8FD 12013: 1.07
136798 Me:0 Other:100999205E37F8FD 12014: 1.04
136748 Me:0 Other:100999205E37F8FD 12015: 1.03
136791 Me:0 Other:100999205E37F8FD 12016: 1.01
136810 Me:0 Other:100999205E37F8FD 12017: 1.02
136708 Me:0 Other:100999205E37F8FD 12018: 0.99
136705 Me:0 Other:100999205E37F8FD 12019: 1.08
136843 Me:0 Other:100999205E37F8FD 12020: 1.08
136808 Me:0 Other:100999205E37F8FD 12021: 1.05
136876 Me:0 Other:100999205E37F8FD 12022: 1.10
136824 Me:0 Other:100999205E37F8FD 12023: 1.08
136747 Me:0 Other:100999205E37F8FD 12024: 1.08
136714 Me:0 Other:100999205E37F8FD 12025: 1.08
136881 Me:0 Other:100999205E37F8FD 12026: 1.05
136778 Me:0 Other:100999205E37F8FD 12027: 1.04
136726 Me:0 Other:100999205E37F8FD 12028: 1.11
136720 Me:0 Other:100999205E37F8FD 12029: 1.03
136879 Me:0 Other:100999205E37F8FD 12030: 1.07
136737 Me:0 Other:100999205E37F8FD 12031: 1.11
136829 Me:0 Other:100999205E37F8FD 12032: 0.99
136820 Me:0 Other:100999205E37F8FD 12033: 1.03
251146 Me:0 Other:100999205E37F8FD 12034: 1.28  Something happens around here…
136881 Me:0 Other:100999205E37F8FD 12035: 1.25
136799 Me:0 Other:100999205E37F8FD 12036: 1.16
136795 Me:0 Other:100999205E37F8FD 12037: 1.21
136746 Me:0 Other:100999205E37F8FD 12038: 1.13
136814 Me:0 Other:100999205E37F8FD 12039: 1.09
136880 Me:0 Other:100999205E37F8FD 12040: 1.19
136707 Me:0 Other:100999205E37F8FD 12041: 1.10
136778 Me:0 Other:100999205E37F8FD 12042: 1.22
136886 Me:0 Other:100999205E37F8FD 12043: 1.18
136709 Me:0 Other:100999205E37F8FD 12044: 1.17
136828 Me:0 Other:100999205E37F8FD 12045: 1.11
136823 Me:0 Other:100999205E37F8FD 12046: 1.20
136868 Me:0 Other:100999205E37F8FD 12047: 1.24
136783 Me:0 Other:100999205E37F8FD 12048: 1.22
136737 Me:0 Other:100999205E37F8FD 12049: 1.26

136800 Me:0 Other:100999205E37F8FD 12050: 1.18

136756 Me:0 Other:100999205E37F8FD 13253: 1.54
136821 Me:0 Other:100999205E37F8FD 13254: 1.43
136715 Me:0 Other:100999205E37F8FD 13255: 1.46

As delivered the ranging system operates at 100kbps.  Presumably that’s the symbol rate.  At the other end of the scale it works at 6.8Mbps.  I tried both speeds and it seems like the effective range is a little longer at the slower data rate.

The ranging protocol relies upon the peers taking a known, and fixed amount of time to respond to a ranging request.  The code indicates that this is 150ms!   Unless the peers can sleep, that’s a long time to have to remain awake every range event.  When the EVB1000 is connected to a PC, the turnaround time is set to 750ms!  Yup 3/4 second.  Since there are two fixed period turnarounds, the total ranging time is in excess of 1.5s.

Fortunately, a feature of the DW chip is it’s ability to schedule transmissions, and receptions for some time in the future, and to sleep while waiting (or is it to let the processor sleep while it waits?) Without that, I reckon the power budget would be horrendous.  Nevertheless, it means that to perform the four one-shot range operations required to locate yourself in 3D, it would take  150*2*4 ms = 1.2 seconds.  A moving person could travel 6-10 feet in that time, so there would be a much higher probability of trying to do trilateration (is it really quadlateration) with a degenerate set of coordinates. (i.e. the ranges don’t intersect, so can’t specify an area, let alone a single point).  My experiments so far, show that one-shot ranges are way off, and that it isn’t until the second try that it get’s reasonable.

The DW code claims to have some options to allow “fast ranging”.  I think they are assuming that the two peers are using identical processors and software, and that the turnaround delay is proportional to the time it takes to transmit the ranging packet.

The question they are trying to answer is, “If radio A sends a ranging packet to radio B, how briefly can radio A sleep for before expecting to hear back from radio B”.   This is puzzling.  Radio A must stay awake until the last bit of the packet is sent.  Assuming that the processor attached to radio B takes minimal time to turn the packet round and have the radio send it out, then why would radio A need to sleep for more than a trice before it has to wake up to catch the first bits of the return packet.  This doesn’t seem like a big win.

Of course they might be trying to let processor A sleep as soon as it has handed over it’s packet to the DW, and not be awoken until the return packet has been received.  In that case the delay until being awoken should be about the time it takes to send two ranging packets.

Looking through the code it appears they try to calculate the minimum fixed delay time based on the time it takes transmit a range packet.   I don’t understand the calculations, but they have parameters that measure the length of the fixed, and variable parts of a ranging packet under different transmission modes.  At 110Kbps the delay appears to be much longer than at 6.8Mbps, but doing their math in my head doesn’t produce the result I expect.  There are a bunch of fudge factors, and these seem to be significant.

Anyhow, the final calculation seems to result in a number that is less than 600us which is more appetizing.  With that you could quadlaterate in < 5ms (200Hz) which is very respectable.  Of course there are actual legal restrictions on how much UWB traffic you put into the ether, so there may be other limitations.

However, and much more importantly, I can’t get the “fast ranging” to work.   Comments in the code indicate that it only works at 6.8Mb, but all my attempts to configure it as suggested fail, and the two nodes can’t find each other.

I’m looking to put the DW1000 into a deep sleep, and then to wake it up and start ranging operations. Here’s the output from the text program, which is actually DW’s program that I have hacked a bit.

Semihosting operational                    trace messages via semi-hosting   
DW1000 now in (deep?) sleep mode           put  DW1000 to sleep


DW1000 failed to respond                   provably not responding

Clear chip select and wait 200us           slowly toggle chip select
Set chip select and wait 5000us

Retry DW1000
                               see if it responds now?
DW1000 responding
                                         
TAG mode                                  
set myself in tag mode
TAG BLINK 100886205E37F75A               beacon my 64bit address
080018 Me:0 Other:100999205E37F8FD 1.28    ranges to “other”
138060 Me:0 Other:100999205E37F8FD 1.04
138018 Me:0 Other:100999205E37F8FD 1.10
138119 Me:0 Other:100999205E37F8FD 1.04
138123 Me:0 Other:100999205E37F8FD 1.04

For some reason the first range is always about 20 cms too large.  I’ve tried this perhaps 20 times, and it is consistently too big.

However, the Nanotron always had to do 3/4 range operations before it stabilized!
Of course I don’t know if this process is actually saving any power.  I have not figured out how to measure that yet.
Their code is ambiguous about whether the crystal is turned off or not.  The code claims it is, but the comments in the code claim it isn’t.

Observed Power

I found instructions for measuring the current.  All I have is a clunky Fluke, but it seems to measure something or other that’s changing.

If I turn the crystal off during deep sleep, the Fluke reads 0mA.  If I leave the crystal on, then it reads 3.67 mA.  Can it be true that the crystal is sucking that much power, or is this a measuring science issue?  According to the spec, sleeping ought to cost a few uA.

The other problem is that when the Fluke is connected to the tag node the ranging doesn’t work.  If I connect the Fluke to the anchor node (which is battery powered) it does work.  Maybe I should swap the PSUs over and see if it makes any difference.

Useful general numbers

TX    70mA
RX    30mA
Sleep 1uA
A small ranging packet takes about 200uS to send or receive.

Useful specific numbers for Tag ranging

Poll 176uS
Idle 312uS
RX   192uS
Idle 320uS
TX   ~192uS

Useful specific numbers for Anchor mode

Idle after responding to poll  312uS
Receive Poll                   192uS
Respond                        180uS
Idle                           300uS
Receive final                  220uS

I’m inserting trace message into the DW code so that I can try to understand what it does.

I’d like to figure the simplest sequences to do the following:

  1. Power-up from off, or very, deep sleep;
  2. Power down, or enter very, deep sleep;
  3. Get ready to receive and respond to a ranging request;
  4. Issue a ranging request, and capture the result.
My cursory work through the code suggests that I’m being a bit naive about the complexity.

Earlier, I said that I didn’t think any particular pin configuration really mattered, and I have not changed my mind… yet anyway.

They specify two sets of SPI pins, but it looks like they may dedicate one complete set for their LCD. But why?  Perhaps it is super slow, and locks out the radio which perhaps has some crisis time?

They may have four LEDs connected directly to the DW chip.

#define GPIO_MSGP0_MASK 0x000000C0UL /* Mode Selection for GPIO0/RXOKLED */
#define GPIO_MSGP1_MASK 0x00000300UL /* Mode Selection for GPIO1/SFDLED */
#define GPIO_MSGP2_MASK 0x00000C00UL /* Mode Selection for GPIO2/RXLED */
#define GPIO_MSGP3_MASK 0x00003000UL /* Mode Selection for GPIO3/TXLED */

#define GPIO_MSGP4_MASK 0x0000C000UL /* Mode Selection for GPIO4/EXTPA */
#define GPIO_MSGP5_MASK 0x00030000UL /* Mode Selection for GPIO5/EXTTXE */
#define GPIO_MSGP6_MASK 0x000C0000UL /* Mode Selection for GPIO6/EXTRXE */
#define GPIO_MSGP7_MASK 0x00300000UL /* Mode Selection for SYNC/GPIO7 */
#define GPIO_MSGP8_MASK 0x00C00000UL /* Mode Selection for IRQ/GPIO8 */

I found this comment, which could be useful for debugging is some places to hang a scope:

//NOTE:……
//this can be seen on the scope when GPIO5 is configured as EXTTXE output and GPIO6 as EXTRXE output


Following on from our phone conversation earlier today, I decided to do some memory budgeting to see how much of a fix we are in.  I’m relieved that there is a 32K RAM Nordic available.  Sadly I don’t see more flash on the horizon.

Leaning on this: http://electronics.stackexchange.com/questions/127667/what-are-the-resource-requirements-ram-flash-of-the-latest-nordic-bluetooth-s
I learned the following:

The latest S110 v7 softdevice uses 88 kB flash and 8 kB of static RAM for S110 leaving 168 kB of flash and 8 kB of RAM for the application (for the 256k chip). Also note that S110 v7 can use over 1.5 kB of stack, so you must make sure that your stack is big enough to accomodate both this and your application’s requirement. 

Lastly, when you use the S110, it also restricts many of the Programmable Peripheral Interconnect (PPI) channels, leaving on 8 channels free for the application code. This restricts how you implemet peripherals such as PWM and I2C.

The DW test program which simply handles ranging provides a rough estimate for the code we will need to talk to the DW chip from the Nordic.  It uses 68K flash, 6.5K of RAM.
So before we get to write any application code our memory footprint looks like this:
                 BLE    DecaW     TOTAL
          Flash   88 +  68      = 156K
          RAM      8 +   6.5    = 14.5K*

*This does not account for stack, or heap.  The BLE call stack can need 1.5K by itself which could drive our RAM footprint up to 16KB, which is all we have on the current module.


We have about 100KB left for code development which I’m estimating will become a headache by itself in about a year.  Apart from actual application code, we have to include driver code for the other chips, which could take another 30%.
The DW code is compiled under -O0 (no optimization).  Optimaztion may save 10%.  There may well be a bunch of drivers and library routines that have been eroneously dragged into my DW test compilation, and are not used.  Maybe we can save another 10%

Bottom line

RAM is going to be tight, until we get the 32KB modules.  Flash is not an immediate issue, but two factors will quickly make it one:  other device drivers (IMU/Bat monitor);  Storage for sensor/range data.  I think off-chip memory is on the near horizon.

Today, I scratched around some more and finally decided I had to ask for help.  This was just soaking up a lot of time, doing random things that I thought might be the cause of the problem. i.e. not based on any real evidence.

So I tooled a message for David to send to Leo.

Thank heavens, that David had the good sense to read my drivel before he sent it.  It appears Leo actually sent us a revised IDE installation document last week.

Hi David
The attached Eclipse doc is the latest.
Is that not the one I gave you?
Regards,
Leo Theunissen

David figured, I hadn’t noticed it and sent me a nudge.   It’s not easy being so stupid.  What a waste of bloody time.
—————
So I printed off a new version of the document and carefully went through all the installation steps. It’s a lot, lot better, but there are still issues.

43 files compiled with mere warnings, but it finally ground to a halt with some “Assembler messages”.  Who knows what this means?

‘Building file: ../Libraries/CMSIS/CM3/CoreSupport/core_cm3.c’
‘Invoking: Cross ARM C Compiler’
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -w  -g3 -DSTM32F10X_CL -DUSE_STDPERIPH_DRIVER -I”C:UserslammingworkspaceDecaRangingMPEVBLibrariesSTM32F10x_StdPeriph_Driverinc” -I”C:UserslammingworkspaceDecaRangingMPEVBLibrariesSTM32F10x_StdPeriph_Driversrc” -I”C:UserslammingworkspaceDecaRangingMPEVBLibrariesCMSISCM3CoreSupport” -I”C:UserslammingworkspaceDecaRangingMPEVBLibrariesCMSISCM3DeviceSupportSTSTM32F10x” -I”C:UserslammingworkspaceDecaRangingMPEVBsrcapplication” -I”C:UserslammingworkspaceDecaRangingMPEVBsrccompiler” -I”C:UserslammingworkspaceDecaRangingMPEVBsrcdecadriver” -I”C:UserslammingworkspaceDecaRangingMPEVBsrcplatform” -I”C:UserslammingworkspaceDecaRangingMPEVBsrcsys” -std=gnu11 -MMD -MP -MF”Libraries/CMSIS/CM3/CoreSupport/core_cm3.d” -MT”Libraries/CMSIS/CM3/CoreSupport/core_cm3.o” -c -o “Libraries/CMSIS/CM3/CoreSupport/core_cm3.o” “../Libraries/CMSIS/CM3/CoreSupport/core_cm3.c”
C:UserslammingAppDataLocalTempccKeD9Ks.s: Assembler messages:
C:UserslammingAppDataLocalTempccKeD9Ks.s:772: Error: registers may not be the same — `strexb r3,r2,[r3]’
C:UserslammingAppDataLocalTempccKeD9Ks.s:818: Error: registers may not be the same — `strexh r3,r2,[r3]’
cs-make: *** [Libraries/CMSIS/CM3/CoreSupport/core_cm3.o] Error 1

Aha!  http://www.atollic.com/index.php/kb/1-kb_building/117-kb_error_in_strexb

In the tool chain included in TrueSTUDIO up to version 5.0 there where a bug in gcc for optimization level -O0 that would allow the code to compile with that optimization.
Hot to change to a lower optimization level for STREXB and STREX:
Find the functions __STREXB and STREXH. They are located in the CMSIS libraries. The exact position for the libraries depends on the project organization.
Change the function prototypes for these two function to set a lower optimization level with [optimize(“O0”)].
But I already have optimization “O0”  and the precise fix they recommend doesn’t match my source.
—————
So the software that they suggest you download from ST is out-of-date.  It seems pretty clear tome that nobody has run through the DW instructions.
I managed to find a more modern version out on the web.  

I downloaded it and patched in the new core_cm3.c and tried to rebuid.   Got exactly the same error.   This time I opened up the code and it seems to match the reported buggy code.  So I made the suggested alteration to the new code described here:  http://www.coocox.org/forum/topic.php?id=943

I think there is an error in core_cm3.c file at CoIDE 1.7.1.
I had the same issue with Sourcery CodeBench gcc 4.7.2 and it was resolved after editing cmsiscore_cm3.c file in my project’s directory.According to this thread you should edit functions __STREXB and __STREXH by changing “=r” to “=&r”.
You’ll see code:
__ASM volatile (“strexb %0, %2, [%1]” : “=r” (result) : “r” (addr), “r” (value) );
Should be:
__ASM volatile (“strexb %0, %2, [%1]” : “=&r” (result) : “r” (addr), “r” (value) );

I ended up with two edited lines in ___STREXB and __STREXH

(line 736) __ASM volatile (“strexb %0, %2, [%1]” : “=&r” (result) : “r” (addr), “r” (value) );
(line 753) __ASM volatile (“strexh %0, %2, [%1]” : “=&r” (result) : “r” (addr), “r” (value) );

I saved and recompiled.
Yay… it compiles now!

The important statistics we have been waiting to see are:

   text   data    bss    dec    hex filename
  67992   1552   4992  74536  12328 DecaRangingMPEVB.elf

  • text is basically the code that lives in flash.  Initializers for variables that live in RAM will be placed here too, but don’t contribute to the text size.
  • data is pre-initialized variables, that lives in RAM.  The initializers will be in flash, and will get copied to ram before the main routine is called.
  • bss is un-initialized variable storage that lives in RAM.
  • dec and hex are the total size of everything expressed in decimal and hex.  It’s not useful unless you are worried about storing/transmitting the image for subsequent download.

Yay… it downloads now.
Yay… it runs.

 

I’ve been thinking about drones which are in the news again.

Objectives recap

Topology mapping recap

I espouse the idea that we can do a lot without making a map.  I think it’s still critical to be able to do things without a map.

If we had an easy way to add a map then it could enable a lot of extra capabilities.

One thing I’m pretty sure we can do is sense the position of an object to within a meter, or less.  So I can imagine having a tiny, and very inexpensive drone with a TV camera that could follow you around the house.

Take the drone out of the box, and remove the paper strip maked “Remove me first”.   Set the drone on the floor in front of you.  Put on your wrist band.  Wave your hand over the top of the drone <somehow> until the red light on the drone comes on. Now walk away from the drone, and sit still somewhere you can see the whole room.  In a few seconds the drone will start, and slowly rise into the air.  It will slowly hover around around the room taking pictures.  Don’t move until it lands again.

Walk into another room, and the drone will follow you.  Sit down and the drone will survey this room.

Move to each room in turn until you are done, and then walk towards the drone and wave your hand over it.  You are done.  Put the drone back in it’s little box, and put it way somewhere safe. 

The drone builds a 3D map using techniques like these.
Project Tango