Native ANT+ Part 2 - Improved Power Support

Fix SRM power decoding to stop requiring a new message
pair whenever a zero change occurs - this was erroneous
and severely limited the update rate. Power and Cadence
updates for SRM are now immediate.

Desk check of support for Standard Power messages showed
that the code was interfering with normal cranktorque or
wheeltorque power calculations. This did not show up with
SRM cranks since they do not send standard power messages.

This should help to resolve issues with erratic/incorrect
power readings from Powertaps. I am not sure if Quarq cranks
send standard power messages, but if they do then this should
improve power readings for those too.
This commit is contained in:
Mark Liversedge
2011-03-10 14:26:12 +00:00
parent 10819d05fa
commit 3cfbfd446a
4 changed files with 28 additions and 19 deletions

View File

@@ -42,7 +42,7 @@ ANTChannel::ANTChannel(int number, ANT *parent) : number(number), parent(parent)
messages_received=0;
messages_dropped=0;
setId();
srm_offset=0;
srm_offset=400; // default relatively arbitrary, but matches common 'indoors' values
burstInit();
}
@@ -237,6 +237,9 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
{
ANTMessage antMessage(parent, ant_message);
bool savemessage = true; // flag to stop lastmessage being
// overwritten for standard power
// messages
unsigned char *message=ant_message+2;
double timestamp=get_timestamp();
@@ -245,6 +248,7 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
last_message_timestamp=timestamp;
if (state != MESSAGE_RECEIVED) {
qDebug()<<"who are you? sent";
// first message! who are we talking to?
parent->sendMessage(ANTMessage::requestMessage(number, ANT_CHANNEL_ID));
blanking_timestamp=get_timestamp();
@@ -292,7 +296,6 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
// Always ack calibs unless they are acks too!
if (antMessage.data[6] != 0xAC) {
antMessage.data[6] = 0xAC;
qDebug()<<"sending calibration ack...";
parent->sendMessage(antMessage);
}
@@ -331,6 +334,7 @@ qDebug()<<"got new offset!"<<srm_offset;
}
} // ANT_SPORT_CALIBRATION
savemessage = false; // we don't want to overwrite other messages
break;
//
@@ -345,7 +349,7 @@ qDebug()<<"got new offset!"<<srm_offset;
if (time && antMessage.slope && period) {
nullCount = 0;
float torque_freq = torque / time - 428/*srm_offset*/; //XXX need to support calibration
float torque_freq = torque / time - 420/*srm_offset*/;
float nm_torque = 10.0 * torque_freq / antMessage.slope;
float cadence = 2000.0 * 60 * (antMessage.eventCount - lastMessage.eventCount) / period;
float power = 3.14159 * nm_torque * cadence / 30;
@@ -359,7 +363,7 @@ qDebug()<<"got new offset!"<<srm_offset;
} else {
nullCount++;
antMessage.type = 0; // we need a new data pair
//antMessage.type = 0; // we need a new data pair XXX bad!!!
if (nullCount >= 4) { // 4 messages on an SRM
parent->setWatts(0);
@@ -401,21 +405,20 @@ qDebug()<<"got new offset!"<<srm_offset;
break;
//
// Standard Power
// Standard Power - interleaved with other messages 1 per second
// NOTE: Standard power messages are interleaved
// with other power broadcast messages and so
// we need to make sure lastmessage is NOT
// updated with this message and instead we
// store in a special lastStdPwrMessage
//
case ANT_STANDARD_POWER: // 0x10 - standard power
{
uint8_t events = antMessage.eventCount - lastMessage.eventCount;
if (events) {
nullCount =0;
if (lastStdPwrMessage.type != 0) {
parent->setWatts(antMessage.instantPower);
} else {
nullCount++;
if (nullCount >= 4) { // 4 messages on Standard Power ? XXX validate this
parent->setWatts(0);
}
}
lastStdPwrMessage = antMessage;
savemessage = false;
}
break;
@@ -537,7 +540,10 @@ qDebug()<<"got new offset!"<<srm_offset;
// reset nullCount if receiving first telemetry update
dualNullCount = nullCount = 0;
}
lastMessage = antMessage;
// we don't overwrite for Standard Power messages
// these are maintained separately in lastStdPwrMessage
if (savemessage) lastMessage = antMessage;
}
}

View File

@@ -144,7 +144,7 @@ class ANTChannel {
ANT *parent;
ANTMessage lastMessage;
ANTMessage lastMessage, lastStdPwrMessage;
int dualNullCount, nullCount;
double last_message_timestamp;
double blanking_timestamp;

View File

@@ -406,9 +406,10 @@ qDebug()<<"broadcast data, channel="<<message[3]<<"type="<<message[4]<<"calid?"<
case ANT_STANDARD_POWER: // 0x10 - standard power
eventCount = message[5];
instantCadence = message[6];
sumPower = message[7] + (message[8]<<8);
instantPower = message[9] + (message[10]<<8);
pedalPower = message[6]; // left/right 0xFF = not used
instantCadence = message[7];
sumPower = message[8] + (message[9]<<8);
instantPower = message[10] + (message[11]<<8);
break;
case ANT_WHEELTORQUE_POWER: // 0x11 - wheel torque (Powertap)
@@ -593,6 +594,7 @@ void ANTMessage::init()
wheelRevolutions = crankRevolutions = 0;
slope = period = torque = 0;
sync = length = type = 0;
pedalPower = 0;
srmOffset = srmSlope = srmSerial = 0;
calibrationID = ctfID = 0;
autoZeroStatus = autoZeroEnable = 0;

View File

@@ -91,6 +91,7 @@ class ANTMessage {
uint8_t data_page, calibrationID, ctfID;
uint16_t srmOffset, srmSlope, srmSerial;
uint8_t eventCount;
uint8_t pedalPower;
uint16_t measurementTime, wheelMeasurementTime, crankMeasurementTime;
uint8_t heartrateBeats, instantHeartrate; // heartrate
uint16_t slope, period, torque; // power