Avatar for Mark_wllms

Mark_wllms

Member since Apr 2021 • Last active Jul 2021
  • 2 conversations
  • 24 comments

I have set up an M11 smart watch to run Espruino, and am having fun writing some watch apps for it.

Most recent activity

  • in Bangle.js
    Avatar for Mark_wllms

    Maybe it would be better to correct the time on the hour (e.g. 00 minutes past), to make sure it happens regardless of the current app load time?

  • in Porting to new Devices
    Avatar for Mark_wllms

    At the moment it is all working, but I am polling the sensor 10 times a second to look for wrist twist, which is putting a bit of a strain on battery life, even when the watch isn't being worn. I'll look into the 'movement' interrupt, but am unsure if this is specific to BMA423. It won't hurt to try. The datasheet implies you can set a threshold movement in each axis to trigger the interrupt.

    • 22 comments
    • 1,527 views
  • in Porting to new Devices
    Avatar for Mark_wllms

    I should also divide x y and z by 16 as only 12 bits are used.

  • in Porting to new Devices
    Avatar for Mark_wllms

    Thanks. I was just reading https://developer.mozilla.org/en-US/docs­/Web/JavaScript/Typed_arrays when you replied! Much neater.
    I suspect 103 was redundant, as it is really a pointer assignment, not a copy.

  • in Porting to new Devices
    Avatar for Mark_wllms

    This is current state of code - just enough to demonstrate working. Various things still need adding, e.g. events and scaling the accel vector.

    /*
     Espruino module for BMA421/BMA423 motion sensor
     */
    
    
    //delete the next line for module
    var exports={};
    
    //create an instance - initialise if necessary (or just reconnect)
    function BMA421(_i2c) {
      this.i2c = _i2c;
      this.enabled = (this.checkstatus()==1);
      if (!this.enabled) this.initialise();
    }
    
    
    BMA421.prototype.initialise = function() {
    //reset sensor
      this.writeReg(0x7E,0xB6); 
    //disable power save
      this.writeReg(0x7C,0x00); 
      this.loadConfig();
    //Accl Enable
      this.writeReg(0x7D, 0x04);
    //Acc Config
      this.writeReg(0x40, 0b00101000);
    //Enable and Reset Step Counter - this will also enable power save
      this.resetSteps();
      this.enabled = (this.checkstatus()==1);
    }
    
    //x and y are swapped - could remap in hardware
    BMA421.prototype.getAccel = function() {
      var acc = { x: 0, y: 0, z: 0 };
      if (this.enabled) {
        var data = this.readBytes(0x12,6);
        acc.x = (data[3] << 8) | data[2];
        if (acc.x > 32767) acc.x -= 65536;
        acc.y = (data[1] << 8) | data[0]; 
        if (acc.y > 32767) acc.y -= 65536;
        acc.z = (data[5] << 8) | data[4];
        if (acc.z > 32767) acc.z -= 65536;
      }
      return acc;
    }
    
    BMA421.prototype.getSteps = function() {
      if (this.enabled) {
        var steps = this.readBytes(0x1E,4);
        return (steps[3] << 24) + (steps[2] <<16) + (steps[1] << 8) + steps[0];
      }
      else return 0;
    }
    
    //Temperature always seems to be 25
    BMA421.prototype.getTemp = function() {
        if (this.enabled) {
          return this.readBytes(0x22,1)[0] +23;
      }
      else return -300;
    }
    
    //enables the step counter, disables the step detector
    BMA421.prototype.resetSteps = function() {
      this.writeReg(0x7C, 0x00);//Sleep disable
      var feature_config = new Uint8Array(70);
      feature_config = this.readFeatures(70);
      feature_config[0x3A + 1] =  0x34; 
      this.writeFeatures(feature_config, 70);
    //Sleep Enable
      this.writeReg(0x7C, 0x03);
    }
    
    //burst write data to a register    
    BMA421.prototype.writeReg = function(r,d) {
        this.i2c.writeTo(0x18,r,d);
    }
    
    //read a given number of bytes from a register
    BMA421.prototype.readBytes = function(r,l) {
      this.i2c.writeTo(0x18,r);
      return this.i2c.readFrom(0x18,l);
    }
    
    //read a single byte from a register
    BMA421.prototype.readReg = function(reg) {
        this.i2c.writeTo(0x18,reg);
        return this.i2c.readFrom(0x18,1)[0];
    }
    
    //burst read bytes from the feature config
    BMA421.prototype.readFeatures = function(l) {
      this.i2c.writeTo(0x18,0x5E);
      return this.i2c.readFrom(0x18,l);
    }
    
    //burst write bytes to the feature config
    BMA421.prototype.writeFeatures = function(config) {
      this.i2c.writeTo(0x18,0x5E,config);
    }
    
    //Config file as a binary blob - write in chunks
    BMA421.prototype.loadConfig = function () {
      var buffer_size = 64;
      var config =  new Uint8Array(buffer_size);
    //initialise config
      this.writeReg(0x59,0x00); 
      for (var i=0;i<6144; i+=buffer_size) {
        config = require("Storage").read("bma421_config.b­in",i,buffer_size);
        this.i2c.writeTo(0x18,0x5B,  (i / 2) & 0x0F);
        this.i2c.writeTo(0x18,0x5C, (i / 2) >> 4);
        this.i2c.writeTo(0x18,0x5E,config);
      }
    //enable sensor features
      this.writeReg(0x59,0x01); 
    }
    
    //LSB of status register is 1 for working
    BMA421.prototype.checkstatus = function() {
        return (this.readReg(0x2A) & 0x1F);
    }
    
    exports.connect = function(_i2c) {
      return new BMA421(_i2c);
    }
    

    BTW, I have no experience of JavaScript, only C/Pascal/Delphi (and a little python), so I'm not convinced by the object model here at all.

  • in Porting to new Devices
    Avatar for Mark_wllms

    Would I have a a problem with terminators (0xFF) in the string? There are a few in the data.

  • in Porting to new Devices
    Avatar for Mark_wllms

    Thanks. Tried to open whole file with Storage.readArrayBuffer but ran out of heap memory, so chunked instead. I will try a larger chunk to see what works, now I can see if I am successful.

    I will upload code when I have tweaked it, and maybe submit somewhere as well. I am trying to write as a proper module, but I have zero JavaScript. It would help Pinetime owners, at least. I think only older P8s have BMA421.

  • in Porting to new Devices
    Avatar for Mark_wllms

    Ok, going back to my original question:

    I've taken the suggestion from @fanoush and just written a short module in javascript for the BMA421 from scratch. All it does it load the binary code to set up the step counter and then reads steps and xyz acceleration. It seems to all work, for not many lines of code, so I'm happy with that as an approach.
    My eventual solution was just to turn the bytes from the config file into a binary file that I upload to Storage. I then read it in chunks (I don't think this really uses memory?) and write each chunk to the sensor. Everything else is very similar to the example code in the ATCWatcH project. The datasheet has several errors / omissions in it, but it helped to get started.
    BMA421 doesn't have twist interrupts, so I will have to check that on an interval if I want to turn on the screen that way.

Actions