// TEENSYDUINO has a port of Dean Camera's ATOMIC_BLOCK macros for AVR to ARM Cortex M3. #define HAS_ATOMIC_BLOCK (defined(ARDUINO_ARCH_AVR) || defined(TEENSYDUINO))
// Whether we are running on either the ESP8266 or the ESP32. #define ARCH_ESPRESSIF (defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32))
// Whether we are actually running on FreeRTOS. #define IS_FREE_RTOS defined(ARDUINO_ARCH_ESP32)
// Define macro designating whether we're running on a reasonable // fast CPU and so should slow down sampling from GPIO. #define FAST_CPU \ ( \ ARCH_ESPRESSIF || \ defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) || \ defined(ARDUINO_ARCH_STM32) || defined(TEENSYDUINO) \ )
voidHX711::set_gain(byte gain) { switch (gain) { case128: // channel A, gain factor 128 GAIN = 1; break; case64: // channel A, gain factor 64 GAIN = 3; break; case32: // channel B, gain factor 32 GAIN = 2; break; }
}
longHX711::read() {
// Wait for the chip to become ready. wait_ready();
// Define structures for reading data into. unsignedlong value = 0; uint8_t data[3] = { 0 }; uint8_t filler = 0x00;
// Protect the read sequence from system interrupts. If an interrupt occurs during // the time the PD_SCK signal is high it will stretch the length of the clock pulse. // If the total pulse time exceeds 60 uSec this will cause the HX711 to enter // power down mode during the middle of the read sequence. While the device will // wake up when PD_SCK goes low again, the reset starts a new conversion cycle which // forces DOUT high until that cycle is completed. // // The result is that all subsequent bits read by shiftIn() will read back as 1, // corrupting the value returned by read(). The ATOMIC_BLOCK macro disables // interrupts during the sequence and then restores the interrupt mask to its previous // state after the sequence completes, insuring that the entire read-and-gain-set // sequence is not interrupted. The macro has a few minor advantages over bracketing // the sequence between `noInterrupts()` and `interrupts()` calls. #if HAS_ATOMIC_BLOCK ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
#elif IS_FREE_RTOS // Begin of critical section. // Critical sections are used as a valid protection method // against simultaneous access in vanilla FreeRTOS. // Disable the scheduler and call portDISABLE_INTERRUPTS. This prevents // context switches and servicing of ISRs during a critical section. portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&mux);
// Pulse the clock pin 24 times to read the data. data[2] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST); data[1] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST); data[0] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
// Set the channel and the gain factor for the next reading using the clock pin. for (unsignedint i = 0; i < GAIN; i++) { digitalWrite(PD_SCK, HIGH); #if ARCH_ESPRESSIF delayMicroseconds(1); #endif digitalWrite(PD_SCK, LOW); #if ARCH_ESPRESSIF delayMicroseconds(1); #endif }
#if IS_FREE_RTOS // End of critical section. portEXIT_CRITICAL(&mux);
// Replicate the most significant bit to pad out a 32-bit signed integer if (data[2] & 0x80) { filler = 0xFF; } else { filler = 0x00; }
// Construct a 32-bit signed integer value = ( static_cast<unsignedlong>(filler) << 24 | static_cast<unsignedlong>(data[2]) << 16 | static_cast<unsignedlong>(data[1]) << 8 | static_cast<unsignedlong>(data[0]) );
return static_cast<long>(value); }
voidHX711::wait_ready(unsignedlong delay_ms) { // Wait for the chip to become ready. // This is a blocking implementation and will // halt the sketch until a load cell is connected. while (!is_ready()) { // Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP. // https://github.com/bogde/HX711/issues/73 delay(delay_ms); } }
boolHX711::wait_ready_retry(int retries, unsignedlong delay_ms) { // Wait for the chip to become ready by // retrying for a specified amount of attempts. // https://github.com/bogde/HX711/issues/76 int count = 0; while (count < retries) { if (is_ready()) { returntrue; } delay(delay_ms); count++; } returnfalse; }
boolHX711::wait_ready_timeout(unsignedlong timeout, unsignedlong delay_ms) { // Wait for the chip to become ready until timeout. // https://github.com/bogde/HX711/pull/96 unsignedlong millisStarted = millis(); while (millis() - millisStarted < timeout) { if (is_ready()) { returntrue; } delay(delay_ms); } returnfalse; }
longHX711::read_average(byte times) { long sum = 0; for (byte i = 0; i < times; i++) { sum += read(); // Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP. // https://github.com/bogde/HX711/issues/73 delay(0); } return sum / times; }
classHX711 { private: byte PD_SCK; // Power Down and Serial Clock Input Pin byte DOUT; // Serial Data Output Pin byte GAIN; // amplification factor long OFFSET = 0; // used for tare weight float SCALE = 1; // used to return weight in grams, kg, ounces, whatever
public:
HX711();
virtual ~HX711();
// Initialize library with data output pin, clock input pin and gain factor. // Channel selection is made by passing the appropriate gain: // - With a gain factor of 64 or 128, channel A is selected // - With a gain factor of 32, channel B is selected // The library default is "128" (Channel A). voidbegin(byte dout, byte pd_sck, byte gain = 128);
// Check if HX711 is ready // from the datasheet: When output data is not ready for retrieval, 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. boolis_ready();
// Wait for the HX711 to become ready voidwait_ready(unsignedlong delay_ms = 0); boolwait_ready_retry(int retries = 3, unsignedlong delay_ms = 0); boolwait_ready_timeout(unsignedlong timeout = 1000, unsignedlong delay_ms = 0);
// set the gain factor; takes effect only after a call to read() // channel A can be set for a 128 or 64 gain; channel B has a fixed 32 gain // depending on the parameter, the channel is also set to either A or B voidset_gain(byte gain = 128);
// waits for the chip to be ready and returns a reading longread();
// returns an average reading; times = how many times to read longread_average(byte times = 10);
// returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to do doubleget_value(byte times = 1);
// returns get_value() divided by SCALE, that is the raw value divided by a value obtained via calibration // times = how many readings to do floatget_units(byte times = 1);
// set the OFFSET value for tare weight; times = how many times to read the tare value voidtare(byte times = 10);
// set the SCALE value; this value is used to convert the raw data to "human readable" data (measure units) voidset_scale(float scale = 1.f);
// get the current SCALE floatget_scale();
// set OFFSET, the value that's subtracted from the actual reading (tare weight) voidset_offset(long offset = 0);
// get the current OFFSET longget_offset();
// puts the chip into power down mode voidpower_down();
// wakes up the chip after power down mode voidpower_up(); };
Please contact me if you have any questions. We are using the CDN service by Cloudflare, without nodes in Chinese mainland. As for the people in Chinese mainland should solve the problem, like the terrible loading speed, by themselves.