Editing Mer/Documentation/BME Protocol

Warning: You are not logged in. Your IP address will be recorded in this page's edit history.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
-
{{Mer}}
+
This documentation is entirely for the purpose of implementing software gathering battery information on Nokia Internet Tablets, not alteration of battery management state.  
-
 
+
-
This documentation is entirely for the purpose of implementing software gathering battery information on Nokia Internet Tablets, not alteration of battery management state.
+
-
 
+
-
See [[Mer/Status/Battery | battery status]] for the current state of support for BME in Mer.
+
-
 
+
-
This information (other than the basic explanations of battery behaviour) is not applicable to the n900, which has a different protocol.
+
Existing code:
Existing code:
Line 60: Line 54:
struct emsg_bme_bulk_reply {
struct emsg_bme_bulk_reply {
-
   uint32    unknown1; // (Apparently always 0.)
+
   uint32    unknown1;
-
   uint32    unknown2; // (Apparently always 0.)
+
   uint32    unknown2;
-
   uint32    unknown3; // (Apparently always 0.)
+
   uint32    unknown3;
-
   uint16    sw_status; // Battery monitor SW status.  (Values 0..3 encountered.)
+
   uint16    sw_status; // Battery monitor SW status
   uint16    instaneous_battery_voltage; // Instantaneous battery voltage (mV)
   uint16    instaneous_battery_voltage; // Instantaneous battery voltage (mV)
   uint16      // Remaining standby time to battery low (mins)
   uint16      // Remaining standby time to battery low (mins)
-
   uint16    unknown4; // (Apparently always 0.)
+
   uint16    unknown4;
-
   uint16    unknown5; // (Values 0..24 encountered, with 0 being by far most common.)
+
   uint16    unknown5;
   uint16    unknown6;
   uint16    unknown6;
   uint16    // Battery monitor check voltage (mV)
   uint16    // Battery monitor check voltage (mV)
-
   uint16    // Battery low warning interval counter.  (Values 0..4 encountered, with 0 being by far most common.)
+
   uint16    // Battery low warning interval counter
   uint16    // Double median filtered battery voltage
   uint16    // Double median filtered battery voltage
   uint16    // Initial battery monitor voltage (mV)
   uint16    // Initial battery monitor voltage (mV)
-
   uint16    // Time per battery bar (mins).  Apparently always 2520.
+
   uint16    // Time per battery bar (mins)
   uint16    // DMF voltage sampled at first battery low (mV)
   uint16    // DMF voltage sampled at first battery low (mV)
   uint32    // Average phone current (uA)
   uint32    // Average phone current (uA)
Line 81: Line 75:
   uint16    // Largest TX-Off/On voltage difference (mV)
   uint16    // Largest TX-Off/On voltage difference (mV)
   uint8      // Battery bar level log mask
   uint8      // Battery bar level log mask
-
   uint8      // Previous battery bar level.  (Values 0..4 encountered.)
+
   uint8      // Previous battery bar level
-
   uint8      // Battery low reason.  (Values 0,1 encountered.)
+
   uint8      // Battery low reason
-
   uint8      // CS state information.  (Apparently always 1.)
+
   uint8      // CS state information  
-
   uint16    // Number of battery bars.  (Values 1..4.)
+
   uint16    // Number of battery bars
-
   uint16    // Battery type.  (Value 4 for me, with standard Nokia battery.)
+
   uint16    // Battery type
   uint16    // Temperature, in kelvin
   uint16    // Temperature, in kelvin
   uint16    // Battery capacity  
   uint16    // Battery capacity  
-
   uint16    // Battery impedance (mOhm).  (Apparently always 160.)
+
   uint16    // Battery impedance (mOhm)
-
   uint16    // Present value of v_bat_full_level.  (Apparently always 3855.)
+
   uint16    // Present value of v_bat_full_level
-
   uint16    // Present value of v_bat_low_ths_mv.  (Apparently always 3650.)
+
   uint16    // Present value of v_bat_low_ths_mv
-
   uint16    unknown7; (Values 0..21 encountered.)
+
   uint16    unknown7;
-
   uint16    unknown8; (Apparently always 0.)
+
   uint16    unknown8;
-
   uint16    unknown9; (Apparently always 0.)
+
   uint16    unknown9;
-
   uint16    // Load current estimated by Batmon4 (uA).  (Various values in 0..125 encountered.)
+
   uint16    // Load current estimated by Batmon4 (uA)
-
   uint16    unknown10; (Apparently always 0.)
+
   uint16    unknown10;
};
};
</pre>
</pre>
-
The '''“Instantaneous battery voltage (mV)”''' field’s observed values have a certain regular spacing indicating a linear function of some integer value with a smaller range, presumably retu adc register #8.  If it is indeed from that register, then note there is a non-zero offset involved: one function that gives values consistent with the set of values observed and that somewhat matches one set of observations of both fields (which unfortunately had a non-negligible delay between sampling the two) is mV = 2252.362 + 2.81361 * adc#8 (where the multiplier is fairly accurate, while the constant is accurate to within 2 units in the last place; the choice of 2252.362 rather than some integer multiple of 2.81361 away from there is based on how well ioctl values match with values read from bme at about the same time, though there was still quite a bit of noise, and the methodology could be improved).
+
The “Instantaneous battery voltage (mV)” field’s observed values have a certain regular spacing indicating a linear function of some integer value with a smaller range, presumably retu adc register #8.  If it is indeed from that register, then note there is a non-zero offset involved: from memory, one function that gives values consistent with the set of values observed and that somewhat matches observations of both fields (unfortunately with non-negligible delay between sampling the two so far) is mV = 2252.361 + 2.81361 * adc#8 (where the multiplier is fairly accurate if I've correctly remembered it, but the constant could be out by some multiple of 2.81361).  -- pjrm.
-
 
