Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] Battery % Display in 1% increments #27

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

r3wt
Copy link

@r3wt r3wt commented Apr 17, 2022

So i started out simply trying to shave cycles out of onBatteryChanged., mainly by avoiding loops and conversion between number -> string -> number, and ended up completely rewriting it instead to show 101 points of precision in 1% increments, from 0% to 100%. I followed the voltage range "clamps", and wrote a script which calculates the voltage range for each percentage, then generates the code to be placed in onBatteryChanged.

I do not have a cutiepi yet to test this on, so i was hoping the dev team might be willing to test it on a device and ensure it works properly. It should, based on everything i read about QT javascript support

Pros:

  • Calculate battery percent without excessively wasting resources
  • 95% more efficient (300k ops/s vs 13k ops/s)
  • 101 points of precision vs 21 - full 0% to 100% can be displayed.

Cons:

  • My math skills are poor, I probably misunderstood how voltage decay works. i know its exponential but wasn't sure. I tried various "factors" until it looked right to me
  • Extremely verbose (500 LOC)

Wanted to create a jsbench test suite, but the code exceeds the maximum allowed size for a test case.
image

Here's the script i used to generate the code:

const fs = require('fs');

var batteryVoltages = [
  "3.89",
  "3.88",
  "3.86",
  "3.82",
  "3.80",
  "3.76",
  "3.73",
  "3.69",
  "3.67",
  "3.65",
  "3.63",
  "3.61",
  "3.60",
  "3.59",
  "3.56",
  "3.55",
  "3.53",
  "3.51",
  "3.49",
  "3.48",
  "3.00",
].map(v=>parseFloat(v)*1000);

var batteryPercentages = [
  100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10,
  5, 0,
];

function generateRange(arr,baseVal) {
  let res = [];
  for(let i=arr.length-1;i>0;i--){
    let a = arr[i]+1;
    let b = arr[i-1]
    if(i===arr.length-1) {
      a=baseVal;
    }
    res.push([b,a]);
  }
  return res.reverse();
}

function getNums(n,f,tot){
  let x=1;
   const arr=[...new Array(n)]
    .map(c=>x*=f);
   const mul=tot/arr.reduce((a,c)=>a+c);
   return arr.map(v=>mul*v)
}

function expandRanges( pctRanges, voltRanges ) {
  return pctRanges.map((pr,i)=>{
    let n = pr[0]-pr[1]+1;// number of elements
    let prFinal = [];
    for(let i=pr[1];i<=pr[0];i++) {
      prFinal.push(i)
    }
    let vr = voltRanges[i];
    let vrFinal = [];
    let total = vr[0]-vr[1]
    let chunks = getNums(n,1.12359,total).reverse().map(v=>Math.round(v));
    let start = vr[1];
    for(let i=0;i<chunks.length;i++){
      vrFinal.push(start);
      start+=chunks[i];
      if(i==chunks.length-1){
        vrFinal[i]=vr[0];
      }
    }
    return { pct: prFinal.reverse(), voltage: vrFinal.reverse() };
  });
}

const batteryPercentageRanges = generateRange(batteryPercentages,0);
const batteryVoltageRanges = generateRange(batteryVoltages,3000);

console.log(batteryPercentageRanges,batteryVoltageRanges);

const crossMap = expandRanges( batteryPercentageRanges, batteryVoltageRanges );

console.log(crossMap);

const flattenedMap = [
  [],//voltages
  []//percentage
];
crossMap.forEach( item => {
  flattenedMap[0].push(...item.voltage);
  flattenedMap[1].push(...item.pct);
})

console.log(flattenedMap);
console.log(flattenedMap[0].length,flattenedMap[1].length);

let code = [];

code.push(
`
view.queue.push(battery);// there is no need to divide to get value volts, just use raw mv
if (view.queue.length > 15) {
  view.queue.shift();
}
var sum = 0;
var nSum = view.queue.length;
`);
for(let i=0;i<15;i++) {
  code.push(
  `if(view.queue[${i}]!==undefined) {
    sum += view.queue[${i}];
  }`
  );
}

code.push(`var meanVol=~~(sum/nSum);//strip decimal bits (round to integer)`);
code.push('switch(true){');

for(let i=0;i<flattenedMap[0].length;i++){
  if(i===0){
    //special case high voltage
    code.push(`case(meanVol>${flattenedMap[0][i+1]}):
      batteryPercentage=${flattenedMap[1][i]};
    break;
    `);  
  }
  else if(i===flattenedMap[0].length-2) {
    //special case 1%
    code.push(`case(meanVol>${flattenedMap[0][i]}):
      batteryPercentage=${flattenedMap[1][i]};
    break;
    `);  
  }
  else if(i===flattenedMap[0].length-1) {
    //special case low voltage
    code.push(`case(meanVol>${flattenedMap[0][i]}):
      //fall through to default case
    `);  
  }else{
    // all other case
    code.push(`case(meanVol>${flattenedMap[0][i+1]}&&meanVol<=${flattenedMap[0][i]}):
      batteryPercentage=${flattenedMap[1][i]};
    break;
    `);  
  }
  
}
code.push(`
  default:
    // doesnt seem possible but just in case something weird happened
    batteryPercentage=0;
  break;  
`)
code.push('}');
code.push('view.stableVol=Math.floor((meanVol/1000)*100)/100;');
code.push(`
if (!batteryCharging) { 
  if (view.queue.length < 5) {
    batteryText.text = "Checking..";
  } else {
    batteryText.text = batteryPercentage + "%";
  }
}
`);

const finalGeneratedCode = code.join("\r\n");

fs.writeFileSync('./onBatteryChanged.js',finalGeneratedCode,'utf-8');

@penk
Copy link
Contributor

penk commented Apr 18, 2022

@r3wt thanks! let me take a look of it.

@penk penk self-assigned this Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants