GY-63_MS5611/libraries/HX711/HX711.cpp

350 lines
6.5 KiB
C++
Raw Normal View History

2021-01-29 06:31:58 -05:00
//
// FILE: HX711.cpp
// AUTHOR: Rob Tillaart
2022-11-06 14:24:21 -05:00
// VERSION: 0.3.4
2022-06-02 08:32:49 -04:00
// PURPOSE: Library for load cells for UNO
2021-01-29 06:31:58 -05:00
// URL: https://github.com/RobTillaart/HX711
//
2022-11-06 14:24:21 -05:00
// HISTORY: see CHANGELOG.md
2021-05-26 09:54:34 -04:00
2021-01-29 06:31:58 -05:00
#include "HX711.h"
2021-05-26 09:54:34 -04:00
2021-01-29 06:31:58 -05:00
HX711::HX711()
{
reset();
}
2021-05-26 09:54:34 -04:00
2021-01-29 06:31:58 -05:00
HX711::~HX711() {}
2021-05-16 13:08:20 -04:00
2021-01-29 06:31:58 -05:00
void HX711::begin(uint8_t dataPin, uint8_t clockPin)
{
2021-11-16 11:42:29 -05:00
_dataPin = dataPin;
2021-01-29 06:31:58 -05:00
_clockPin = clockPin;
pinMode(_dataPin, INPUT);
pinMode(_clockPin, OUTPUT);
digitalWrite(_clockPin, LOW);
reset();
}
2021-05-16 13:08:20 -04:00
2021-01-29 06:31:58 -05:00
void HX711::reset()
{
2022-11-06 14:24:21 -05:00
power_down();
power_up();
2021-05-16 13:08:20 -04:00
_offset = 0;
_scale = 1;
2022-11-06 14:24:21 -05:00
_gain = HX711_CHANNEL_A_GAIN_128;
2021-05-16 13:08:20 -04:00
_lastRead = 0;
_mode = HX711_AVERAGE_MODE;
2021-01-29 06:31:58 -05:00
}
2021-05-16 13:08:20 -04:00
2021-01-29 06:31:58 -05:00
bool HX711::is_ready()
{
return digitalRead(_dataPin) == LOW;
}
2021-05-16 13:08:20 -04:00
2022-06-02 08:32:49 -04:00
// From datasheet page 4
2021-11-16 11:42:29 -05:00
// When output data is not ready for retrieval,
2022-06-02 08:32:49 -04:00
// digital output pin DOUT is HIGH.
// Serial clock input PD_SCK should be LOW.
// When DOUT goes to LOW, it indicates data is ready for retrieval.
float HX711::read()
2021-01-29 06:31:58 -05:00
{
// this BLOCKING wait takes most time...
2021-01-29 06:31:58 -05:00
while (digitalRead(_dataPin) == HIGH) yield();
2021-01-29 06:31:58 -05:00
union
{
long value = 0;
uint8_t data[4];
} v;
// blocking part ...
2021-01-29 06:31:58 -05:00
noInterrupts();
// Pulse the clock pin 24 times to read the data.
// v.data[2] = shiftIn(_dataPin, _clockPin, MSBFIRST);
// v.data[1] = shiftIn(_dataPin, _clockPin, MSBFIRST);
// v.data[0] = shiftIn(_dataPin, _clockPin, MSBFIRST);
2021-11-16 11:42:29 -05:00
v.data[2] = _shiftIn();
v.data[1] = _shiftIn();
v.data[0] = _shiftIn();
2021-01-29 06:31:58 -05:00
// TABLE 3 page 4 datasheet
2022-11-06 14:24:21 -05:00
//
// CLOCK CHANNEL GAIN m
// ------------------------------------
// 25 A 128 1 // default
// 26 B 32 2
// 27 A 64 3
//
// only default 128 verified,
// selection goes through the set_gain(gain)
//
uint8_t m = 1;
if (_gain == HX711_CHANNEL_A_GAIN_128) m = 1;
else if (_gain == HX711_CHANNEL_A_GAIN_64) m = 3;
else if (_gain == HX711_CHANNEL_B_GAIN_32) m = 2;
2021-01-29 06:31:58 -05:00
while (m > 0)
{
2022-11-06 14:24:21 -05:00
// delayMicroSeconds(1) needed for fast processors?
2021-01-29 06:31:58 -05:00
digitalWrite(_clockPin, HIGH);
digitalWrite(_clockPin, LOW);
m--;
}
interrupts();
// yield();
2021-01-29 06:31:58 -05:00
// SIGN extend
2021-01-29 06:31:58 -05:00
if (v.data[2] & 0x80) v.data[3] = 0xFF;
_lastRead = millis();
return 1.0 * v.value;
}
2021-05-16 13:08:20 -04:00
2022-11-06 14:24:21 -05:00
// note: if parameter gain == 0xFF40 some compilers
// will map that to 0x40 == HX711_CHANNEL_A_GAIN_64;
// solution: use uint32_t or larger parameters everywhere.
// note that changing gain/channel may take up to 400 ms (page 3)
bool HX711::set_gain(uint8_t gain, bool forced)
{
if ( (not forced) && (_gain == gain)) return true;
switch(gain)
{
case HX711_CHANNEL_B_GAIN_32:
case HX711_CHANNEL_A_GAIN_64:
case HX711_CHANNEL_A_GAIN_128:
_gain = gain;
read(); // next user read() is from right channel / gain
return true;
}
return false; // unchanged, but incorrect value.
}
uint8_t HX711::get_gain()
{
return _gain;
}
2022-06-02 08:32:49 -04:00
// assumes tare() has been set.
2021-05-16 13:08:20 -04:00
void HX711::calibrate_scale(uint16_t weight, uint8_t times)
2021-01-29 06:31:58 -05:00
{
_scale = (1.0 * weight) / (read_average(times) - _offset);
}
2022-06-02 08:32:49 -04:00
// OBSOLETE 0.4.0 (LL is wrong)
2021-05-16 13:08:20 -04:00
void HX711::callibrate_scale(uint16_t weight, uint8_t times)
{
calibrate_scale(weight, times);
2021-05-16 13:08:20 -04:00
};
void HX711::wait_ready(uint32_t ms)
2021-01-29 06:31:58 -05:00
{
while (!is_ready())
{
delay(ms);
}
}
2021-05-16 13:08:20 -04:00
bool HX711::wait_ready_retry(uint8_t retries, uint32_t ms)
2021-01-29 06:31:58 -05:00
{
while (retries--)
{
if (is_ready()) return true;
delay(ms);
}
return false;
}
2021-01-29 06:31:58 -05:00
bool HX711::wait_ready_timeout(uint32_t timeout, uint32_t ms)
{
uint32_t start = millis();
while (millis() - start < timeout)
2021-01-29 06:31:58 -05:00
{
if (is_ready()) return true;
delay(ms);
}
return false;
}
2021-05-16 13:08:20 -04:00
float HX711::read_average(uint8_t times)
2021-01-29 06:31:58 -05:00
{
2021-05-16 13:08:20 -04:00
if (times < 1) times = 1;
2021-01-29 06:31:58 -05:00
float sum = 0;
for (uint8_t i = 0; i < times; i++)
2021-01-29 06:31:58 -05:00
{
sum += read();
yield();
}
return sum / times;
}
2021-05-16 13:08:20 -04:00
float HX711::read_median(uint8_t times)
2021-05-16 13:08:20 -04:00
{
if (times > 15) times = 15;
if (times < 3) times = 3;
2022-06-02 08:32:49 -04:00
float samples[15];
for (uint8_t i = 0; i < times; i++)
2021-05-16 13:08:20 -04:00
{
2022-06-02 08:32:49 -04:00
samples[i] = read();
2021-05-16 13:08:20 -04:00
yield();
}
2022-06-02 08:32:49 -04:00
_insertSort(samples, times);
if (times & 0x01) return samples[times/2];
return (samples[times/2] + samples[times/2 + 1]) / 2;
2021-05-16 13:08:20 -04:00
}
float HX711::read_medavg(uint8_t times)
2021-05-16 13:08:20 -04:00
{
if (times > 15) times = 15;
if (times < 3) times = 3;
2022-06-02 08:32:49 -04:00
float samples[15];
for (uint8_t i = 0; i < times; i++)
2021-05-16 13:08:20 -04:00
{
2022-06-02 08:32:49 -04:00
samples[i] = read();
2021-05-16 13:08:20 -04:00
yield();
}
2022-06-02 08:32:49 -04:00
_insertSort(samples, times);
2021-05-16 13:08:20 -04:00
float sum = 0;
// iterate over 1/4 to 3/4 of the array
2022-06-02 08:32:49 -04:00
uint8_t count = 0;
2021-05-16 13:08:20 -04:00
uint8_t first = (times + 2) / 4;
uint8_t last = times - first - 1;
2022-06-02 08:32:49 -04:00
for (uint8_t i = first; i <= last; i++) // !! include last one too
2021-05-16 13:08:20 -04:00
{
2022-06-02 08:32:49 -04:00
sum += samples[i];
count++;
2021-05-16 13:08:20 -04:00
}
2022-06-02 08:32:49 -04:00
return sum / count;
2021-05-16 13:08:20 -04:00
}
float HX711::read_runavg(uint8_t times, float alpha)
2021-05-26 09:54:34 -04:00
{
if (times < 1) times = 1;
if (alpha < 0) alpha = 0;
if (alpha > 1) alpha = 1;
float val = read();
for (uint8_t i = 1; i < times; i++)
2021-05-26 09:54:34 -04:00
{
val += alpha * (read() - val);
yield();
}
return val;
}
2021-05-16 13:08:20 -04:00
void HX711::_insertSort(float * array, uint8_t size)
{
uint8_t t, z;
float temp;
for (t = 1; t < size; t++)
2021-05-16 13:08:20 -04:00
{
z = t;
temp = array[z];
while( (z > 0) && (temp < array[z - 1] ))
2021-05-16 13:08:20 -04:00
{
array[z] = array[z - 1];
z--;
}
array[z] = temp;
yield();
}
}
float HX711::get_value(uint8_t times)
2021-05-16 13:08:20 -04:00
{
float raw;
switch(_mode)
{
2022-06-02 08:32:49 -04:00
case HX711_RAW_MODE:
raw = read();
break;
2021-05-26 09:54:34 -04:00
case HX711_RUNAVG_MODE:
raw = read_runavg(times);
break;
2021-05-16 13:08:20 -04:00
case HX711_MEDAVG_MODE:
raw = read_medavg(times);
break;
case HX711_MEDIAN_MODE:
raw = read_median(times);
break;
case HX711_AVERAGE_MODE:
default:
raw = read_average(times);
break;
}
return raw - _offset;
};
2021-01-29 06:31:58 -05:00
float HX711::get_units(uint8_t times)
{
float units = get_value(times) * _scale;
return units;
};
2021-05-16 13:08:20 -04:00
void HX711::power_down()
2021-01-29 06:31:58 -05:00
{
2022-11-06 14:24:21 -05:00
// at least 60 us HIGH
2021-01-29 06:31:58 -05:00
digitalWrite(_clockPin, HIGH);
2022-11-06 14:24:21 -05:00
delayMicroseconds(64);
2021-01-29 06:31:58 -05:00
}
2021-05-16 13:08:20 -04:00
void HX711::power_up()
2021-01-29 06:31:58 -05:00
{
digitalWrite(_clockPin, LOW);
}
2021-11-16 11:42:29 -05:00
// MSB_FIRST optimized shiftIn
// see datasheet page 5 for timing
uint8_t HX711::_shiftIn()
{
2022-06-02 08:32:49 -04:00
// local variables are faster.
2022-03-16 07:11:42 -04:00
uint8_t clk = _clockPin;
uint8_t data = _dataPin;
2021-11-16 11:42:29 -05:00
uint8_t value = 0;
2022-03-16 07:11:42 -04:00
uint8_t mask = 0x80;
while (mask > 0)
2021-11-16 11:42:29 -05:00
{
2022-03-16 07:11:42 -04:00
digitalWrite(clk, HIGH);
2022-06-02 08:32:49 -04:00
delayMicroseconds(1); // T2 >= 0.2 us
2022-03-16 07:11:42 -04:00
if (digitalRead(data) == HIGH)
2021-11-16 11:42:29 -05:00
{
value |= mask;
}
2022-03-16 07:11:42 -04:00
digitalWrite(clk, LOW);
2022-06-02 08:32:49 -04:00
delayMicroseconds(1); // keep duty cycle ~50%
2021-11-16 11:42:29 -05:00
mask >>= 1;
}
return value;
}
2021-01-29 06:31:58 -05:00
// -- END OF FILE --
2022-03-16 07:11:42 -04:00