Calibration and Firmware Update Issues!

edited August 2018 in Firmware

Hi there,
I been trying to add the functionalities that came with the new update (Firmware 1.4.1, Android API v3.5.0) to my Metawear Android app. There are two main problems that I cannot figure.

----> The calibration method that retrieves the sensor fusion calibration states does not work, instead, the method just disconnects the MetaMotion R device immediately. The following are the method I use to retrieve the calibration and Android Studio's printed log.

private void calibrate() {
    Log.i("Calibration", "Start");
    final SensorFusionBosch fusionModule = connection.board.getModule(SensorFusionBosch.class);
    fusionModule.readCalibrationStateAsync().continueWith(new Continuation<SensorFusionBosch.CalibrationState, Void>() {
        @Override
        public Void then(Task<SensorFusionBosch.CalibrationState> task) {
            Log.i("Calibration", task.getResult().accelerometer.toString());
            Log.i("Calibration", task.getResult().gyroscope.toString());
            Log.i("Calibration", task.getResult().magnetometer.toString());
            Log.i("Calibration", task.getResult().toString());
            return null;
        }
    });
}

……
I/Calibration: Start
D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=6 device=D2:5D:E0:63:F0:C0
D/BluetoothGatt: refresh() - device: D2:5D:E0:63:F0:C0
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=6
I/D2:5D:E0:63:F0:C0: Disconnected
……

----> The update firmware method does the job but I am not sure if that is how it supposed to work. When I use the update method it always end with "DFU service destroyed" and disconnecting the device. The first time I use the method on a Metamotion R device with Firmware v1.3.7, it ends by turning into metaboot mode with Firmware v0.2.2. The second time I use the method on the same device it remains in metaboot mode but goes to firmware 0.3.1. The third time it updates fully to firmware 1.4.1. The following are the method I use to update the device and Android Studio's printed log.

private void updateFirmware(final Context context, final Class<? extends DfuBaseService> dfuServiceClass) {
    showDialog("Updating firmware...");
    Log.i("--------------", "1");
    Capture<List<File>> files = new Capture<>();
    connection.board.downloadFirmwareUpdateFilesAsync().onSuccessTask(new Continuation<List<File>, Task<Void>>() {
        @Override
        public Task<Void> then(Task<List<File>> task) throws Exception {
            Log.i("--------------", "2");
            files.set(task.getResult());
            if (connection.board.inMetaBootMode()) { return null; }
            return connection.board.getModule(Debug.class).jumpToBootloaderAsync();
        }
    }).onSuccessTask(new Continuation<Void, Task<Void>>() {
        @Override
        public Task<Void> then(Task<Void> ignored) throws Exception {
            Log.i("--------------", "3");
            Task<Void> task = Task.forResult(null);
            for(final File f: files.get()) {
                task = task.onSuccessTask(new Continuation<Void, Task<Void>>() {
                    @Override
                    public Task<Void> then(Task<Void> ignored2) throws Exception {
                        Log.i("--------------", "4");
                        return Task.delay(1000);
                    }
                }).onSuccessTask(new Continuation<Void, Task<Void>>() {
                    @Override
                    public Task<Void> then(Task<Void> ignored2) throws Exception {
                        Log.i("--------------", "5");
                        dfuTaskSource = new TaskCompletionSource<>();

                        DfuServiceInitiator starter = new DfuServiceInitiator(connection.board.getMacAddress())
                                .setKeepBond(false)
                                .setForceDfu(true);
                        int i = f.getName().lastIndexOf('.');
                        String extension = f.getName().substring(i + 1);

                        if (extension.equals("hex") || extension.equals("bin")) {
                            starter.setBinOrHex(DfuBaseService.TYPE_APPLICATION, f.getAbsolutePath());
                        } else {
                            starter.setZip(f.getAbsolutePath());
                        }
                        starter.start(context, dfuServiceClass);
                        Log.i("--------------", "6");
                        return dfuTaskSource.getTask();
                    }
                });
            }
            return task;
        }
    }).continueWith(new Continuation<Void, Void>() {
        @Override
        public Void then(Task<Void> task) throws Exception {
            Log.i("--------------", "7");
            if (task.isFaulted()) {
                closeDialog("firmware update failed");
                Log.i("Firmware update", "Failed", task.getError());
            }
            else if (task.isCancelled()) {
                closeDialog("firmware update cancelled");
                Log.i("Firmware update", "Cancelled");
            }
            else {
                closeDialog("firmware update successful");
            }
            return null;
        }
    });
}

