Acknowledged

Edge 530 Data Field Generic ANT Channel Freezes after Sleep

On the Edge 530, the Generic ANT channel freezes after waking from sleep.  To view the problem:

  • Set up a Data Field with a generic ANT Channel
  • Insert the Data Field into a Ride
  • Go into a ride with the Data Field showing but don't start the ride
  • Wait 5 minutes for the Edge to go to sleep.
  • The Generic ANT channel will not work when the Edge is woke up.

This video shows the details.

https://youtu.be/00gkoML7SnA

A work around requires first detecting that it happened and then programmatically resetting the ANT channel so it works again.  Detection is not simple because the data field doesn't get any indication when the Edge goes to sleep or wakes up.  It's also difficult to distinguish between a frozen ANT channel and a channel that is just searching for  a sensor.  I have not come up with a sequence to programmatically reset the channel yet, but I will keep trying.

This seems like it might be a rare occurrence, but our customers run into quite frequently and it appears to them like it's a random bug.  They assume the problem is on the Moxy side and they try powering it off and hard resetting it and trying to change the sensor settings.

I have firmware 9.73 on the Edge 530.

Please let me know if I can provide more information about the problem.

Roger

Parents
  • I added in a freeze detection algorithm as a work around.

    1) I reduced the low priority search timeout to 5 seconds (it was 25 seconds).  This causes the channel to close and reopen if the channel is working but just not connected to a sensor yet.  This close and reopen causes calls to onMessage to occur so the freeze detector doesn't get tripped by simply not getting connected to a sensor.

    var deviceConfig = new Ant.DeviceConfig({
                :deviceNumber              => deviceNumber,
                :deviceType                => 31,
                :transmissionType          => 0,
                :messagePeriod             => 8192,
                :radioFrequency            => 57,
                :searchTimeoutLowPriority  => 2,  // 2.5 seconds per unit
                :searchTimeoutHighPriority => 0,
                :searchThreshold           => 0
            });

    2) I added a msg_timer variable inside of onMessage that keeps track of the last time.now() that onMessage was called.

       function onMessage(msg as Message) as Void {
            var payload = msg.getPayload();
    		msg_timer = Time.now().value(); // Freeze Detector
            if (Ant.MSG_ID_CHANNEL_RESPONSE_EVENT == msg.messageId) {
    
                if (Ant.MSG_ID_RF_EVENT == payload[0]) {...

    3) Then I added a function inside of compute() that detects if the ANT channel is frozen (i.e. onMessage is not getting called).  freeze_count needs to be > 5 to determine that it is frozen.

    	function compute(info) {									// Called Once Per Second
    		if (mSensor != null) {
    			if (Time.now().value() - mSensor.msg_timer >= 2) {  // Not getting new messagaes
    				freeze_count = freeze_count+1;
    				mSensor.reset();        // Stops displaying data
    			}
    			else {
    				freeze_count = 0;
    			}
    			if (!mSensorConnected) {
    				if (mSensor._eventCount != null) {
    					mFitContributor = new MO2FitContributor(self, mSensor);
    					mFitContributor.setDeviceInfo(mSensor.getDeviceInfo());
    					mSensorConnected = true;
    				}
    			}
    			if (mSensorConnected) {
    				mFitContributor.compute(mSensor);
    				if (mSensor.updateDeviceInfo == true) {
    					mFitContributor.setDeviceInfo(mSensor.getDeviceInfo());
    				}
    			}
    		}
    		else {
    			freeze_count = freeze_count+1;
    		}
    		if (freeze_count > 5) {									//  Want this to take longer than the search timeout
    			App.getApp().restartSensor();   // destroys the ANT channel and recreates it
            	freeze_count = 0;
            }
        }
    

    4) The restartSensor() function destroys the ANT channel and recreates it.

    function restartSensor() {
    
            if((mSensor != null) && (mSyncedDeviceNumber == 0))
            {//update if it hasn't previously been set.
    
            mSyncedDeviceNumber = mSensor.syncedDeviceNumber; //Grab old device number and use if it has been synced
            }
          mSensor.release();
          mSensor = null;
          acquireSensor();
          mToggle = getProperty("DispToggle");
          mView.setSensor(mSensor, mToggle);
        }    		

Comment
  • I added in a freeze detection algorithm as a work around.

    1) I reduced the low priority search timeout to 5 seconds (it was 25 seconds).  This causes the channel to close and reopen if the channel is working but just not connected to a sensor yet.  This close and reopen causes calls to onMessage to occur so the freeze detector doesn't get tripped by simply not getting connected to a sensor.

    var deviceConfig = new Ant.DeviceConfig({
                :deviceNumber              => deviceNumber,
                :deviceType                => 31,
                :transmissionType          => 0,
                :messagePeriod             => 8192,
                :radioFrequency            => 57,
                :searchTimeoutLowPriority  => 2,  // 2.5 seconds per unit
                :searchTimeoutHighPriority => 0,
                :searchThreshold           => 0
            });

    2) I added a msg_timer variable inside of onMessage that keeps track of the last time.now() that onMessage was called.

       function onMessage(msg as Message) as Void {
            var payload = msg.getPayload();
    		msg_timer = Time.now().value(); // Freeze Detector
            if (Ant.MSG_ID_CHANNEL_RESPONSE_EVENT == msg.messageId) {
    
                if (Ant.MSG_ID_RF_EVENT == payload[0]) {...

    3) Then I added a function inside of compute() that detects if the ANT channel is frozen (i.e. onMessage is not getting called).  freeze_count needs to be > 5 to determine that it is frozen.

    	function compute(info) {									// Called Once Per Second
    		if (mSensor != null) {
    			if (Time.now().value() - mSensor.msg_timer >= 2) {  // Not getting new messagaes
    				freeze_count = freeze_count+1;
    				mSensor.reset();        // Stops displaying data
    			}
    			else {
    				freeze_count = 0;
    			}
    			if (!mSensorConnected) {
    				if (mSensor._eventCount != null) {
    					mFitContributor = new MO2FitContributor(self, mSensor);
    					mFitContributor.setDeviceInfo(mSensor.getDeviceInfo());
    					mSensorConnected = true;
    				}
    			}
    			if (mSensorConnected) {
    				mFitContributor.compute(mSensor);
    				if (mSensor.updateDeviceInfo == true) {
    					mFitContributor.setDeviceInfo(mSensor.getDeviceInfo());
    				}
    			}
    		}
    		else {
    			freeze_count = freeze_count+1;
    		}
    		if (freeze_count > 5) {									//  Want this to take longer than the search timeout
    			App.getApp().restartSensor();   // destroys the ANT channel and recreates it
            	freeze_count = 0;
            }
        }
    

    4) The restartSensor() function destroys the ANT channel and recreates it.

    function restartSensor() {
    
            if((mSensor != null) && (mSyncedDeviceNumber == 0))
            {//update if it hasn't previously been set.
    
            mSyncedDeviceNumber = mSensor.syncedDeviceNumber; //Grab old device number and use if it has been synced
            }
          mSensor.release();
          mSensor = null;
          acquireSensor();
          mToggle = getProperty("DispToggle");
          mView.setSensor(mSensor, mToggle);
        }    		

Children