It’s been a struggle but I have an S130 simultaneously listening for broadcasts, while advertising, and able to listen for UI connections.

Receiving a broadcast advertising packet from another node called “Z1”.  The example packet contains a maximally-sized 20-byte block of “proprietary data”, i.e. it doesn’t conform to the BLE standard and will only make sense to TS devices.
TS (7) [c7.60.61.56.c1.bf] – BLE_GAP_EVT_ADV_REPORT                              
  T9(2)NAME Z1    Field type and length                                  
  T1(1)FLAGS 04                                                                  
  T255(22)TS_PROPRIETARY_DATA [(20), 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ]

It requests second block of data from the broadcaster – the so-called scan response data.   (For some reason this appears to come from a different MAC address – 0xbe instead of 0xbf?? )  This block contains the state of the sender’s battery, and the temp – just random bits of data it was easy to provide.
TS (8) [c7.60.61.56.c1.be] – BLE_GAP_EVT_ADV_REPORT
  T22(3)BLE_UUID_BATTERY_SERVICE 100%              
  T22(6)BLE_UUID_HEALTH_THERMOMETER_SERVICE 34C    

Now I use my Android phone and an off-the-shelf applciation to make a “TS_UART” connection to the S130.  TS_UART is a connection that simply sends and receives strings of characters (up to 20).
———————-
UI connected.
———————-

While waiting for some activity on the connection it continues to report broadcast packets…
TS (9) [c7.60.61.56.c1.c6] – BLE_GAP_EVT_ADV_REPORT                              
  T9(2)NAME Z1                                                                   
  T1(1)FLAGS 04                                                                  
  T255(22)TS_PROPRIETARY_DATA [(20), 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ]                                                                 
TS (10) [c7.60.61.56.c1.c6] – BLE_GAP_EVT_ADV_REPORT                             
  T22(3)BLE_UUID_BATTERY_SERVICE 100%                                            
  T22(6)BLE_UUID_HEALTH_THERMOMETER_SERVICE 34C                                  
TS (11) [c7.60.61.56.c1.c6] – BLE_GAP_EVT_ADV_REPORT                             
  T9(2)NAME Z1                                                                   
  T1(1)FLAGS 04                                                                  
  T255(22)TS_PROPRIETARY_DATA [(20), 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ]  

I type a string “buddy” into my phone UI and press “send”.  This is the interim mechanism I intend to use to configure each node, and to query it for statistics and so forth.
———————-    
UI received string “buddy”
———————-    

.
.
At the same time, in another typescript window, a peer is receiving broadcast packets from the S130, demonstrating that (with some kludgery) it is possible to send and receive broadcast packets at the same time.

Z1 (22157) [92.3d.42.c2.f1.f8] -62dB BLE_GAP_EVT_SCAN_REQ_REPORT
Z1 (22158) [92.3d.42.c2.f1.f8] -61dB BLE_GAP_EVT_SCAN_REQ_REPORT
Z1 (22159) [92.3d.42.c2.f1.f8] -68dB BLE_GAP_EVT_SCAN_REQ_REPORT
Z1 (22160) [92.3d.42.c2.f1.f8] -67dB BLE_GAP_EVT_SCAN_REQ_REPORT
Z1 (22161) [92.3d.42.c2.f1.f8] -69dB BLE_GAP_EVT_SCAN_REQ_REPORT
Z1 (22162) [92.3d.42.c2.f1.f8] -68dB BLE_GAP_EVT_SCAN_REQ_REPORT
Z1 (22163) [92.3d.42.c2.f1.f8] -67dB BLE_GAP_EVT_SCAN_REQ_REPORT
I have not yet managed to send UI responses back to the phone, but I’m pretty confident that it’s just a small program bug.

The code is a complete haystack, and will take a few days to clean up.

How slowly everything proceeds! I’m just banging away at getting the right/minimal combination of BLE features into our footprint.

The challenge is to be able to have BLE do three things at the same time:

  1. On some condition (TBD) broadcast a BLE command to peers asking them to to turn on their DW chip for subsequent ranging; 
  2. Listen out for instructions from peers to turn on theDW chip and respond to their subsequent range request; 
  3. Respond to operator commands to set various parameters on the peer. Don’t quite know what they will be, but probably some short UID, role(anchor, wearable, gateway…). 

Being both a broadcaster/advertiser (aka service), and a listener(aka central/application/scanner) is not the standard behavior for Nordic chips.

