/* gain to pulse and scale conversion */ #define HX711_GAIN_MAX 3 #define HX711_RESET_GAIN 128
struct hx711_gain_to_scale { int gain; int gain_pulse; int scale; int channel;
};
/* * .scale depends on AVDD which in turn is known as soon as the regulator * is available * therefore we set .scale in hx711_probe() * * channel A in documentation is channel 0 in source code * channel B in documentation is channel 1 in source code
*/ staticstruct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
{ 128, 1, 0, 0 },
{ 32, 2, 0, 1 },
{ 64, 3, 0, 0 }
};
staticint hx711_get_gain_to_pulse(int gain)
{ int i;
for (i = 0; i < HX711_GAIN_MAX; i++) if (hx711_gain_to_scale[i].gain == gain) return hx711_gain_to_scale[i].gain_pulse; return 1;
}
staticint hx711_get_gain_to_scale(int gain)
{ int i;
for (i = 0; i < HX711_GAIN_MAX; i++) if (hx711_gain_to_scale[i].gain == gain) return hx711_gain_to_scale[i].scale; return 0;
}
staticint hx711_get_scale_to_gain(int scale)
{ int i;
for (i = 0; i < HX711_GAIN_MAX; i++) if (hx711_gain_to_scale[i].scale == scale) return hx711_gain_to_scale[i].gain; return -EINVAL;
}
struct hx711_data { struct device *dev; struct gpio_desc *gpiod_pd_sck; struct gpio_desc *gpiod_dout; int gain_set; /* gain set on device */ int gain_chan_a; /* gain for channel A */ struct mutex lock; /* * triggered buffer * 2x32-bit channel + 64-bit naturally aligned timestamp
*/ struct {
u32 channel[2];
aligned_s64 timestamp;
} buffer; /* * delay after a rising edge on SCK until the data is ready DOUT * this is dependent on the hx711 where the datasheet tells a * maximum value of 100 ns * but also on potential parasitic capacities on the wiring
*/
u32 data_ready_delay_ns;
u32 clock_frequency;
};
/* * if preempted for more then 60us while PD_SCK is high: * hx711 is going in reset * ==> measuring is false
*/
local_irq_save(flags);
gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
/* * wait until DOUT is ready * it turned out that parasitic capacities are extending the time * until DOUT has reached it's value
*/
ndelay(hx711_data->data_ready_delay_ns);
/* * here we are not waiting for 0.2 us as suggested by the datasheet, * because the oscilloscope showed in a test scenario * at least 1.15 us for PD_SCK high (T3 in datasheet) * and 0.56 us for PD_SCK low on TI Sitara with 800 MHz
*/
gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
local_irq_restore(flags);
/* * make it a square wave for addressing cases with capacitance on * PC_SCK
*/
ndelay(hx711_data->data_ready_delay_ns);
/* sample as late as possible */ return gpiod_get_value(hx711_data->gpiod_dout);
}
staticint hx711_read(struct hx711_data *hx711_data)
{ int i, ret; int value = 0; int val = gpiod_get_value(hx711_data->gpiod_dout);
/* we double check if it's really down */ if (val) return -EIO;
for (i = 0; i < 24; i++) {
value <<= 1;
ret = hx711_cycle(hx711_data); if (ret)
value++;
}
value ^= 0x800000;
for (i = 0; i < hx711_get_gain_to_pulse(hx711_data->gain_set); i++)
hx711_cycle(hx711_data);
return value;
}
staticint hx711_wait_for_ready(struct hx711_data *hx711_data)
{ int i, val;
/* * in some rare cases the reset takes quite a long time * especially when the channel is changed. * Allow up to one second for it
*/ for (i = 0; i < 100; i++) {
val = gpiod_get_value(hx711_data->gpiod_dout); if (!val) break; /* sleep at least 10 ms */
msleep(10);
} if (val) return -EIO;
return 0;
}
staticint hx711_reset(struct hx711_data *hx711_data)
{ int val = hx711_wait_for_ready(hx711_data);
if (val) { /* * an examination with the oszilloscope indicated * that the first value read after the reset is not stable * if we reset too short; * the shorter the reset cycle * the less reliable the first value after reset is; * there were no problems encountered with a value * of 10 ms or higher
*/
gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
msleep(10);
gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
val = hx711_wait_for_ready(hx711_data);
/* after a reset the gain is 128 */
hx711_data->gain_set = HX711_RESET_GAIN;
}
return val;
}
staticint hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
{ int ret;
if (chan == 0) { if (hx711_data->gain_set == 32) {
hx711_data->gain_set = hx711_data->gain_chan_a;
ret = hx711_read(hx711_data); if (ret < 0) return ret;
ret = hx711_wait_for_ready(hx711_data); if (ret) return ret;
}
} else { if (hx711_data->gain_set != 32) {
hx711_data->gain_set = 32;
ret = hx711_read(hx711_data); if (ret < 0) return ret;
ret = hx711_wait_for_ready(hx711_data); if (ret) return ret;
}
}
return 0;
}
staticint hx711_reset_read(struct hx711_data *hx711_data, int chan)
{ int ret; int val;
/* * hx711_reset() must be called from here * because it could be calling hx711_read() by itself
*/ if (hx711_reset(hx711_data)) {
dev_err(hx711_data->dev, "reset failed!"); return -EIO;
}
ret = hx711_set_gain_for_channel(hx711_data, chan); if (ret < 0) return ret;
val = hx711_read(hx711_data);
return val;
}
staticint hx711_read_raw(struct iio_dev *indio_dev, conststruct iio_chan_spec *chan, int *val, int *val2, long mask)
{ struct hx711_data *hx711_data = iio_priv(indio_dev);
switch (mask) { case IIO_CHAN_INFO_RAW:
mutex_lock(&hx711_data->lock);
staticint hx711_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct hx711_data *hx711_data = iio_priv(indio_dev); int ret; int gain;
switch (mask) { case IIO_CHAN_INFO_SCALE: /* * a scale greater than 1 mV per LSB is not possible * with the HX711, therefore val must be 0
*/ if (val != 0) return -EINVAL;
mutex_lock(&hx711_data->lock);
gain = hx711_get_scale_to_gain(val2); if (gain < 0) {
mutex_unlock(&hx711_data->lock); return gain;
}
if (gain != hx711_data->gain_set) {
hx711_data->gain_set = gain; if (gain != 32)
hx711_data->gain_chan_a = gain;
ret = hx711_read(hx711_data); if (ret < 0) {
mutex_unlock(&hx711_data->lock); return ret;
}
}
static ssize_t hx711_scale_available_show(struct device *dev, struct device_attribute *attr, char *buf)
{ struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr); int channel = iio_attr->address; int i, len = 0;
for (i = 0; i < HX711_GAIN_MAX; i++) if (hx711_gain_to_scale[i].channel == channel)
len += sprintf(buf + len, "0.%09d ",
hx711_gain_to_scale[i].scale);
/* * PD_SCK stands for power down and serial clock input of HX711 * in the driver it is an output
*/
hx711_data->gpiod_pd_sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); if (IS_ERR(hx711_data->gpiod_pd_sck)) return dev_err_probe(dev, PTR_ERR(hx711_data->gpiod_pd_sck), "failed to get sck-gpiod\n");
/* * DOUT stands for serial data output of HX711 * for the driver it is an input
*/
hx711_data->gpiod_dout = devm_gpiod_get(dev, "dout", GPIOD_IN); if (IS_ERR(hx711_data->gpiod_dout)) return dev_err_probe(dev, PTR_ERR(hx711_data->gpiod_dout), "failed to get dout-gpiod\n");
ret = devm_regulator_get_enable_read_voltage(dev, "avdd"); if (ret < 0) return ret;
/* * with * full scale differential input range: AVDD / GAIN * full scale output data: 2^24 * we can say: * AVDD / GAIN = 2^24 * therefore: * 1 LSB = AVDD / GAIN / 2^24 * AVDD is in uV, but we need 10^-9 mV * approximately to fit into a 32 bit number: * 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV]
*/
/* we need 10^-9 mV */
ret *= 100;
for (i = 0; i < HX711_GAIN_MAX; i++)
hx711_gain_to_scale[i].scale =
ret / hx711_gain_to_scale[i].gain / 1678;
hx711_data->clock_frequency = 400000;
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
&hx711_data->clock_frequency);
/* * datasheet says the high level of PD_SCK has a maximum duration * of 50 microseconds
*/ if (hx711_data->clock_frequency < 20000) {
dev_warn(dev, "clock-frequency too low - assuming 400 kHz\n");
hx711_data->clock_frequency = 400000;
}
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.