Update RX & Battery OLED pages.

RX page shows up to 14 channels.
Battery page shows current and capacity information.
This commit is contained in:
Dominic Clifton 2014-11-13 01:29:07 +00:00
parent 8661849a5f
commit f5a0f9d3b2
10 changed files with 124 additions and 47 deletions

View File

@ -40,7 +40,7 @@ Note: When battery monitoring is enabled on the CC3D RC5 can no-longer be used f
Enable the `VBAT` feature.
Configure min/max cell voltages using the following CLI commands:
Configure min/max cell voltages using the following CLI setting:
`vbat_scale` - adjust this to match battery voltage to reported value.
@ -55,3 +55,28 @@ set vbat_scale = 110
set vbat_max_cell_voltage = 43
set vbat_min_cell_voltage = 33
```
# Current Monitoring
Current monitoring (Amperage) is supported by connecting a current meter to the appropriate current meter ADC input (See Board documentation).
When enabled Amps, mAh used and capacity remaining calculated and used by the telemetry and OLED display subsystems.
## Configuration
Enable current monitoring using the cli command
```
feature CURRENT_METER
```
Configure capacity using the `battery_capacity` setting, it takes a value in mAh.
The current meter may need to be configured so that the value read at the ADC input matches actual current draw. Just like you need a voltmeter to correctly calibrate your voltage reading you also need an ammeter to calibrate your current sensor.
Use the following settings to adjust calibrtion.
`current_meter_scale`
`current_meter_offset`
If you're using an OSD that expects the multiwii current meter output value then set `multiwii_current_meter_output` to `1`.

View File

@ -104,7 +104,7 @@ profile_t *currentProfile;
static uint8_t currentControlRateProfileIndex = 0;
controlRateConfig_t *currentControlRateProfile;
static const uint8_t EEPROM_CONF_VERSION = 84;
static const uint8_t EEPROM_CONF_VERSION = 85;
static void resetAccelerometerTrims(flightDynamicsTrims_t *accelerometerTrims)
{
@ -209,7 +209,17 @@ void resetTelemetryConfig(telemetryConfig_t *telemetryConfig)
telemetryConfig->gpsNoFixLongitude = 0;
telemetryConfig->frsky_coordinate_format = FRSKY_FORMAT_DMS;
telemetryConfig->frsky_unit = FRSKY_UNIT_METRICS;
telemetryConfig->batterySize = 0;
}
void resetBatteryConfig(batteryConfig_t *batteryConfig)
{
batteryConfig->vbatscale = VBAT_SCALE_DEFAULT;
batteryConfig->vbatmaxcellvoltage = 43;
batteryConfig->vbatmincellvoltage = 33;
batteryConfig->currentMeterOffset = 0;
batteryConfig->currentMeterScale = 400; // for Allegro ACS758LCB-100U (40mV/A)
batteryConfig->batteryCapacity = 0;
}
void resetSerialConfig(serialConfig_t *serialConfig)
@ -315,11 +325,7 @@ static void resetConf(void)
masterConfig.yaw_control_direction = 1;
masterConfig.gyroConfig.gyroMovementCalibrationThreshold = 32;
masterConfig.batteryConfig.vbatscale = VBAT_SCALE_DEFAULT;
masterConfig.batteryConfig.vbatmaxcellvoltage = 43;
masterConfig.batteryConfig.vbatmincellvoltage = 33;
masterConfig.batteryConfig.currentMeterOffset = 0;
masterConfig.batteryConfig.currentMeterScale = 400; // for Allegro ACS758LCB-100U (40mV/A)
resetBatteryConfig(&masterConfig.batteryConfig);
resetTelemetryConfig(&masterConfig.telemetryConfig);

View File

@ -49,6 +49,8 @@
#include "display.h"
//#define ENABLE_DEBUG_OLED_PAGE
#define MILLISECONDS_IN_A_SECOND (1000 * 1000)
#define DISPLAY_UPDATE_FREQUENCY (MILLISECONDS_IN_A_SECOND / 10)
@ -58,6 +60,8 @@ static uint32_t nextDisplayUpdateAt = 0;
static rxConfig_t *rxConfig;
#define PAGE_TITLE_LINE_COUNT 1
static char lineBuffer[SCREEN_CHARACTER_COLUMN_COUNT + 1];
typedef enum {
@ -66,8 +70,11 @@ typedef enum {
PAGE_BATTERY,
PAGE_SENSORS,
PAGE_RX,
PAGE_PROFILE,
PAGE_PROFILE
#ifdef ENABLE_DEBUG_OLED_PAGE
,
PAGE_DEBUG
#endif
} pageId_e;
const char* pageTitles[] = {
@ -76,18 +83,24 @@ const char* pageTitles[] = {
"BATTERY",
"SENSORS",
"RX",
"PROFILE",
"PROFILE"
#ifdef ENABLE_DEBUG_OLED_PAGE
,
"DEBUG"
#endif
};
#define PAGE_COUNT (PAGE_RX + 1)
const uint8_t cyclePageIds[] = {
PAGE_PROFILE,
PAGE_DEBUG,
PAGE_RX,
PAGE_BATTERY,
PAGE_SENSORS,
PAGE_RX
PAGE_SENSORS
#ifdef ENABLE_DEBUG_OLED_PAGE
,
PAGE_DEBUG,
#endif
};
#define CYCLE_PAGE_ID_COUNT (sizeof(cyclePageIds) / sizeof(cyclePageIds[0]))
@ -186,32 +199,37 @@ void drawRxChannel(uint8_t channelIndex, uint8_t width)
drawHorizonalPercentageBar(width - 1, percentage);
}
#define RX_CHANNELS_PER_PAGE_COUNT 14
void showRxPage(void)
{
for (uint8_t channelIndex = 0; channelIndex < 8; channelIndex += 2) {
i2c_OLED_set_line((channelIndex / 2) + 1);
for (uint8_t channelIndex = 0; channelIndex < rxRuntimeConfig.channelCount && channelIndex < RX_CHANNELS_PER_PAGE_COUNT; channelIndex += 2) {
i2c_OLED_set_line((channelIndex / 2) + PAGE_TITLE_LINE_COUNT);
uint8_t width = SCREEN_CHARACTER_COLUMN_COUNT / 2;
drawRxChannel(channelIndex, width);
if (channelIndex >= rxRuntimeConfig.channelCount) {
continue;
}
if (width * 2 != SCREEN_CHARACTER_COLUMN_COUNT) {
LCDprint(' ');
}
drawRxChannel(channelIndex + 1, width);
drawRxChannel(channelIndex + PAGE_TITLE_LINE_COUNT, width);
}
}
void showWelcomePage(void)
{
tfp_sprintf(lineBuffer, "Rev: %s", shortGitRevision);
i2c_OLED_set_line(1);
i2c_OLED_set_line(PAGE_TITLE_LINE_COUNT + 0);
i2c_OLED_send_string(lineBuffer);
tfp_sprintf(lineBuffer, "Target: %s", targetName);
i2c_OLED_set_line(2);
i2c_OLED_set_line(PAGE_TITLE_LINE_COUNT + 1);
i2c_OLED_send_string(lineBuffer);
}
@ -222,29 +240,44 @@ void showArmedPage(void)
void showProfilePage(void)
{
tfp_sprintf(lineBuffer, "Profile: %d", getCurrentProfile());
i2c_OLED_set_line(1);
i2c_OLED_set_line(PAGE_TITLE_LINE_COUNT + 0);
i2c_OLED_send_string(lineBuffer);
tfp_sprintf(lineBuffer, "Rate profile: %d", getCurrentControlRateProfile());
i2c_OLED_set_line(2);
i2c_OLED_set_line(PAGE_TITLE_LINE_COUNT + 1);
i2c_OLED_send_string(lineBuffer);
}
void showBatteryPage(void)
{
tfp_sprintf(lineBuffer, "Volts: %d.%d, Cells: %d", vbat / 10, vbat % 10, batteryCellCount);
i2c_OLED_set_line(1);
i2c_OLED_send_string(lineBuffer);
padLineBuffer();
uint8_t rowIndex = PAGE_TITLE_LINE_COUNT;
uint32_t batteryPercentage = calculateBatteryPercentage();
i2c_OLED_set_line(2);
drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, batteryPercentage);
if (feature(FEATURE_VBAT)) {
tfp_sprintf(lineBuffer, "Volts: %d.%d, Cells: %d", vbat / 10, vbat % 10, batteryCellCount);
i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer);
padLineBuffer();
uint8_t batteryPercentage = calculateBatteryPercentage();
i2c_OLED_set_line(rowIndex++);
drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, batteryPercentage);
}
if (feature(FEATURE_CURRENT_METER)) {
tfp_sprintf(lineBuffer, "Amps: %d.%d, mAh: %d", amperage / 100, amperage % 100, mAhDrawn);
i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer);
padLineBuffer();
uint8_t capacityPercentage = calculateBatteryCapacityRemainingPercentage();
i2c_OLED_set_line(rowIndex++);
drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, capacityPercentage);
}
}
void showSensorsPage(void)
{
uint8_t rowIndex = 1;
uint8_t rowIndex = PAGE_TITLE_LINE_COUNT;
i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(" X Y Z");
@ -270,7 +303,7 @@ void showSensorsPage(void)
#endif
}
#define PAGE_TITLE_LINE_COUNT 1
#ifdef ENABLE_DEBUG_OLED_PAGE
void showDebugPage(void)
{
@ -283,6 +316,7 @@ void showDebugPage(void)
i2c_OLED_send_string(lineBuffer);
}
}
#endif
void updateDisplay(void)
{
@ -346,9 +380,11 @@ void updateDisplay(void)
case PAGE_PROFILE:
showProfilePage();
break;
#ifdef ENABLE_DEBUG_OLED_PAGE
case PAGE_DEBUG:
showDebugPage();
break;
#endif
}
if (!armedState) {
updateTicker();

View File

@ -278,8 +278,8 @@ const clivalue_t valueTable[] = {
{ "frsky_default_longitude", VAR_FLOAT | MASTER_VALUE, &masterConfig.telemetryConfig.gpsNoFixLongitude, -180.0, 180.0 },
{ "frsky_coordinates_format", VAR_UINT8 | MASTER_VALUE, &masterConfig.telemetryConfig.frsky_coordinate_format, 0, FRSKY_FORMAT_NMEA },
{ "frsky_unit", VAR_UINT8 | MASTER_VALUE, &masterConfig.telemetryConfig.frsky_unit, 0, FRSKY_UNIT_IMPERIALS },
{ "frsky_battery_size", VAR_UINT16 | MASTER_VALUE, &masterConfig.telemetryConfig.batterySize, 0, 20000 },
{ "battery_capacity", VAR_UINT16 | MASTER_VALUE, &masterConfig.batteryConfig.batteryCapacity, 0, 20000 },
{ "vbat_scale", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.vbatscale, VBAT_SCALE_MIN, VBAT_SCALE_MAX },
{ "vbat_max_cell_voltage", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.vbatmaxcellvoltage, 10, 50 },
{ "vbat_min_cell_voltage", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.vbatmincellvoltage, 10, 50 },

View File

@ -229,15 +229,15 @@ void annexCode(void)
vbatCycleTime += cycleTime;
if (!(++vbatTimer % VBATFREQ)) {
if (feature(FEATURE_VBAT)) {
updateBatteryVoltage();
if (feature(FEATURE_VBAT)) {
updateBatteryVoltage();
batteryWarningEnabled = shouldSoundBatteryAlarm();
}
}
if (feature(FEATURE_CURRENT_METER)) {
updateCurrentMeter(vbatCycleTime);
}
vbatCycleTime = 0;
if (feature(FEATURE_CURRENT_METER)) {
updateCurrentMeter(vbatCycleTime);
}
vbatCycleTime = 0;
}
}

View File

@ -56,7 +56,7 @@ bool sumhInit(rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig, rcReadRa
bool rxMspInit(rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig, rcReadRawDataPtr *callback);
const char rcChannelLetters[] = "AERT1234";
const char rcChannelLetters[] = "AERT12345678abcdefgh";
uint16_t rssi; // range: [0;1023]

View File

@ -18,6 +18,8 @@
#include "stdbool.h"
#include "stdint.h"
#include "common/maths.h"
#include "drivers/adc.h"
#include "drivers/system.h"
@ -32,7 +34,7 @@ uint8_t vbat = 0; // battery voltage in 0.1V steps
int32_t amperage = 0; // amperage read by current sensor in centiampere (1/100th A)
int32_t mAhDrawn = 0; // milliampere hours drawn from the battery since start
static batteryConfig_t *batteryConfig;
batteryConfig_t *batteryConfig;
uint16_t batteryAdcToVoltage(uint16_t src)
{
@ -110,7 +112,14 @@ void updateCurrentMeter(int32_t lastUpdateAt)
mAhDrawn = mAhdrawnRaw / (3600 * 100);
}
uint32_t calculateBatteryPercentage(void)
uint8_t calculateBatteryPercentage(void)
{
return (((uint32_t)vbat - (batteryConfig->vbatmincellvoltage * batteryCellCount)) * 100) / ((batteryConfig->vbatmaxcellvoltage - batteryConfig->vbatmincellvoltage) * batteryCellCount);
}
uint8_t calculateBatteryCapacityRemainingPercentage(void)
{
uint16_t batteryCapacity = batteryConfig->batteryCapacity;
return constrain((batteryCapacity - constrain(mAhDrawn, 0, 0xFFFF)) * 100.0 / batteryCapacity , 0, 100);
}

View File

@ -31,6 +31,7 @@ typedef struct batteryConfig_s {
// FIXME this doesn't belong in here since it's a concern of MSP, not of the battery code.
uint8_t multiwiiCurrentMeterOutput; // if set to 1 output the amperage in milliamp steps instead of 0.01A steps via msp
uint16_t batteryCapacity; // mAh
} batteryConfig_t;
extern uint8_t vbat;
@ -47,4 +48,5 @@ void batteryInit(batteryConfig_t *initialBatteryConfig);
void updateCurrentMeter(int32_t lastUpdateAt);
int32_t currentMeterToCentiamps(uint16_t src);
uint32_t calculateBatteryPercentage(void);
uint8_t calculateBatteryPercentage(void);
uint8_t calculateBatteryCapacityRemainingPercentage(void);

View File

@ -58,6 +58,8 @@ static serialPort_t *frskyPort;
static telemetryConfig_t *telemetryConfig;
extern batteryConfig_t *batteryConfig;
extern int16_t telemTemperature1; // FIXME dependency on mw.c
#define CYCLETIME 125
@ -181,7 +183,7 @@ static void sendThrottleOrBatterySizeAsRpm(void)
if (ARMING_FLAG(ARMED)) {
serialize16(rcCommand[THROTTLE] / BLADE_NUMBER_DIVIDER);
} else {
serialize16((telemetryConfig->batterySize / BLADE_NUMBER_DIVIDER));
serialize16((batteryConfig->batteryCapacity / BLADE_NUMBER_DIVIDER));
}
}
@ -371,12 +373,10 @@ static void sendAmperage(void)
static void sendFuelLevel(void)
{
uint16_t batterySize = telemetryConfig->batterySize;
sendDataHead(ID_FUEL_LEVEL);
if (batterySize > 0) {
serialize16((uint16_t)constrain((batterySize - constrain(mAhDrawn, 0, 0xFFFF)) * 100.0 / batterySize , 0, 100));
if (batteryConfig->batteryCapacity > 0) {
serialize16((uint16_t)calculateBatteryCapacityRemainingPercentage());
} else {
serialize16((uint16_t)constrain(mAhDrawn, 0, 0xFFFF));
}

View File

@ -50,7 +50,6 @@ typedef struct telemetryConfig_s {
float gpsNoFixLongitude;
frskyGpsCoordFormat_e frsky_coordinate_format;
frskyUnit_e frsky_unit;
uint16_t batterySize;
} telemetryConfig_t;
void checkTelemetryState(void);