Recently Nordic created a new soft machine called the S130 which is able to be a broadcaster/advertiser and a listener/scanner simultaneously – albeit in a limited way. The soft-machine is basically an operating system.

TS06 requirements are actually quite modest, but unusual and I’m trying to build them atop the S130, and shoe-horn them into the nRF51822 along with the DW libraries. I think the code will fit OK, but the challenge is likely to be the limited RAM size for buffers.

Since this is a show-stopper until we get the 32K chips (and maybe even then) it’s a priority to see if this can all be done.

So far I have managed to get some trivial programs that generate zero radio traffic, but blink LEDs running atop the S130. This turned out to be more of a configuration nightmare than I thought because there was an errors in Nordic’s “.ld” file they published for the S130. That was several days wasted.

Yesterday I managed to get an advertiser running atop the S130, and I was able to observe it’s adverts were correct using my phone. It’s a simple and almost trivial accomplishment, but a relief to have made a bit of progress.

The next step is see if I can get the scanner side working in parallel with the advertiser.

This latest Pebble teardown is really interesting/

https://www.ifixit.com/Teardown/Pebble+Time+Teardown/42382

Image #1Image #1

Highlights

They use an ST + external memory and an external BT chip.  Two chips for their IMU.
This “motor driver” is interesting.  Seems like a lot of effort for a little advantage – if I understand it’s purpose.   DRV2603
It references this “smartstrap” page which seems like a useful thing to know.

This 150 mAh, 0.57 Wh, 3.8 V battery packs a bit less punch than even the smallish 205 mAh, 0.78 Wh battery we found in the Apple Watch. 

That’s also about half the juice of other recent smartwatches, like the Moto 360 and the Samsung Gear Live—but with its e-paper display, Pebble claims that the Time can last up to seven days between charges.

//Mik

I have been struggling to get any program to run with the s130 softmachine.  The programs just don’t start, and I think they are just generating a fault in the startup code.  This has consumed me for days.  The trick, as always, is to figure out the right google search terms.

Hi,
I’m sorry for the late response. I tried to recreate this problem with gcc when I found that there was a typo in the SD document. The flash origin should be 0x1C000 and not 0x2000 as stated in the documentation. This will be fixed in the next release.
I looked it over, and I have questions.

  1. I don’t understand the choice of pin assignments for UART, SPI and I2C.  Your assigns are perfectly OK, but please look at http://blog.touchstone-labs.com/2015/05/pin-assignments.html  At the bottom of the page I suggest assignments that make the software tidy.  I’m assuming that if all the pins are going to the same module are adjacent on the uC, it makes the routing cleaner, but I also realize I’m talking out my arse!  So maybe the other DW signals should be on pins adjacent to the SPI?
  2. I was assuming that I’d use an external FT232 (as I have now) to carry debug info to the PC.  But it looks like you are incorporating one for charging.  That makes my life easier for sure, but does it soak up a lot of board space?
  3. On the DWM module it looks like p10 and p11 are grounded.  I think p9 and p10 should be grounded to hardwire the SPI protocol details.
  4. Confirm that DW m_sync not connected to anything is OK.  I don’t need it.
  5. As a general rule, it ought to be possible to turn off ALL the LEDs to conserve power, even those not under direct control of the processor.  Jumpers, or scratch-out links would be good in places where the software can’t disable them.
  6. The more stuff we can get off the SPI the better, because the radio may have a limit to how long it can wait after raising an interrupt.  So loading stuff (like the IMU) on I2C is slightly preferred.
  7. For some reason the Nordic standard is active low for buttons.  Maybe there is some subtle power-saving reason?
  8. You mention a pressure sensor in the notes, but it’s not present (which is fine)  FYI I think a pressure sensor can be attached to the IMU, rather than hanging off the I2C (or both?).  I need to find out what the pros and cons are.
  9. I’m not sure what the benefit is of having a micro USB connector, and routing to the “USB and UART” J.   
  10. Can you route 2 GPIOs to the SERIAL_COMM connector (nc-a and nc_b) pins to act as CS pins for any device we might want to experiment with.  They can also act as triggers for a scope.  Maybe they can be jumpered to LEDs by default? 
  11. Maybe route 5V and 3.3V to same J connector too?  No idea if this makes sense.
  12. Nordic pins 17,18,19 are ADC pins.  I can imagine they might be useful for power experiments if they were easy to get at.
  13. You said the microSD card would suck power.  We could leave it off.  If space becomes an issue before the next rev (unlikely) then I can hang it off a J connector.
  14. Should the LTC2942 pin be routed to a Nordic GPIO so it can raise an interrupt?
  15. LTC3127.  Should pin3 be under software control?  Is it for forcing power-off when all hell breaks loose?  What about pin 4.  I never understood what it did in TS05
  16. LTC3105.  What does SHNn do?  How is it different from LTC3127p3?  How would I use PGOOD?  Should it be routed to a GPIO?
  17. Nordic pin24 is labelled PWRON.  What does it do?
  18. Is there a convenient point to measure tiny currents other than with the coulomb counter.
  19. Need to connect the MPU9250 “INT” pin to the processor.

