Skip to content

Commit

Permalink
battery-indicator: Remove "consumed power" and toggle between instant…
Browse files Browse the repository at this point in the history
…aneour current and power

Consumed power was being accumulated uncorrectly because of the very low sampling rate, which leads to wrong integrations over time.
  • Loading branch information
rafaellehmkuhl committed Oct 4, 2024
1 parent f79e767 commit e56752e
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 89 deletions.
126 changes: 50 additions & 76 deletions src/components/mini-widgets/BatteryIndicator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,39 @@
<span class="absolute text-sm text-yellow-400 -bottom-[2px] -right-[7px] mdi mdi-alert-circle"></span>
</span>
<div class="flex flex-col w-[4rem] select-none text-sm font-semibold leading-4 text-end">
<template v-if="showVoltageAndCurrent">
<div class="w-full">
<span class="font-mono">{{ voltageDisplayValue }}</span>
<span> V</span>
</div>
<div class="w-full">
<div class="w-full">
<span class="font-mono">{{ voltageDisplayValue }}</span>
<span> V</span>
</div>
<div class="w-full">
<template v-if="showCurrent">
<span class="font-mono">{{ currentDisplayValue }}</span>
<span> A</span>
</div>
</template>
<template v-else>
<div class="w-full">
</template>
<template v-else>
<span class="font-mono">{{ instantaneousWattsDisplayValue }}</span>
<span> W</span>
</div>
<div class="w-full">
<span class="font-mono">{{ totalConsumedWattsDisplayValue }}</span>
<span> Wh</span>
</div>
</template>
</template>
</div>
</div>
</div>
<v-dialog v-model="widgetStore.miniWidgetManagerVars(miniWidget.hash).configMenuOpen" width="auto">
<v-card class="pa-4 text-white" style="border-radius: 15px" :style="interfaceStore.globalGlassMenuStyles">
<v-card class="pa-4 text-white w-[20rem]" style="border-radius: 15px" :style="interfaceStore.globalGlassMenuStyles">
<v-card-title class="text-center">Battery Indicator Config</v-card-title>
<v-card-text class="flex flex-col gap-y-4">
<v-checkbox
v-model="miniWidget.options.showVoltageAndCurrent"
label="Show Voltage and Current"
hide-details
@update:model-value="validateShowOptions"
/>
<v-checkbox
v-model="miniWidget.options.showPowerAndConsumption"
label="Show Power and Consumption"
hide-details
@update:model-value="validateShowOptions"
/>
<v-checkbox v-model="miniWidget.options.showCurrent" label="Show Current" hide-details />
<v-checkbox v-model="miniWidget.options.showPower" label="Show Power" hide-details />
<v-text-field
v-if="miniWidget.options.showVoltageAndCurrent && miniWidget.options.showPowerAndConsumption"
v-model.number="toggleInterval"
v-model.number="userSetToggleInterval"
label="Toggle Interval (ms)"
type="number"
:min="minInterval"
step="100"
density="compact"
variant="outlined"
:error-messages="intervalErrorMessage"
@update:model-value="(v) => validateToggleInterval(Number(v))"
:disabled="!miniWidget.options.showCurrent || !miniWidget.options.showPower"
/>
<p class="text-red-500 text-center text-sm w-[full]">{{ errorMessage }}</p>
</v-card-text>
</v-card>
</v-dialog>
Expand Down Expand Up @@ -89,10 +72,12 @@ const store = useMainVehicleStore()
const widgetStore = useWidgetManagerStore()
const interfaceStore = useAppInterfaceStore()
const showVoltageAndCurrent = ref(true)
const showCurrent = ref(true)
const toggleIntervaler = ref<ReturnType<typeof setInterval> | undefined>(undefined)
const minInterval = 500
const toggleInterval = ref(miniWidget.value.options.toggleInterval ?? defaultOptions.toggleInterval)
const errorMessage = ref('')
const errorMessageTimeout = ref<ReturnType<typeof setTimeout> | undefined>(undefined)
const userSetToggleInterval = ref(miniWidget.value.options.toggleInterval ?? defaultOptions.toggleInterval)
const voltageDisplayValue = computed(() => {
if (store?.powerSupply?.voltage === undefined) return NaN
Expand All @@ -112,72 +97,61 @@ const instantaneousWattsDisplayValue = computed(() => {
return store.instantaneousWatts ? store.instantaneousWatts.toFixed(1) : NaN
})
const totalConsumedWattsDisplayValue = computed(() => {
return store.totalConsumedWatts.toFixed(1)
})
const batteryIconClass = computed(() => {
return 'mdi-battery'
})
const setupToggleInterval = (): void => {
if (toggleIntervaler.value) {
if (toggleIntervaler.value || errorMessageTimeout.value) {
clearInterval(toggleIntervaler.value)
clearTimeout(errorMessageTimeout.value)
}
toggleInterval.value = miniWidget.value.options.toggleInterval
if (miniWidget.value.options.showVoltageAndCurrent && miniWidget.value.options.showPowerAndConsumption) {
toggleIntervaler.value = setInterval(() => {
showVoltageAndCurrent.value = !showVoltageAndCurrent.value
}, miniWidget.value.options.toggleInterval)
// Ensure toggle interval is at least minInterval
if (userSetToggleInterval.value < minInterval) {
miniWidget.value.options.toggleInterval = minInterval
errorMessage.value = `Interval must be at least ${minInterval}ms.`
} else {
showVoltageAndCurrent.value = miniWidget.value.options.showVoltageAndCurrent
miniWidget.value.options.toggleInterval = userSetToggleInterval.value
}
}
watch(() => miniWidget.value.options, setupToggleInterval, { deep: true })
const validateShowOptions = (value: boolean): void => {
if (!miniWidget.value.options.showVoltageAndCurrent && !miniWidget.value.options.showPowerAndConsumption) {
// If both options are unchecked, force the current one to be checked
miniWidget.value.options[value ? 'showPowerAndConsumption' : 'showVoltageAndCurrent'] = true
// Ensure at least one of current or power is enabled
if (!miniWidget.value.options.showCurrent && !miniWidget.value.options.showPower) {
miniWidget.value.options.showCurrent = true
miniWidget.value.options.showPower = true
errorMessage.value = 'At least one of the options must be enabled.'
}
}
const intervalErrorMessage = ref('')
const validateToggleInterval = (value: number): void => {
if (value < minInterval) {
intervalErrorMessage.value = `Interval must be at least ${minInterval}ms`
if (miniWidget.value.options.showCurrent && miniWidget.value.options.showPower) {
toggleIntervaler.value = setInterval(() => {
showCurrent.value = !showCurrent.value
}, miniWidget.value.options.toggleInterval)
} else {
intervalErrorMessage.value = ''
miniWidget.value.options.toggleInterval = value
showCurrent.value = miniWidget.value.options.showCurrent
}
errorMessageTimeout.value = setTimeout(() => {
errorMessage.value = ''
if (userSetToggleInterval.value < minInterval) {
userSetToggleInterval.value = minInterval
}
}, 5000)
}
onBeforeMount(() => {
// If both show options are disabled, use default options
if (!miniWidget.value.options.showVoltageAndCurrent && !miniWidget.value.options.showPowerAndConsumption) {
miniWidget.value.options = { ...defaultOptions }
} else {
miniWidget.value.options = Object.assign({}, defaultOptions, miniWidget.value.options)
}
watch([() => miniWidget.value.options, userSetToggleInterval], setupToggleInterval, { deep: true })
// Ensure toggle interval is above the minimum
miniWidget.value.options.toggleInterval = Math.max(minInterval, miniWidget.value.options.toggleInterval)
onBeforeMount(() => {
miniWidget.value.options = Object.assign({}, defaultOptions, miniWidget.value.options)
setupToggleInterval()
// Register new variables for logging
// Register new variable for logging
datalogger.registerUsage('Instantaneous Watts' as DatalogVariable)
datalogger.registerUsage('Total Consumed Wh' as DatalogVariable)
})
onUnmounted(() => {
if (toggleIntervaler.value) {
clearInterval(toggleIntervaler.value)
}
if (toggleIntervaler.value !== undefined) return
clearInterval(toggleIntervaler.value)
})
</script>

Expand Down
2 changes: 0 additions & 2 deletions src/libs/sensors-logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export enum DatalogVariable {
time = 'Time',
date = 'Date',
instantaneousPower = 'Instantaneous power',
totalConsumedWh = 'Consumed power',
}

const logDateFormat = 'LLL dd, yyyy'
Expand Down Expand Up @@ -278,7 +277,6 @@ class DataLogger {
[DatalogVariable.time]: { value: format(timeNow, 'HH:mm:ss O'), hideLabel: true, ...timeNowObj },
[DatalogVariable.date]: { value: format(timeNow, 'LLL dd, yyyy'), hideLabel: true, ...timeNowObj },
[DatalogVariable.instantaneousPower]: { value: `${vehicleStore.instantaneousWatts?.toFixed(1)} W` || 'Unknown', ...timeNowObj },
[DatalogVariable.totalConsumedWh]: { value: `${vehicleStore.totalConsumedWatts.toFixed(1)} Wh`, ...timeNowObj },
}

/* eslint-enable vue/max-len, prettier/prettier, max-len */
Expand Down
11 changes: 0 additions & 11 deletions src/stores/mainVehicle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => {
const coordinates: Coordinates = reactive({} as Coordinates)
const powerSupply: PowerSupply = reactive({} as PowerSupply)
const instantaneousWatts = ref<number | undefined>(undefined)
const totalConsumedWatts = ref<number>(0)
const lastUpdateTime = ref<number>(Date.now())
const velocity: Velocity = reactive({} as Velocity)
const mainVehicle = ref<ArduPilot | undefined>(undefined)
const isArmed = ref<boolean | undefined>(undefined)
Expand Down Expand Up @@ -399,16 +397,8 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => {
mainVehicle.value.onPowerSupply.add((newPowerSupply: PowerSupply) => {
Object.assign(powerSupply, newPowerSupply)

const currentTime = Date.now()
const timeDiff = (currentTime - lastUpdateTime.value) / 1000 // Convert to seconds

instantaneousWatts.value =
powerSupply.voltage && powerSupply.current ? powerSupply.voltage * powerSupply.current : undefined
totalConsumedWatts.value += (instantaneousWatts.value || 0 * timeDiff) / 3600

if (instantaneousWatts.value !== undefined) {
lastUpdateTime.value = currentTime
}
})
mainVehicle.value.onStatusText.add((newStatusText: StatusText) => {
Object.assign(statusText, newStatusText)
Expand Down Expand Up @@ -590,7 +580,6 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => {
velocity,
powerSupply,
instantaneousWatts,
totalConsumedWatts,
statusText,
statusGPS,
mode,
Expand Down

0 comments on commit e56752e

Please sign in to comment.