/* * Battery driver for LEGO MINDSTORMS EV3 * * Copyright (C) 2017 David Lechner <david@lechnology.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation.
* This program is distributed "as is" WITHOUT ANY WARRANTY of any * kind, whether express or implied; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
*/
struct lego_ev3_battery { struct iio_channel *iio_v; struct iio_channel *iio_i; struct gpio_desc *rechargeable_gpio; struct power_supply *psy; int technology; int v_max; int v_min;
};
staticint lego_ev3_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
{ struct lego_ev3_battery *batt = power_supply_get_drvdata(psy); int ret, val2;
switch (psp) { case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = batt->technology; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: /* battery voltage is iio channel * 2 + Vce of transistor */
ret = iio_read_channel_processed(batt->iio_v, &val->intval); if (ret) return ret;
val->intval *= 2000;
val->intval += 50000;
/* plus adjust for shunt resistor drop */
ret = iio_read_channel_processed(batt->iio_i, &val2); if (ret) return ret;
val2 *= 1000;
val2 /= 15;
val->intval += val2; break; case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
val->intval = batt->v_max; break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
val->intval = batt->v_min; break; case POWER_SUPPLY_PROP_CURRENT_NOW: /* battery current is iio channel / 15 / 0.05 ohms */
ret = iio_read_channel_processed(batt->iio_i, &val->intval); if (ret) return ret;
switch (psp) { case POWER_SUPPLY_PROP_TECHNOLOGY: /* * Only allow changing technology from Unknown to NiMH. Li-ion * batteries are automatically detected and should not be * overridden. Rechargeable AA batteries, on the other hand, * cannot be automatically detected, and so must be manually * specified. This should only be set once during system init, * so there is no mechanism to go back to Unknown.
*/ if (batt->technology != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) return -EINVAL; switch (val->intval) { case POWER_SUPPLY_TECHNOLOGY_NiMH:
batt->technology = POWER_SUPPLY_TECHNOLOGY_NiMH;
batt->v_max = 7800000;
batt->v_min = 5400000; break; default: return -EINVAL;
} break; default: return -EINVAL;
}
batt = devm_kzalloc(dev, sizeof(*batt), GFP_KERNEL); if (!batt) return -ENOMEM;
platform_set_drvdata(pdev, batt);
batt->iio_v = devm_iio_channel_get(dev, "voltage");
err = PTR_ERR_OR_ZERO(batt->iio_v); if (err) return dev_err_probe(dev, err, "Failed to get voltage iio channel\n");
batt->iio_i = devm_iio_channel_get(dev, "current");
err = PTR_ERR_OR_ZERO(batt->iio_i); if (err) return dev_err_probe(dev, err, "Failed to get current iio channel\n");
batt->rechargeable_gpio = devm_gpiod_get(dev, "rechargeable", GPIOD_IN);
err = PTR_ERR_OR_ZERO(batt->rechargeable_gpio); if (err) return dev_err_probe(dev, err, "Failed to get rechargeable gpio\n");
/* * The rechargeable battery indication switch cannot be changed without * removing the battery, so we only need to read it once.
*/ if (gpiod_get_value(batt->rechargeable_gpio)) { /* 2-cell Li-ion, 7.4V nominal */
batt->technology = POWER_SUPPLY_TECHNOLOGY_LION;
batt->v_max = 84000000;
batt->v_min = 60000000;
} else { /* 6x AA Alkaline, 9V nominal */
batt->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
batt->v_max = 90000000;
batt->v_min = 48000000;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.