It was pretty easy to simulate a UART over BLE.  Nordic had made an example service, but there was no corresponding “central”.

Lashing together the central was actually pretty easy – I stole some fragments from the web, and it came together quickly, but getting the right mix of components proved to be tricky.  Of course the “central” uses a different soft-machine, and has to be matched with the right API so the calls get vectored to the right place.

When eventually it would compile, then it wouldn’t load producing the useful message “ld.exe: region RAM overflowed with stack“.  It took me a while to figure this one out.  The stack grwos down from the top of RAM, and the rest of the RAM allocations grow up from the bottom of RAM.  This message means that there was not enough RAM to run it.  So for the last two days I have been trying to figure out how to save RAM.

Simply optimizing the code of course makes no difference because this is data.   The obvious wheeze is to get rid of the heap which consumes 2K of RAM and is not used.  That seems like an easy thing to do – and it is – just change the value of the compile-time constant: __HEAP_SIZE=0

Problem is that it is not a compile-time constant, it is an assemble-time constant.  So I chased by own tail for hours trying to understand why the heap stuck around.   Of well – another painful lesson, but at last the program is working.

Here’s a demo of the TS connecting to my Android.  It works in both directions echoing back whatever the Android sends it.  Also, when the button on the TS06 is pressed it sends a canned string to the Android.

The big triumph is that I can now send strings of characters between TS06 and the Nordic eval board PCA10001.  Both are connected to my PC using  USART-to-USB adaptors and so in this demo all you can see is two typescript windows showing that TS06 is sending a string to PCA10001.  Gives you some idea of the possible data rate.

Explaining the BLE architecture to myself was actually helpful.   I worked through the code more carefully and discovered that I didn’t quite appreciate that services, and characteristics all use the same 128 bit base address.  I guess that all makes sense because it’s important for listeners to be able to reject radio messages that are not from a service they care about.

So here’s the physical setup:  The TS06 is playing the part of the wearable.  The Nordic eval board is playing the part of the gateway to the cloud.

The black blob on the end of two black wires is a button I deftly soldered onto the TS06 board.  (Exquisite huh?)  It is the “sensor”.

The demo has three phases: discovery, connection, and data transfer.

  • Phase 1: The TS board starts off scanning for a gateway.  It has LED_0 illuminated while it is scanning.  
  • Phase 2: It discovers the gateway and tries to connect.  If successful it turns off LED_0 and turns on LED_1.  Now it is ready to transfer sensor data up to the cloud.

  • Phase 3: Each time I press the button the TS06 generates a “button-down” or “button-up” event, and sends it up to the cloud.  
  • When the cloud receives the event it logs it.
  • Then is sends an “led-on” or “led-off” event back to the TS06.  
  • The TS06 receives the event and does the obvious thing.

The latency is awful.

Another week has gone by and I’m still trying to create a sender and receiver for a custom BLE service.  Why this is necessary is a lesson in itself, and I can’t believe how hard I’m finding this – but I guess old brain is a factor.  It’s all supposed to be so easy, but I seem to find gotchas at every touch and turn.  One of the issues is that BLE defines new terms that are subtle and confusing.

I’m trying to do something that’s “Oh so simple” – create a custom profile.  A profile defines what a physical BLE device does, i.e. how it behaves.  The profile is like a contract between the two ends of a BLE radio link that defines how, and what the two devices are going to communicate.  It’s the high-level protocol that allows them to understand the meaning of the information they have agreed to exchange.  BLE distinguishes the word profile, from protocol.  I can’t really see the difference, but clearly a profile defines higher-level semantics, and protocol lover-level.  The protocol might describe addressing a routing issues, whereas the profile describes how the data should be interpreted by the application.  And what’s an application…?  I’m not going there.