+
-
One might wonder how bme authors came up with numbers like 2252.362 and 2.81361One hypothesis would be that someone measured a voltage for two adc8 values (perhaps one near the top of the range and one near the bottom), and used a straight-line fit for the rest.  If the mV field is calculated by rounding to nearest int rather than flooring, and the two voltage measurements were both an integer number of mV, then there is exactly one pair of integer points that matches the data: adc8 of 238 was 3222mV, while 576 was 4173mV.  Thus, without yet having looked for other simple models, it seems most likely that this mV field is calculated by some expression equivalent to mV = 3222 + round((adc8 - 238) * ((4173 - 3222) / (576 - 238.))), i.e. mV = 3222 + round((adc8 - 238) * (951 / 338.)); where the rounding function can either be C99 round or floor(x+.5), or rint with some rounding modes, so long as 3697.5 rounds to 3698.
+
-
 
+
-
Accordingly, some uses of this “instantaneous voltage” field would do well to convert to an integer adc8 value (or convert to an integer adc8 value then convert back to a non-integer mV value), in order to avoid uneven steps between values (sometimes 2mV between neighbouring values and sometimes 3mV).  This can be done as adc8 = 238 + round((claimed_mV - 3222) * (338 / 951.)).
+
-
 
+
-
The '''“Battery monitor check voltage (mV)”''' field has similar values to the “Instantaneous battery voltage (mV)” field, but without obvious regular spacing.  I (pjrm) don't know how it's calculated.
+
-
 
+
-
Voltage levels depend not just on amount of charge remaining in the battery, but also recent electrical load: the voltage level goes down markedly while the CPU is being heavily used, for example.
+
-
 
+
-
There is some weak evidence that the voltage level goes down by about 1mV for each 3 units of backlight level (so 40–50mV for full brightness compared to screen off).  The main weakness of this evidence is that there's no serious correction for the effect of CPU usage on voltage, and one would assume CPU usage to correlate with backlight.
+
-
 
+
-
'''“Time per battery bar”''' seems to be a constant 2520; edit this page if you've seen a different value.
+
-
 
+
-
The '''“Average phone current”''' field has some strangeness in that if there is a long period of high CPU activity then it takes 3-7 seconds before this field's value increases (even though the voltage field drops straight away, suggesting that the true current does drop straight away); but the field is much quicker to go down once the CPU activity stops, so it's not just a matter of always lagging by a few seconds (such as because of using a simple averaging/smoothing method).  One might suggest that this could be because some thread that updates the average is at low priority and doesn't get scheduled for a while, but the "CPU activity" in the experiment consisted of alternating ~100ms of full CPU followed by a usleep of 100ms, so this effect presumably isn't just because of standard kernel scheduling decisions and niceness.
+
-
'''“Number of battery bars”''' is something like min(4, ceil(standby-time-remaining / time-per-bar)), but with a bit of lag: sometimes time-per-bar * n-bars can exceed standby-time-remaining by 2522 or so.  (Where of course standby-time-remaining means the value of the “Remaining standby time to battery low (mins)” field, time-per-bar means the “Time per battery bar” field, and n-bars means the “Number of battery bars” field.) Note the ‘min(4,’ part: standby-time-remaining can be over 4000mins more than the product of those two fields would suggest.
+
The “Battery monitor check voltage (mV)” field has similar values to the “Instantaneous battery voltage (mV)” field, but without obvious regular spacing.  I don't know how it's calculated.  -- pjrm.
== Some BULK1 message (0x43, 0x00) ==
== Some BULK1 message (0x43, 0x00) ==
Line 186: Line 166:
Some battery-related information is also available from retu adc registers (which in turn are available via ioctl's on /dev/rutu: see retu-adc source).
Some battery-related information is also available from retu adc registers (which in turn are available via ioctl's on /dev/rutu: see retu-adc source).
-
It's said that register 3 shows whether charging is occurring: with value 0 meaning "not being charged", while "values 0xff and above" are an indication of the voltage being applied for charging.  Matan adds (http://talk.maemo.org/showpost.php?p=259465&postcount=43) that values around 0x100 indicate charging, while values around 0x170 indicate that the power source is connected but we aren't charging.
+
It's said that register 3 shows whether charging is occurring: with value 0 meaning "not being charged", while "values 0xff and above" are an indication of the voltage being applied for charging.
Register 8 apparently indicates battery voltage.  See the note above about “instantaneous battery voltage (mV)” for how it might correspond to one measure of voltage.
Register 8 apparently indicates battery voltage.  See the note above about “instantaneous battery voltage (mV)” for how it might correspond to one measure of voltage.

Learn more about Contributing to the wiki.


Please note that all contributions to maemo.org wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see maemo.org wiki:Copyrights for details). Do not submit copyrighted work without permission!


Cancel | Editing help (opens in new window)

Templates used on this page: