User Tools

Site Tools


palmpowermanagement

Контроль напряжения в PalmOS

Введение

В статье обсуждается что в действительности означает вольтаж и процент зарядки аккумулятора.

Время работы устройства на одной зарядке

Можно уверенно сказать, что батарея является узким местом в современных карманных устройствах. Если старые монохромные КПК жили неделями на двух ААА батарейках, то современные устройства требуют подзарядки раз в 2-3 дня в зависимости от активности использования.

КПК потребляют электроэнергию во всех состояниях: и в включенном и в выключенном. Необходимость сохранения данных в выключенном виде тоже требует питания, поэтому пальма не пытается работать до полного опустошения аккумулятора, а выключается раньше, оставляя часть заряда на сохранение данных “до ближайшего кредла”.

У пальм есть два важных порога разряженности батареи: предупреждающее и критическое. По достижению предупреждающего порога устройсво выдает сообщение пользователю. По достижению критического порога устройство выключается и продолжает сохранять данные.

Пороговые значения железно задаются в прошивке устройств. Как показывает следующее сообщение, http://palmz.4to.info/showpost.php?p=185918&postcount=5 , эти величины берутся с большим запасом, так что уменьшение порогов может продлить время работы устройства.

Что показывает пальм?

У любого устройства на PalmOS есть возможность показать пользователю текущее напряжение на аккумуляторе и степень его заряженности. Возникает вопрос - а откуда эти числа берутся? Насколько можно им доверять?

В API PalmOS существует функция, получающая информацию о состоянии батареи. Вот ее прототип:

UInt16	SysBatteryInfo(Boolean set, UInt16 *warnThresholdP, UInt16 *criticalThresholdP,
	Int16 *maxTicksP, SysBatteryKind* kindP, Boolean *pluggedIn, UInt8 *percentP);

Функция позволяет получить следующие характеристики:

  • текущее напряжение в сантивольтах
  • зарядка аккумулятора в процентах
  • напряжение в сантивольтах, при котором выдается сообщение о разрядке батареи
  • напряжение в сантивольтах, при котором устройство отключается
  • тип батареи (алкалиновая, Li-Ion, NiMH итд)
  • факт подключения к внешней зарядке
  • таймаут между последовательными показами сообщения о разрядке

Сразу возникают вопросы: насколько можно верить значени напряжения? Как рассчитывается разряженность батареи? Понятно, что где-то стоит ADC, который преобразовывает напряжение в некоторое число в диапазоне 0-255. А как из этого числа получить вольты с точностью до сотых долей? Понятно, что мини-вольтметру нужна калибрация.

Калибрационные поправки

В очень старые времена, когда пальмы были на батарейках AAA, никакой встроенной калибрации не было. Существовал хак, позволявший задать корректирующие значения вручную.

У моделей со встроенным аккумулятором погрешности измерений могли привести к порче батареи, поэтому проблему нужно было решать на уровне производителя. Разработчики PalmOS решили эту задачу следующим образом.

Большая часть системного ROM одинакова у всех экземпляров одной модели, но предусмотрена возможность прошивать индивидуальные данные. Эти данные прописываются в специальном формате и называются ROM Token. Каждый токен представляет из себя четырехбуквенное имя и блок данных. Самый известный токен имеет имя num. В него записывается FlashID устройства.

Для калибрации используется токен с именем adcc. В него записываются замеры двух пар (напряжение, значение ADC). Одно значение измеряется для маленького напряжения, а второе для большого. Из двух значений аппроксимацией можно получить значение напряжения с достаточной точностью.

typedef struct {
	UInt16	lowCentivolts;
	UInt16	lowAToDOutput;
	UInt16	highCentivolts;
	UInt16	highAToDOutput;
} SysAToDCalibrationTokenType;

Такой способ калибрации используется во всех устройствах от PalmOne у которых вместо ROM стоит перезаписываемая флешка.

Уровень разряженности

Процент разряда вычисляется как функция от напряжения. Поскольку зависимость разряда от напряжения нелинейная, то воспользоваться линейной аппроксимацией не получится. Поэтому используются предопределенные значения напряжения в 11 точках, соответствующих 0%, 10%, 20%… 100% заряда. Находится интервал, в который попадает текущее напряжение и уже внутри интервала используется линейная аппроксимация.

Тип батареи

Магическое значение “тип батареи” определяет характеристики батарее: предупреждающее и критическое напряжение, выборки кривой разряда итд. Желающие могут поглядеть на данные, которые определяются для каждого типа батарей и аккумуляторов.