The terms server and client are too rigid for BLE.  BLE defines the term role.  Although in BLE every connection defines one end as master and the other end as slave, there appears to be no reason why a device cannot be both.  It can even be both at the same time.  Example roles are “heart rate sensor” and “heart rate collector”.  This is all a bit too subtle for now, but it’s good to know that there is this verbal gotcha lurking in the woodwork.  Client and server are not terms that crop up much.

So… back to the profile.  Each profile defines a set of services.  Some services are mandatory across all profiles, some are so common that they have been defined by the BLE standard, and others are specialized to the particulars of the device – a custom service.

  • One mandatory service provides the human readable string describing the profile, e.g. “Heart Rate Monitor”, or “HRM”.  
  • A standard, but non-mandatory service, “BAS” provides the state of the battery – an estimate of the charge left in the battery expressed in % or volts.  
  • A specialized service might provide the state of some sensor, or actuator, e.g. the rate of flow of water through a valve. TS has a special behavior so it has to define a custom service in order to communicate over BLE.  

A profile can combine a mixture of mandatory, standard and custom services.  So a profile might combine an HRM service and a BAS service.  A more elaborate device might add some proprietary extra service call “FOO”.

Now, for me, it all gets a bit arbitrary.  For some reason BLE has made some decisions about what services will be standard.  I think some of these decisions are based upon who was at the table when the standard was being written.  For example the HRM service is defined in the standard, along with the HTP “Heath Thermometer Profile”, and the HID “Human Interface Device” profile.

This is an important distinction because standard services are allowed to use privileged (and shorter) packets to do their work, thus saving power.  A standard part of the traffic in each packet is a UUID. This defines the profile, service and characteristic (part of a service) that the packet is about.  A standard UUID is 128 bits long – a substantial fraction of a packet that can only be 128 bytes long, and a lot of overhead when you have a tiny battery.   So the standard has decreed that some services can use much shorter UUIDs, and they are not to be used for any other purpose.  If you want to define your own shorter UUID then I guess you have to cross the palm of BLE with silver.

Anyone can define a new UUID here.  They are generated randomly, and so there is a very small chance that two organizations can be allocated the same UUID.

A characteristic is a fancy term for a blob of data – the stuff we actually care about – a heart-rate measurement, or a range measurement for example.  Unless you use the standard characteristic types, then each of these requires 128 bits to describe.  Fortunately the standard defines a lot of useful characteristics that can be pressed into service.

Just to make things more confusing, there are standard profiles.  But standard profiles don’t have a physical manifestation – they are just a collection of services that appear to have no data structure, or type associated with them, so I don’t even see how something that doesn’t ever exist can be standardized – but hey!   I think the point of standard profiles is that a manufacturer can define their own private profile that allows their devices to communicate, and prevents others from inter-operating with them.  So TS will probably need a custom profile.

TS has to define a custom profile, and one, or more custom services, and maybe some custom characteristics, all of which carry with them this onerous extra overhead that sucks the battery dry.

My plan is to build a collector service that remotely instructs a TS_ranger to turn on it’s ranger; to range the collector; and then to send the resulting range measurement back to the collector.  This is about as simple a program as I can define that will require all parts of the software to fit into memory, and to cooperate.  If I can’t make this work, then as I keep saying… “we are done”.

Now there are demo examples of how to setup a standard profile using standard services.  I have compiled those examples and satisfied myself that they work OK.  Now I am trying to incrementally change them so that they use a custom profile and custom service.  It ought to be as simple as swapping some short numbers for some longer ones…

So my example is simple.  I have a new stunning service called LEDBUTT.  LEDBUTT implements one button and one LED.  The objective is that when you press the button, a signal is send to a peer device which in turn sends a message back requesting the sender to illuminate it’s LED.  Yup – a light switch!  When you release the button, another pair of obvious messages are exchanged and the LED turns off.

How hard can this be… well a full week of fiddling has not brought me much closer to success.

I've had some issues getting BLE to work in tandem with semihosting.  If an error message is output while some BLE is in progress then it gets stuck.  I discovered that I'm not alone, and one of the guys at Nordic actually says that it is better to use the hardware UART for debugging.

Today I have gone back to using the UART pins 8,9,10,11 which means I had to give up on a couple of LEDs.   Notice that I have reworked the spreadsheet for TS06.2 to omit those two LEDs, so if you have not wired them up, then don't.
Of course it doesn't matter if you have already put LEDs on because I can just remove the jumpers, but I know adding LEDs is a pain, so I hope I caught you in time.


//Mik