Comments

  • ...first time...
    I/--------------: 1
    I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
    I/System.out: (HTTPLog)-Static: isShipBuild true
    I/System.out: (HTTPLog)-Thread-10893-288517927: SmartBonding Enabling is false, SHIP_BUILD is true, log to file is false, DBG is false
    I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
    I/System.out: KnoxVpnUidStorageknoxVpnSupported API value returned is false
    I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
    I/--------------: 2
    D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=6 device=DC:81:97:1E:52:57
    D/BluetoothGatt: refresh() - device: DC:81:97:1E:52:57
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=6
    I/--------------: 3
    I/--------------: 4
    I/--------------: 5
    I/--------------: 6
    I/DfuBaseService: DFU service created. Version: 1.7.0
    I/DfuBaseService: Connecting to the device...
    D/BluetoothGatt: connect() - device: DC:81:97:1E:52:57, auto: false
    D/BluetoothGatt: registerApp()
    D/BluetoothGatt: registerApp() - UUID=00c6728f-7429-40dd-96a1-cd358f4df626
    D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
    D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=DC:81:97:1E:52:57
    I/DfuBaseService: Connected to GATT server
    D/BluetoothGatt: discoverServices() - device: DC:81:97:1E:52:57
    I/DfuBaseService: Attempting to start service discovery... succeed
    I/DfuBaseService: Action received: android.bluetooth.device.action.ACL_CONNECTED
    D/BluetoothGatt: onSearchComplete() = Device=DC:81:97:1E:52:57 Status=0
    I/DfuBaseService: Services discovered
    I/DfuImpl: Reading DFU version number...
    I/DfuImpl: Version number read: 0.8 -> Bootloader from SDK 9.0 or newer. Signature supported
    W/DfuImpl: Legacy DFU bootloader found
    I/DfuImpl: Enabling notifications...
    D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001531-1212-efde-1523-785feabcd123 enable: true
    I/DfuImpl: Sending Start DFU command (Op Code = 1, Upload Mode = 2)
    I/DfuImpl: Sending image size array to DFU Packet (0b, 16416b, 0b)
    I/DfuImpl: Sending the Initialize DFU Parameters START (Op Code = 2, Value = 0)
    I/DfuImpl: Sending 14 bytes of init packet
    I/DfuImpl: Sending init packet (Value = 05-00-01-00-FF-FF-FF-FF-01-00-88-00-47-4C)
    I/DfuImpl: Sending the Initialize DFU Parameters COMPLETE (Op Code = 2, Value = 1)
    I/DfuImpl: Sending the number of packets before notifications (Op Code = 8, Value = 12)
    I/DfuImpl: Sending Receive Firmware Image request (Op Code = 3)
    I/DfuImpl: Uploading firmware...
    V/ActivityThread: updateVisibility : ActivityRecord{20d1b746 token=android.os.BinderProxy@21068bd2 {ca.uottawa.spinelab.amrelshafei.metaapp/ca.uottawa.spinelab.amrelshafei.metaapp.SpotActivity}} show : true
    I/DfuImpl: Response received (Op Code = 16, Req Op Code = 3, Status = 1)
    I/DfuImpl: Transfer of 16416 bytes has taken 9599 ms
    I/DfuImpl: Sending Validate request (Op Code = 4)
    I/DfuImpl: Response received (Op Code = 16, Req Op Code = 4, Status = 1)
    I/DfuImpl: Sending Activate and Reset request (Op Code = 5)
    D/BluetoothGatt: onClientConnectionState() - status=19 clientIf=6 device=DC:81:97:1E:52:57
    W/DfuBaseService: Target device disconnected with status: 19
    D/BluetoothGatt: refresh() - device: DC:81:97:1E:52:57
    I/DfuBaseService: Refreshing result: true
    I/DfuBaseService: Action received: android.bluetooth.device.action.ACL_DISCONNECTED
    I/DfuBaseService: Cleaning up...
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=6
    I/DfuBaseService: DFU service destroyed
    ......
    
  • ...second time...
    I/--------------: 1
    I/--------------: 2
    I/--------------: 3
    I/--------------: 4
    I/--------------: 5
    I/--------------: 6
    I/DfuBaseService: DFU service created. Version: 1.7.0
    I/DfuBaseService: Connecting to the device...
    D/BluetoothGatt: connect() - device: DC:81:97:1E:52:57, auto: false
    D/BluetoothGatt: registerApp()
    D/BluetoothGatt: registerApp() - UUID=488cde41-a222-4674-aacd-993ac730f29b
    D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
    D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=DC:81:97:1E:52:57
    I/DfuBaseService: Connected to GATT server
    D/BluetoothGatt: discoverServices() - device: DC:81:97:1E:52:57
    I/DfuBaseService: Attempting to start service discovery... succeed
    D/BluetoothGatt: onSearchComplete() = Device=DC:81:97:1E:52:57 Status=0
    I/DfuBaseService: Services discovered
    I/DfuImpl: Reading DFU version number...
    I/DfuImpl: Version number read: 0.8 -> Bootloader from SDK 9.0 or newer. Signature supported
    W/DfuImpl: Legacy DFU bootloader found
    I/DfuImpl: Enabling notifications...
    D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001531-1212-efde-1523-785feabcd123 enable: true
    I/DfuImpl: Sending Start DFU command (Op Code = 1, Upload Mode = 3)
    I/DfuImpl: Sending image size array to DFU Packet (146000b, 16384b, 0b)
    I/DfuImpl: Sending the Initialize DFU Parameters START (Op Code = 2, Value = 0)
    I/DfuImpl: Sending 14 bytes of init packet
    I/DfuImpl: Sending init packet (Value = 05-00-01-00-FF-FF-FF-FF-01-00-FE-FF-42-86)
    I/DfuImpl: Sending the Initialize DFU Parameters COMPLETE (Op Code = 2, Value = 1)
    I/DfuImpl: Sending the number of packets before notifications (Op Code = 8, Value = 12)
    I/DfuImpl: Sending Receive Firmware Image request (Op Code = 3)
    I/DfuImpl: Uploading firmware...
    V/ActivityThread: updateVisibility : ActivityRecord{1239282e token=android.os.BinderProxy@2e8bc3a0 {ca.uottawa.spinelab.amrelshafei.metaapp/ca.uottawa.spinelab.amrelshafei.metaapp.SpotActivity}} show : true
    I/art: Background sticky concurrent mark sweep GC freed 102018(5MB) AllocSpace objects, 14(872KB) LOS objects, 14% free, 39MB/45MB, paused 2.471ms total 326.171ms
    V/ActivityThread: updateVisibility : ActivityRecord{1239282e token=android.os.BinderProxy@2e8bc3a0 {ca.uottawa.spinelab.amrelshafei.metaapp/ca.uottawa.spinelab.amrelshafei.metaapp.SpotActivity}} show : true
    I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@2e8bc3a0 time:76528542
    I/DfuImpl: Response received (Op Code = 16, Req Op Code = 3, Status = 1)
    I/DfuImpl: Transfer of 162384 bytes has taken 99638 ms
    I/DfuImpl: Sending Validate request (Op Code = 4)
    I/DfuImpl: Response received (Op Code = 16, Req Op Code = 4, Status = 1)
    I/DfuImpl: Sending Activate and Reset request (Op Code = 5)
    D/BluetoothGatt: onClientConnectionState() - status=19 clientIf=6 device=DC:81:97:1E:52:57
    D/BluetoothGatt: onClientConnectionState() - status=19 clientIf=7 device=DC:81:97:1E:52:57
    W/DfuBaseService: Target device disconnected with status: 19
    D/BluetoothGatt: refresh() - device: DC:81:97:1E:52:57
    D/BluetoothGatt: refresh() - device: DC:81:97:1E:52:57
    I/DfuBaseService: Refreshing result: true
    I/DfuBaseService: Cleaning up...
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=7
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=6
    I/DfuBaseService: Action received: android.bluetooth.device.action.ACL_DISCONNECTED
    I/DfuBaseService: DFU service destroyed
    I/DC:81:97:1E:52:57: Disconnected
    E/ViewRootImpl: sendUserActionEvent() mView == null
    I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@2e8bc3a0 time:76565367
    D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
    I/DC:81:97:1E:52:57: Disconnected
    ……
    
  • …third time…
    I/--------------: 1
    I/--------------: 2
    I/--------------: 3
    I/--------------: 4
    I/--------------: 5
    I/--------------: 6
    I/DfuBaseService: DFU service created. Version: 1.7.0
    I/DfuBaseService: Connecting to the device...
    D/BluetoothGatt: connect() - device: DC:81:97:1E:52:57, auto: false
    D/BluetoothGatt: registerApp()
    D/BluetoothGatt: registerApp() - UUID=bdb2ab25-ecf5-4009-8417-e2798fba5235
    D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
    D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=DC:81:97:1E:52:57
    I/DfuBaseService: Connected to GATT server
    D/BluetoothGatt: discoverServices() - device: DC:81:97:1E:52:57
    I/DfuBaseService: Attempting to start service discovery... succeed
    D/BluetoothGatt: onSearchComplete() = Device=DC:81:97:1E:52:57 Status=0
    I/DfuBaseService: Services discovered
    I/DfuImpl: Reading DFU version number...
    I/DfuImpl: Version number read: 0.8 -> Bootloader from SDK 9.0 or newer. Signature supported
    W/DfuImpl: Legacy DFU bootloader found
    I/DfuImpl: Enabling notifications...
    D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001531-1212-efde-1523-785feabcd123 enable: true
    I/DfuImpl: Sending Start DFU command (Op Code = 1, Upload Mode = 4)
    I/DfuImpl: Sending image size array to DFU Packet (0b, 0b, 127232b)
    I/DfuImpl: Sending the Initialize DFU Parameters START (Op Code = 2, Value = 0)
    I/DfuImpl: Sending 14 bytes of init packet
    I/DfuImpl: Sending init packet (Value = 05-00-01-00-FF-FF-FF-FF-01-00-A8-00-D1-B1)
    I/DfuImpl: Sending the Initialize DFU Parameters COMPLETE (Op Code = 2, Value = 1)
    I/DfuImpl: Sending the number of packets before notifications (Op Code = 8, Value = 12)
    I/DfuImpl: Sending Receive Firmware Image request (Op Code = 3)
    I/DfuImpl: Uploading firmware...
    V/ActivityThread: updateVisibility : ActivityRecord{13877e51 token=android.os.BinderProxy@36a5b9a1 {ca.uottawa.spinelab.amrelshafei.metaapp/ca.uottawa.spinelab.amrelshafei.metaapp.SpotActivity}} show : true
    I/art: Background sticky concurrent mark sweep GC freed 174372(8MB) AllocSpace objects, 11(585KB) LOS objects, 13% free, 49MB/57MB, paused 915us total 174.591ms
    I/DfuImpl: Response received (Op Code = 16, Req Op Code = 3, Status = 1)
    I/DfuImpl: Transfer of 127232 bytes has taken 71990 ms
    I/DfuImpl: Sending Validate request (Op Code = 4)
    I/DfuImpl: Response received (Op Code = 16, Req Op Code = 4, Status = 1)
    I/DfuImpl: Sending Activate and Reset request (Op Code = 5)
    D/BluetoothGatt: onClientConnectionState() - status=19 clientIf=6 device=DC:81:97:1E:52:57
    D/BluetoothGatt: onClientConnectionState() - status=19 clientIf=7 device=DC:81:97:1E:52:57
    W/DfuBaseService: Target device disconnected with status: 19
    D/BluetoothGatt: refresh() - device: DC:81:97:1E:52:57
    D/BluetoothGatt: refresh() - device: DC:81:97:1E:52:57
    I/DfuBaseService: Action received: android.bluetooth.device.action.ACL_DISCONNECTED
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=6
    I/DfuBaseService: Refreshing result: true
    I/DfuBaseService: Cleaning up...
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=7
    I/DfuBaseService: DFU service destroyed
    I/DC:81:97:1E:52:57: Disconnected
    I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@36a5b9a1 time:77015151
    D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
    I/DC:81:97:1E:52:57: Disconnected
    ……
    
  • When is the calibrate function called? What code is executed before calling said function?

    The sample DFU code in the Android documentation should iterate through the list of files to upload with 1 function call. It is extracted from the MetaBase app so some mistakes were probably introduced during the refactoring. I'll double check the code.

  • Hi Eric,
    The activity simply starts by connecting to the device. Code for connecting...

    private void connect(String address) {
        BluetoothDevice device = btAdapter.getRemoteDevice(address.toUpperCase());
        MetaWearBoard board = serviceBinder.getMetaWearBoard(device);
        // Run animation
        connectFragment.setAllEnabled(false);
        connectFragment.getView(address).getProgressBar().setVisibility(View.VISIBLE);
        // Connect
        final AppCompatActivity activity = this;
        final String testId = appSettings.getTestId();
        board.connectAsync().continueWith(new Continuation<Void, Void>() {
            @Override
            public Void then(Task<Void> task) throws Exception {
                if (task.isFaulted()) {
                    Log.i(board.getMacAddress(), "Failed to connect");
                    connect(address);
                }
                else if (task.isCompleted()) {
                    Log.i(board.getMacAddress(), "Connected");
                    connection = new Connection(board, activity, testId);
                    if (!board.inMetaBootMode()) { spot(); }
                    connection.board.onUnexpectedDisconnect(new MetaWearBoard.UnexpectedDisconnectHandler() {
                        @Override
                        public void disconnected(int status) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    (new Handler()).postDelayed(new Runnable() {
                                        @Override
                                        public void run() {onBackPressed();}
                                    }, 3000);
                                }
                            });
    
                        }
                    });
                    // Transition
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            connectFragment.setInitialState();
                            FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
                            transaction1.remove(connectFragment).commit();
                            deviceFragment.setInitialState();
                            FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
                            transaction2.add(R.id.fragment_container, deviceFragment).commit();
                            currentScreen = 2;
                        }
                    });
                }
                return null;
            }
        });
    }
    

    After the activity displays the new fragment, the activity retrieves the Battery level and RSSI data. Code...

    private void getBatteryLevel() {
        connection.board.readBatteryLevelAsync().continueWith(new Continuation<Byte, Object>() {
            @Override
            public Object then(Task<Byte> task) throws Exception {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("Battery", task.getResult().toString() + "%");
                        deviceFragment.setBattery(task.getResult().toString() + "%");
                    }
                });
                return null;
            }
        });
    }
    
    private void getRSSI() {
        connection.board.readRssiAsync().continueWith(new Continuation<Integer, Object>() {
            @Override
            public Object then(Task<Integer> task) throws Exception {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("RSSI", task.getResult().toString() + " dBm");
                        deviceFragment.setRSSI(task.getResult().toString() + " dBm");
                    }
                });
                return null;
            }
        });
    }
    

    Then the user can click a button in the new fragment to call the calibration method, calibration().

    Here is the Android Studio's log...

    D/BluetoothGatt: connect() - device: E2:D2:6D:65:90:E8, auto: false
    D/BluetoothGatt: registerApp()
    D/BluetoothGatt: registerApp() - UUID=5a4ce0dc-7358-4dc1-a678-45c6f09d2719
    D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
    D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=E2:D2:6D:65:90:E8
    D/BluetoothGatt: discoverServices() - device: E2:D2:6D:65:90:E8
    D/BluetoothGatt: onSearchComplete() = Device=E2:D2:6D:65:90:E8 Status=0
    D/BluetoothGatt: setCharacteristicNotification() - uuid: 326a9006-85cb-9195-d9dd-464cfbbae75a enable: true
    I/E2:D2:6D:65:90:E8: Connected
    I/ListPopupWindow: Could not find method setEpicenterBounds(Rect) on PopupWindow. Oh well.
    D/BluetoothGatt: readRssi() - device: E2:D2:6D:65:90:E8
    I/Battery: 78%
    I/RSSI: -52 dBm
    D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
    I/Calibration: Start
    E/ViewRootImpl: sendUserActionEvent() mView == null
    D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
    E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
    D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=6 device=E2:D2:6D:65:90:E8
    D/BluetoothGatt: refresh() - device: E2:D2:6D:65:90:E8
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=6
    I/E2:D2:6D:65:90:E8: Disconnected
    
  • The last line in the log is printed when an unexpected disconnection occurs.

  • Configure and start the sensor fusion algorithm before you read the calibration state.

  • edited August 2018

    Thanks! works perfectly. Is it normal to get the states as “unreliable” on most sensors? and is there a way to calibrate the sensors to make them more accurate?

    Regarding the update firmware method, is there a way to make it all in one step?

    Thanks,
    Amr

  • Read the documentation:
    https://mbientlab.com/androiddocs/3/sensor_fusion.html#calibration

    About the firmware update, quoting myself from my previous post

    @Eric said:
    When is the calibrate function called? What code is executed before calling said function?

    The sample DFU code in the Android documentation should iterate through the list of files to upload with 1 function call. It is extracted from the MetaBase app so some mistakes were probably introduced during the refactoring. I'll double check the code.

This discussion has been closed.