typedef struct {
	Word	sysBattDataStructVersion;	// rev level of the structure (this one is 1)
	Word	sysBattMildWrngVoltage;		// in centivolts-- this is the voltage where the warning dialog appears
	Word	sysBattSevereWrngVoltage;	// in cVolts-- this is the voltage where the critical warning dialog appears
	Word	sysBattMildWrngPercent;		// Mild warning percentage for 3.2 and newer (rev 2)
	Word	sysBattSevereWrngPercent;	// Severe warning percentage for 3.2 and newer (rev 2)
	Word	sysBattShutdownEnVoltage;	// in cV-- This voltage causes us to do a software shutdown
	Word	sysBattShutdownDisVoltage;	// in cV-- This voltage allows us to wakeup from shutdown
	Word	sysBattMinIRVoltage;			// prevents IR from working if below this threshold
	DWord	sysBattMildWrngTimeout;		// in ticks-- this is the number of ticks to wait between displaying warning dialogs
	DWord	sysBattSevereWrngTimeout;	// in ticks-- this is the number of ticks to wait between displaying critical warning dialogs
	Word	sysBattCritWarnOffDays;		// in days-- number of days between mild and severe warnings
	DWord	sysBattCritWarnOnTicks;		// in ticks-- number of ticks between mild and severe warnings
	Word	sysBattStepsPerVolt;			// for scaling A/D to Voltages
	SWord	sysBattVoltageStepOffset;	// for scaling A/D to Voltages
	DWord	sysBattReserved1;				// future use
	DWord	sysBattReserved2;				// future use
	Word	sysBattVoltageCurve[11];	// in cV; this is the voltage at the specified percentage/10; i.e. if the voltage
												// with 20% remaining is 2.5 volts, battVoltageCurve[2] = 250.
	} SysBatteryDataStruct, *SysBatteryDataStructP;

Соберем вместе

Теперь посмотрим на функционирование системы в целом. При старте (и при смене типа батареи) PalmOS выбирает таблицу параметров батареи и калибровочные значения.

С некоторой периодичностью система считывает значение ADC и с помощью данных из параметров батареи и калибрационных поправок происходит вычисление напряжения. По таблице sysBattVoltageCurve вычисляется степень разряженности батареи.

Когда напряжение падает ниже уровня warning, на экран выдается предупреждение. Когда напряжение падает ниже уровня critical, устройство выключается.

Работа с батареей была в модуле, который писал производитель устройства, но функции и системные данные хранились в данных PalmOS 4, поэтому было можно написать универсальный хак, который позволял корректировать времена выключения вручную.

PalmOS5. Что нового?

В PalmOS5 были внесены изменения в идеологию работы с акумулятором. Что было сделано?

На самом верхнем уровне, уровне m68k API (который все программы и используют), никаких изменений не видно. Все также используется функция SysBatteryInfo.

Ниже идет уровень ARM API. Аналог старой функции SysBatteryInfo теперь называется SysBatteryInfoV40, а новая функция SysBatteryInfo вместо сантивольтов возвращает только проценты разрядки. SysBatteryInfoV40 вызывает SysBatteryInfo которая в свою очередь вызывает HALBatteryGetInfo.

Теперь вопрос - как SysBatteryInfoV40 вычисляет напряжение по процентам? Очень просто: cV = percents * 0.5 + 370. Всегда. То есть напряжение, возвращаемое в программы не имеет никакого отношения к реальному напряжению. Скорее это просто показания “идеального аккумулятора” в вакууме.

Функция HALBatteryGetInfo находится в модуле DAL. Этот модуль пишется разработчиками конкретного устройства. Реализация этой функции возвращает информацию в максимально абстрактном виде, в процентах разрядки батареи. Таким образом у ядра PalmOS (у модуля boot.prc) нет никакой возможности узнать реальное напряжение.

Err HALBatteryGetInfo(UInt16 *warnThresholdPercentP,
		UInt16 *criticalThresholdPercentP,
		UInt16 *shutdownThresholdPercentP,
		UInt32 *warnMaxTicksP, SysBatteryKind *kindP,
		Boolean *pluggedInP, SysBatteryState *stateP,
		UInt8 *percentP);

Таким образом в PalmOS 5 нет возможности узнать реальное напряжение. Более того, модули DAL могут и не вычислять напряжение вообще, а сразу переводить его из чисел на выходе ADC в проценты. Это усложняет реализацию ручной поправки критических значений. Если раньше было достаточно подкорректировать системную переменную “критическое напряжение”, то теперь такой переменной нет. Есть просто проценты зарядки при которых устройство отключается. А сам модуль DAL использует внутренние переменные для определения момента выключения и коррекция процентов ни к чему не приводит.

FullPower

Разработчики из Mobile Stream ( http://www.mobile-stream.com/ ) таки раскопали место хранения вольтажа. Программа FullPower позволяет изменять критический порог.

Эта программа залезает в переменные модуля DAL и изменяет пороговые напряжения. Поскольку DALы разных устройств работают по-разному, программа может не работать на некоторых устройствах.

==== Ссылки

http://palmz.4to.info/showthread.php?t=21156 - часть информации была заимствована из обсуждения

palmpowermanagement.txt · Last modified: 2005/06/14 08:05 by 127.0.0.1