-
The problem is that if the readings for an axis are off centre you do get a change in the magnitude as you rotate with respect to gravity. So rotating your wrist will give a false acceleration that may look like swinging your arm while walking. It is why the continuous steps were detected by some people in only some orientations. The current algorithm is trying to detect accelerations that are independent with respect to your orientation to the downward force of gravity which is why the iPhone in my pocket agrees with the watch on my wrist.
-
@HughB Your work with Gordon on the Pedometer is very much appreciated. I thought you might be interested in the results I have been getting using it with a different accelerometer the sc7a20 which is found in a lot of watches such as the P8, ROCK, Magic3 and SN80. The sc7a20 is a very cheap device which sells for pennies and many examples have readings that are well off centre. As a result, I have had to introduce calibration which Gordon has noted is not that simple. You have to gently move the watch into six different positions to get full calibration data - face- up/down, edge - up/down and end - up/down. However, I have only needed to calibate once. I have been comparing the step count during dog walks with that of my iPhone. The results for walking are quite impressive - here are two recent walks which are typical of the results I have been getting:
iPhone: 5121 SN80: 5124
iPhone: 5209 SN80: 5169I have measured this walk at 2.6 miles with the Bangle GPS recorder. Personally, I am interested in measuring steps as a proxy for distance during walks - enabling step counting at the start of a walk and disabling at the end. I am very impressed with the bangle algorithm.
BTW: I have been using the old threshold of 14. -
The problem of removing the static accelerometer magnitude would seem to be the same as DC removal in Digital Signal Processing. The problem with a simple moving average is that it may obscure the signal at some orientations if as seems likely the magnitude at rest varies due to rotation. There is a great article here on a low cost very simple digital filter to deal with this - it even lists a 3-line Javascript implementation.
-
This does seem to be the problem I referred to earlier. I did a quick spreadsheet to compute
(magnitude-8192)/32
which the step count algorithm does initially. Most values exceed 14 theRAW_THRESHOLD
( the average is 15.56). The step count algorithm assumes that at rest the magnitude will be 1g = 8192 which it will not be in all orientations for all accelerometers unless they are calibrated. -
The blink is because the Bangle 1 screen is not buffered so you are seeing the delay between the second hand being deleted and then redrawn. It is noticeable because in this face, the second hands overlap the numbers so they have to be redrawn on every tick. There is now a new version (in the same place) which reduces the delay by only redrawing the 4 numbers that are actually overlapped by the second hand. A better approach would be to be to use an image buffer but with 4 colours this would need about 200*200*2/8 = 10K bytes which should fit but would take most of free memory.
-
Thanks for the kind words. There is a version of the Braun face for the original Bangle:
The nice thing about the brAun logo is that the A is the middle letter and can be centred in the watch. bAngle would look asymmetric.
BTW: The Apple Notification app is now obsolete as Gordon has provided an IOS Integration app. It did work well with a fimware hack but was flaky without it:(
@Gordon - should I do a PR to remove the ANCS app? -
Oops - accidentally deleted the image in my previous post - now restored. I have added the Braun face to
multiclock
which you can load from here - in advance of submission to the offical BangleApps repository. -
I had a go at a Braun face this afternoon and the result is below. The problem with using grey is that it can only be achieved by dithering on the Bangle2 and as a result looks terrible on narrow marks -so the marks are white.
You can see the effect of dithering on the orange second hand which is a made up of red and green pixels - I think it looks better in solid red. -
-
The time to draw the dial on a Bangle2 (with radius 88 rather that 120) with the code above took 376ms. The time using a version of
drawRotRect
that does not usetransformVertices
was 490ms - or 114ms slower. Timed using:var tt = Date.now(); dial(); console.log("Time: "+Math.ceil(Date.now()-tt)+"ms");
-
It's said that the essence of good Software Engineering is reuse (plagiarism?) so in developing my own analog clock faces, I have been looking through the code of many of the clocks in the BangleApps repository. In trying to get clock faces to render as quickly as possible, I found that the use of the Espruino graphics operation
transformVertices
from the builtin Graphics class helped enormously. Using the Github search facility, I found only two apps using the operation in BangleApps - neither are Analog Clocks - hence I hope the following example may be of interest. The example uses the thetransformVertices
operation in implementing thedrawRotRect
function used in the Beeb Clock (reuse in action).The function places a rectangle rotated around the centre of the clock dial at a parameterised distance from the centre of the clock. I have used it for the following Bold Clock influenced face:
The following are the functions to draw the dial and the hands of this clock.
var cx = g.getWidth()/2; var cy = g.getHeight()/2 Graphics.prototype.drawRotRect = function(w, r1, r2, angle) { var w2=w/2, h=r2-r1, theta=angle*Math.PI/180; return this.fillPoly(this.transformVertices([-w2,0,-w2,-h,w2,-h,w2,0], {x:cx+r1*Math.sin(theta),y:cy-r1*Math.cos(theta),rotate:theta})); } function dial() { for (let a=0;a<360;a+=6) if (a % 90 == 0) g.setColor(g.theme.fg).drawRotRect(8,105,120,a); else if (a % 30 == 0) g.setColor(g.theme.fg).drawRotRect(4,105,120,a); else g.setColor(0.6,0.6,0.6).drawRotRect(2,110,120,a); } let hourHand = g.drawRotRect.bind(g,6,6,66); let minuteHand = g.drawRotRect.bind(g,3,6,100); let secondhand = g.drawRotRect.bind(g,2,3,100);
This example uses a rectangle, however, the approach can just as easily be applied to polygons representing more complex hands.
-
The red hand on the watch faces in the pictures are second hands which the NRF52832 handles fine with barely noticeable flicker. The problem with faster than one second is that the flicker caused by unbuffered update becomes very obvious which is why you need buffering. I tried it on the ROCK and because it has the double buffered
lcd_spi_unbuf
and the faster 32MHz SPI it can manage about 150ms for a complete screen rewrite of 240x280 pixels. -
I simply invoke
process.memory()
from the Web IDE console to get the current memory usage. The SN80 has about 2500 espruino memory variables in total - the change to the LCD driver frees up about 300. In general, real delays are a bad idea in Espruino, however, Timeout delays let other bits of code run which cause problems at system initialisation which is why I am using the real delays which stop anything else running while the LCD driver initialises the screen.A sweeping second hand would need to update the screen every 166ms and use a screen buffer as you say to avoid excessive flicker. I tried it as an experiment using a full screen 2 bit image buffer and it took 300ms for each update. It might work with @fanoush 's buffered driver....
-
More traditional watch faces look great on the SN80. Here are some new ones.
The first is based on @HughB 's Bold clock face. In general, the dial for these faces take some time to display and the watch looks terrible if you have to redraw the dial each time the hands move or the LCD turns on. The trick is to ensure that the hands do not overlap the dial markings and consequently as long as the screen is never completely cleared, you can leave the dial undisturbed in the LCD display memory so that it is instantly displayed on power on etc.@yngv126399 I started on the SN80 using a version of your LCD driver and I noticed that it uses a lot of memory. I think the problem is that the memory used for the initialisation data
ST7789_INIT_CODE
is not released. I have programmed it as separate commands but you could just move the declaration intodispinit
which should also work. In addition, my current version of the driver in the WatchApps repository uses real delays rather than timeouts. This reduces start up glitches and means you do not need the 500ms timeout delay at the start of apps. -
-
@yngv126399 I got hold of an SN80 recently to play with circular displays and I have now fixed the lcd_spi_unbuf driver. The problem was that for some reason, no pixels are displayed if the address window you set up is not completely filled. This means that double buffering does not work, so I have fixed the problem for single buffering - just remove the -DLCD_SPI_DOUBLEBUF=1 declaration in the board file. I have left a firmware build with the revised driver here . I have got most of the P8 bangle emulation environment to run on the SN80 including accelerometer, touch screen and heart rate sensor- see picture below.
.
I have made the widgets moveable, so you can specify the location of the widget panel. The clock face above moves the panel top or bottom to minimse it being obscure by the hour hand.
The only remaining problem is the physical button which should be on D13 or D17, however, I have tried these and other unallocated pins with no success. I would be interested to know if you have got the button to work as I suspect that I may have a hardware fault. I am currently using long touch to replace the button - which works OK.
-
-
-
The advantage of using the Bangle is that the firmware in
jswrap_bangle.c
andnmea.c
turns the NMEA strings received from the GPS device into espruino events. To implement the server on the B5 you would need to have an NMEA parser etc - probably too slow in Javascript so it would probably need firmware hacking - although all the software is already there for the Bangle 2. A further advantage is that the Bangle has a relatively large 350maH battery. Advantage would be that the B5 is smaller to carry around:) -
Bangle GPS service for Kospet ROCK and Magic 3
In a previous post I posted the image of a Bangle simulation environment for the ROCK and Magic3 watches. These watches have an NRF52840 processor and a large 240x280 screen which in the case of the ROCK is very bright.
The image showed Wave Clock loaded directly from the BangleApp Loader as a demonstration of the Bangle emulation environment for the ROCK. However, this is very limited as many of the most interesting Bangle Apps use sensors such as GPS so following an idea suggested some time ago by @fanoush, I have implemented an App for the Bangle which provides a BLE service that makes the Bangle's GPS readings available externally.
Using this, the ROCK and Magic 3 can now run Bangle GPS apps loaded again directly from the App Loader. The Open Street Map App is shown below:
The interface to the GPS on the Bangle 1 & 2 is very narrow and that facilitates emulation. For interest, I include the full emulation code here:
Bangle.setGPSPower = function(on){ if (Bangle.gpsOn && on) return; //already started function unpack(v){ var fix = v.getInt8(29); function ck(d) {return d==-1 ? NaN : d;} return { lat:ck(v.getFloat32(0)), lon:ck(v.getFloat32(4)), alt:ck(v.getFloat32(8)), speed:ck(v.getFloat32(12)), course:ck(v.getFloat32(16)), time:new Date(v.getFloat64(20)), satellites:v.getInt8(28), fix:fix, hdop:ck(v.getFloat32(30)), } } if (on) { Bangle.gpsOn=true; NRF.requestDevice({timeout:4000, filters: [{ name: 'gps' }] }).then(function(device) { //console.log("Found"); return device.gatt.connect(); }).then(function(g) { //console.log("Connected"); Bangle.gpsgatt = g; return g.getPrimaryService("974e0001-1b9a-4468-a83d-7f811b3dbaff"); }).then(function(service) { return service.getCharacteristic("974e0002-1b9a-4468-a83d-7f811b3dbaff"); }).then(function (c) { Bangle.gpscharistic=c; //console.log("Got Characteristic"); Bangle.gpsInterval = setInterval(function(){ Bangle.gpscharistic.readValue().then(function(d){ Bangle.gpsFix=unpack(d); Bangle.emit("GPS",Bangle.gpsFix); }); },1000); }).catch(function(e){ E.showMessage("GPS: "+e,"ERROR"); }); } else { Bangle.gpsOn=false; if (Bangle.gpsInterval) Bangle.gpsInterval = clearInterval(Bangle.gpsInterval); if(Bangle.gpsgatt) Bangle.gpsgatt.disconnect(); delete Bangle.gpsgatt; delete Bangle.gpscharistic; } } Bangle.getGPSFix = function() {return Bangle.gpsFix;}
The Bangle GPS server code can be found here.
I have found the Bangle 1 GPS to be more sensitive than the Bangle 2, so it may be that if you have both Bangles, this may be of use. I have found the Bluetooth link between ROCK and Bangle really reliable and its no problem to carry the Bangle in a top pocket or a back pack.
-
I have now finished an initial version of a Bangle compatible environment for the ROCK and Magic3 watches. You can find it in this repository. The firmware uses a double buffered version of
lcd-spi-ubuf.c
which combined with 32Mhz SPI gives much faster screen update than was possible on the P8. The Bangle emulation is implemented in Javascript so is easy to update. Emulation functions are loaded into the NRF52840 internal flash for better performance. They allow you to load apps directly from the Bangle App Loader if you ignore the warnings, however, since the ROCK and Magic3 have very few sensors it is really only Clock apps that are truly portable. As an example, the Wave Clock which runs on both Bangle and Bangle 2 is shown below running on the ROCK - it was loaded straight from the official Bangle App Loader:The emulation has versions of setUI options so menus and prompts work.
-
-
I have also been getting a lot of these FIFO_FULL errors from a build of the latest version of Espruino for an NRF52840 - although it is for a Magic 3 watch. It seems to happen for me after interrupt generated events although I have also got it when loading a large amount of code from the editor window of the IDE into RAM.
-
Yes, but I am afraid that I did not follow the Bangle conventions exactly so my apps did require tweaks. I agree with your views on jswrap_bangle.c but I think the new touch and layout stuff is worth getting to work on the P8.
BTW does the Kospet Rock have a touch screen? It looks like it has three buttons.
Yes, it’s the B2 algorithm on a SN80. I programmed the first version of plot track for B1 that Gordon then added to the gps recorder app and it used exactly the equirectangular approximation you have suggested for the Run app. I have just checked and the current version still uses it so the distance should be accurate as I did check its accuracy at the time.