From: Guenter Roeck <linux@roeck-us.net>
To: lm-sensors@vger.kernel.org
Subject: Re: [lm-sensors] [PATCH] hwmon: (mcp3021) Fix broken output scaling
Date: Wed, 01 Jul 2015 03:11:14 +0000 [thread overview]
Message-ID: <55935A52.1060607@roeck-us.net> (raw)
In-Reply-To: <20150629214453.GA30170@nick.stevens-ubuntu>
Hi Nick,
On 06/29/2015 02:45 PM, Stevens, Nick wrote:
> The mcp3021 scaling code is dividing the VDD (full-scale) value in
> millivolts by the A2D resolution to obtain the scaling factor. When VDD
> is 3300mV (the standard value) and the resolution is 12-bit (4096
> divisions), the result is a scale factor of 3300/4096, which is always
> one. Effectively, the raw A2D reading is always being returned because
> no scaling is applied.
>
> This patch fixes the issue while still using only integer math by
> converting VDD to microvolts before dividing by resolution, and then
> converting back to millivolts at return.
>
> Signed-off-by: Nick Stevens <Nick.Stevens@digi.com>
> ---
> drivers/hwmon/mcp3021.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
> index d219c06..c3bbba2 100644
> --- a/drivers/hwmon/mcp3021.c
> +++ b/drivers/hwmon/mcp3021.c
> @@ -87,10 +87,15 @@ static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
> if (val = 0)
> return 0;
>
> - val = val * data->output_scale - data->output_scale / 2;
> + /* Convert VDD setting to uV and divide by resolution to get uV/bit */
> + u32 uv_per_bit = (data->vdd * 1000) / (
> + (1 << data->output_res) * data->output_scale);
>
> - return val * DIV_ROUND_CLOSEST(data->vdd,
> - (1 << data->output_res) * data->output_scale);
> + /* Scale raw reading by uV/bit */
> + u32 uv_val = val * uv_per_bit;
> +
> + /* Convert back from uV to mV */
> + return (u16)DIV_ROUND_CLOSEST(uv_val, 1000);
How about simplifying this to
return DIV_ROUND_CLOSEST(val * data->vdd,
(1 << data->output_res) * data->output_scale);
instead ? Result is pretty much the same as far as I can see.
You forgot to multiply uv_val with scale, which causes the results
for MCP3021 to be wrong by a factor of 4.
I have no idea why
val = val * data->output_scale - data->output_scale / 2;
in the original code subtracts data->output_scale / 2; that seems wrong to me.
Any idea ?
Thanks,
Guenter
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
next prev parent reply other threads:[~2015-07-01 3:11 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-29 21:45 [lm-sensors] [PATCH] hwmon: (mcp3021) Fix broken output scaling Stevens, Nick
2015-07-01 3:11 ` Guenter Roeck [this message]
2015-07-01 15:39 ` Stevens, Nick
2015-07-01 16:59 ` Guenter Roeck
2015-07-01 18:38 ` Stevens, Nick
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55935A52.1060607@roeck-us.net \
--to=linux@roeck-us.net \
--cc=lm-sensors@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.