From 31e57cd99bcd8a32b97cee2777435b7204a46a34 Mon Sep 17 00:00:00 2001 From: banoz Date: Sun, 23 Jan 2022 22:46:17 -0600 Subject: [PATCH 01/10] Tare issue --- src/HX711.cpp | 20 +++++++++++++------- src/HX711.h | 4 ++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/HX711.cpp b/src/HX711.cpp index 9e3b4f4..985d941 100644 --- a/src/HX711.cpp +++ b/src/HX711.cpp @@ -104,10 +104,12 @@ void HX711::set_gain(byte gain) { } -long HX711::read() { +long HX711::read(unsigned long timeout) { // Wait for the chip to become ready. - wait_ready(); + if (!wait_ready_timeout(timeout)) { + return 0; + } // Define structures for reading data into. unsigned long value = 0; @@ -152,11 +154,11 @@ long HX711::read() { // Set the channel and the gain factor for the next reading using the clock pin. for (unsigned int i = 0; i < GAIN; i++) { digitalWrite(PD_SCK, HIGH); - #if ARCH_ESPRESSIF + #if FAST_CPU delayMicroseconds(1); #endif digitalWrite(PD_SCK, LOW); - #if ARCH_ESPRESSIF + #if FAST_CPU delayMicroseconds(1); #endif } @@ -218,8 +220,8 @@ bool HX711::wait_ready_retry(int retries, unsigned long delay_ms) { bool HX711::wait_ready_timeout(unsigned long timeout, unsigned long delay_ms) { // Wait for the chip to become ready until timeout. // https://github.com/bogde/HX711/pull/96 - unsigned long millisStarted = millis(); - while (millis() - millisStarted < timeout) { + unsigned long stopAt = millis() + timeout; + while (millis() < stopAt) { if (is_ready()) { return true; } @@ -244,10 +246,11 @@ double HX711::get_value(byte times) { } float HX711::get_units(byte times) { - return get_value(times) / SCALE; + return get_value(times) / (SCALE == 0 ? 1 : SCALE); } void HX711::tare(byte times) { + set_offset(0); double sum = read_average(times); set_offset(sum); } @@ -270,6 +273,9 @@ long HX711::get_offset() { void HX711::power_down() { digitalWrite(PD_SCK, LOW); +#if FAST_CPU + delayMicroseconds(1); +#endif digitalWrite(PD_SCK, HIGH); } diff --git a/src/HX711.h b/src/HX711.h index 9814891..91d9b5d 100644 --- a/src/HX711.h +++ b/src/HX711.h @@ -23,7 +23,7 @@ class HX711 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 + float SCALE = 1.f; // used to return weight in grams, kg, ounces, whatever public: @@ -54,7 +54,7 @@ class HX711 void set_gain(byte gain = 128); // waits for the chip to be ready and returns a reading - long read(); + long read(unsigned long timeout = 1000); // returns an average reading; times = how many times to read long read_average(byte times = 10); From cda8dbc4c5c362ef96e7b712a48c5c93f40a46b0 Mon Sep 17 00:00:00 2001 From: banoz Date: Tue, 8 Feb 2022 00:14:40 -0600 Subject: [PATCH 02/10] Read data on LOW CLK --- src/HX711.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HX711.cpp b/src/HX711.cpp index 985d941..ff1c41f 100644 --- a/src/HX711.cpp +++ b/src/HX711.cpp @@ -47,11 +47,11 @@ uint8_t shiftInSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { for(i = 0; i < 8; ++i) { digitalWrite(clockPin, HIGH); delayMicroseconds(1); + digitalWrite(clockPin, LOW); if(bitOrder == LSBFIRST) value |= digitalRead(dataPin) << i; else value |= digitalRead(dataPin) << (7 - i); - digitalWrite(clockPin, LOW); delayMicroseconds(1); } return value; From 22d75ae3171607c92752c4f7a54285525910f498 Mon Sep 17 00:00:00 2001 From: banoz Date: Tue, 8 Feb 2022 13:56:12 -0600 Subject: [PATCH 03/10] get_value return type fix --- src/HX711.cpp | 2 +- src/HX711.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HX711.cpp b/src/HX711.cpp index ff1c41f..93b0971 100644 --- a/src/HX711.cpp +++ b/src/HX711.cpp @@ -241,7 +241,7 @@ long HX711::read_average(byte times) { return sum / times; } -double HX711::get_value(byte times) { +long HX711::get_value(byte times) { return read_average(times) - OFFSET; } diff --git a/src/HX711.h b/src/HX711.h index 91d9b5d..b5739e1 100644 --- a/src/HX711.h +++ b/src/HX711.h @@ -60,7 +60,7 @@ class HX711 long read_average(byte times = 10); // returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to do - double get_value(byte times = 1); + long get_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 From 0eeb209b87b62dad07e98b89974b6f19aa37710d Mon Sep 17 00:00:00 2001 From: banoz Date: Tue, 8 Feb 2022 17:43:11 -0600 Subject: [PATCH 04/10] Support for dual HX711 board with common SCK --- src/HX711_2.cpp | 316 ++++++++++++++++++++++++++++++++++++++++++++++++ src/HX711_2.h | 94 ++++++++++++++ 2 files changed, 410 insertions(+) create mode 100644 src/HX711_2.cpp create mode 100644 src/HX711_2.h diff --git a/src/HX711_2.cpp b/src/HX711_2.cpp new file mode 100644 index 0000000..2d0ee27 --- /dev/null +++ b/src/HX711_2.cpp @@ -0,0 +1,316 @@ +/** + * + * HX711 library for Arduino + * https://github.com/bogde/HX711 + * + * MIT License + * (c) 2018 Bogdan Necula + * +**/ +#include +#include "HX711_2.h" + +// 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) \ + ) + +#if HAS_ATOMIC_BLOCK +// Acquire AVR-specific ATOMIC_BLOCK(ATOMIC_RESTORESTATE) macro. +#include +#endif + +uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_t bitOrder) { + uint8_t value = 0; + uint8_t value2 = 0; + uint8_t i; + + for(i = 0; i < 8; ++i) { + digitalWrite(clockPin, HIGH); + delayMicroseconds(1); + digitalWrite(clockPin, LOW); + delayMicroseconds(1); + if(bitOrder == LSBFIRST) { + value |= digitalRead(dataPin) << i; + value2 |= digitalRead(dataPin2) << i; + } else { + value |= digitalRead(dataPin) << (7 - i); + value2 |= digitalRead(dataPin2) << (7 - i); + } + } + + return value2 << 8 | value; +} + + +#ifdef ARCH_ESPRESSIF +// ESP8266 doesn't read values between 0x20000 and 0x30000 when DOUT is pulled up. +#define DOUT_MODE INPUT +#else +#define DOUT_MODE INPUT_PULLUP +#endif + + +HX711_2::HX711_2() { +} + +HX711_2::~HX711_2() { +} + +void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte gain) { + PD_SCK = pd_sck; + DOUT = dout; + DOUT2 = dout2; + + pinMode(PD_SCK, OUTPUT); + pinMode(DOUT, DOUT_MODE); + pinMode(DOUT2, DOUT_MODE); + + set_gain(gain); +} + +bool HX711_2::is_ready() { + if (digitalRead(DOUT2) == HIGH) { + return false; + } + + return digitalRead(DOUT) == LOW; +} + +void HX711_2::set_gain(byte gain) { + switch (gain) { + case 128: // channel A, gain factor 128 + GAIN = 1; + break; + case 64: // channel A, gain factor 64 + GAIN = 3; + break; + case 32: // channel B, gain factor 32 + GAIN = 2; + break; + } + +} + +void HX711_2::read(long* readValues, unsigned long timeout) { + + // Wait for the chip to become ready. + if (!wait_ready_timeout(timeout)) { + return; + } + + // Define structures for reading data into. + unsigned long value = 0; + uint8_t data[6] = { 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); + + #else + // Disable interrupts. + noInterrupts(); + #endif + + // Pulse the clock pin 24 times to read the data. + uint16_t readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, MSBFIRST); + data[2] = readBits & 0xFF; + data[5] = readBits >> 8; + readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, MSBFIRST); + data[1] = readBits & 0xFF; + data[4] = readBits >> 8; + readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, MSBFIRST); + data[0] = readBits & 0xFF; + data[3] = readBits >> 8; + + // Set the channel and the gain factor for the next reading using the clock pin. + for (unsigned int i = 0; i < GAIN; i++) { + digitalWrite(PD_SCK, HIGH); + #if FAST_CPU + delayMicroseconds(1); + #endif + digitalWrite(PD_SCK, LOW); + #if FAST_CPU + delayMicroseconds(1); + #endif + } + + #if IS_FREE_RTOS + // End of critical section. + portEXIT_CRITICAL(&mux); + + #elif HAS_ATOMIC_BLOCK + } + + #else + // Enable interrupts again. + interrupts(); + #endif + + // 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(filler) << 24 + | static_cast(data[2]) << 16 + | static_cast(data[1]) << 8 + | static_cast(data[0]) ); + + readValues[0] = static_cast(value) - OFFSET; + + if (data[5] & 0x80) { + filler = 0xFF; + } else { + filler = 0x00; + } + + // Construct a 32-bit signed integer + value = ( static_cast(filler) << 24 + | static_cast(data[5]) << 16 + | static_cast(data[4]) << 8 + | static_cast(data[3]) ); + + readValues[1] = static_cast(value) - OFFSET2; + +} + +void HX711_2::wait_ready(unsigned long 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); + } +} + +bool HX711_2::wait_ready_retry(int retries, unsigned long 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()) { + return true; + } + delay(delay_ms); + count++; + } + return false; +} + +bool HX711_2::wait_ready_timeout(unsigned long timeout, unsigned long delay_ms) { + // Wait for the chip to become ready until timeout. + // https://github.com/bogde/HX711/pull/96 + unsigned long stopAt = millis() + timeout; + while (millis() < stopAt) { + if (is_ready()) { + return true; + } + delay(delay_ms); + } + return false; +} + +void HX711_2::read_average(long* readValues, byte times) { + long sum[2] = { 0 }; + for (byte i = 0; i < times; ++i) { + long values[2]; + read(values); + sum[0] += values[0]; + sum[1] += values[1]; + } + readValues[0] = sum[0] / times; + readValues[1] = sum[1] / times; +} + +void HX711_2::get_value(long* readValues, byte times) { + read_average(readValues, times); +} + +void HX711_2::get_units(float* readValues, byte times) { + long values[2]; + read_average(values, times); + + readValues[0] = values[0] / (SCALE == 0 ? 1 : SCALE); + readValues[1] = values[1] / (SCALE2 == 0 ? 1 : SCALE2); +} + +void HX711_2::tare(byte times) { + long readValues[2]; + set_offset(0, 0); + read_average(readValues, times); + set_offset(readValues[0], readValues[1]); +} + +void HX711_2::set_scale(float scale, float scale2) { + SCALE = scale; + SCALE2 = scale2; +} + +void HX711_2::get_scale(float* scaleValues) { + scaleValues[0] = SCALE; + scaleValues[1] = SCALE2; +} + +void HX711_2::set_offset(long offset, long offset2) { + OFFSET = offset; + OFFSET2 = offset2; +} + +void HX711_2::get_offset(long* offsetValues) { + offsetValues[0] = OFFSET; + offsetValues[1] = OFFSET2; +} + +void HX711_2::power_down() { + digitalWrite(PD_SCK, LOW); +#if FAST_CPU + delayMicroseconds(1); +#endif + digitalWrite(PD_SCK, HIGH); +} + +void HX711_2::power_up() { + digitalWrite(PD_SCK, LOW); +} diff --git a/src/HX711_2.h b/src/HX711_2.h new file mode 100644 index 0000000..e2d69c2 --- /dev/null +++ b/src/HX711_2.h @@ -0,0 +1,94 @@ +/** + * + * HX711 library for Arduino + * https://github.com/bogde/HX711 + * + * MIT License + * (c) 2018 Bogdan Necula + * +**/ +#ifndef HX711_2_h +#define HX711_2_h + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +class HX711_2 +{ + private: + byte PD_SCK; // Power Down and Serial Clock Input Pin + byte DOUT; // Serial Data Output Pin + byte DOUT2; // Serial Data Output Pin + byte GAIN; // amplification factor + long OFFSET = 0; // used for tare weight + long OFFSET2 = 0; // used for tare weight + float SCALE = 1.f; // used to return weight in grams, kg, ounces, whatever + float SCALE2 = 1.f; // used to return weight in grams, kg, ounces, whatever + + public: + + HX711_2(); + + virtual ~HX711_2(); + + // 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). + void begin(byte dout, byte dout2, 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. + bool is_ready(); + + // Wait for the HX711 to become ready + void wait_ready(unsigned long delay_ms = 0); + bool wait_ready_retry(int retries = 3, unsigned long delay_ms = 0); + bool wait_ready_timeout(unsigned long timeout = 1000, unsigned long 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 + void set_gain(byte gain = 128); + + // waits for the chip to be ready and returns a reading + void read(long* readValues, unsigned long timeout = 1000); + + // returns an average reading; times = how many times to read + void read_average(long* readValues, byte times = 10); + + // returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to do + void get_value(long* readValues, 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 + void get_units(float* readValues, byte times = 1); + + // set the OFFSET value for tare weight; times = how many times to read the tare value + void tare(byte times = 10); + + // set the SCALE value; this value is used to convert the raw data to "human readable" data (measure units) + void set_scale(float scale = 1.f, float scale2 = 1.f); + + // get the current SCALE + void get_scale(float* scaleValues); + + // set OFFSET, the value that's subtracted from the actual reading (tare weight) + void set_offset(long offset = 0, long offset2 = 0); + + // get the current OFFSET + void get_offset(long* offsetValues); + + // puts the chip into power down mode + void power_down(); + + // wakes up the chip after power down mode + void power_up(); +}; + +#endif /* HX711_2_h */ From b596045d85f2e8eeebd9832d12367ec70db0f033 Mon Sep 17 00:00:00 2001 From: banoz Date: Tue, 8 Feb 2022 17:57:00 -0600 Subject: [PATCH 05/10] HX711_2 basic example --- .../HX711_2_basic_example.ino | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 examples/HX711_2_basic_example/HX711_2_basic_example.ino diff --git a/examples/HX711_2_basic_example/HX711_2_basic_example.ino b/examples/HX711_2_basic_example/HX711_2_basic_example.ino new file mode 100644 index 0000000..3a13636 --- /dev/null +++ b/examples/HX711_2_basic_example/HX711_2_basic_example.ino @@ -0,0 +1,35 @@ +#include "HX711_2.h" + +// HX711 circuit wiring +const int LOADCELL_SCK_PIN = 2; +const int LOADCELL_DOUT_PIN = 3; +const int LOADCELL_DOUT2_PIN = 4; + +HX711_2 scale; + +void setup() { + Serial.begin(57600); + scale.begin(LOADCELL_DOUT_PIN, LOADCELL_DOUT2_PIN, LOADCELL_SCK_PIN); +} + +void loop() { + + scale.power_up(); + + if (scale.is_ready()) { + long reading[2]; + + scale.read(reading); + + Serial.print("HX711 readings: "); + Serial.print(reading[0]); + Serial.print(" "); + Serial.println(reading[1]); + } else { + Serial.println("HX711 not found."); + } + + scale.power_down(); + + delay(1000); +} From ee52435022398d91b80510a03f2b8329acea54a9 Mon Sep 17 00:00:00 2001 From: lis0r <2305601+lis0r@users.noreply.github.com> Date: Sat, 30 Apr 2022 08:34:01 +0100 Subject: [PATCH 06/10] Allow HX711_2 to optionally drive two clocks, and thus two seperate boards. --- src/HX711_2.cpp | 45 +++++++++++++++++++++++++++++++-------------- src/HX711_2.h | 5 +++-- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/HX711_2.cpp b/src/HX711_2.cpp index 2d0ee27..a290fee 100644 --- a/src/HX711_2.cpp +++ b/src/HX711_2.cpp @@ -33,15 +33,19 @@ #include #endif -uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_t bitOrder) { +uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_t clockPin2, uint8_t bitOrder) { uint8_t value = 0; uint8_t value2 = 0; uint8_t i; - + for(i = 0; i < 8; ++i) { digitalWrite(clockPin, HIGH); + if (clockPin2 != 255) + digitalWrite(clockPin2, HIGH); delayMicroseconds(1); digitalWrite(clockPin, LOW); + if (clockPin2 != 255) + digitalWrite(clockPin2, LOW); delayMicroseconds(1); if(bitOrder == LSBFIRST) { value |= digitalRead(dataPin) << i; @@ -51,7 +55,7 @@ uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_ value2 |= digitalRead(dataPin2) << (7 - i); } } - + return value2 << 8 | value; } @@ -70,12 +74,15 @@ HX711_2::HX711_2() { HX711_2::~HX711_2() { } -void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte gain) { +void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2, byte gain) { PD_SCK = pd_sck; + PD_SCK2 = pd_sck2; DOUT = dout; DOUT2 = dout2; pinMode(PD_SCK, OUTPUT); + if (PD_SCK2 != 255) + pinMode(PD_SCK2, OUTPUT); pinMode(DOUT, DOUT_MODE); pinMode(DOUT2, DOUT_MODE); @@ -148,23 +155,27 @@ void HX711_2::read(long* readValues, unsigned long timeout) { #endif // Pulse the clock pin 24 times to read the data. - uint16_t readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, MSBFIRST); + uint16_t readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, PD_SCK2, MSBFIRST); data[2] = readBits & 0xFF; data[5] = readBits >> 8; - readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, MSBFIRST); + readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, PD_SCK2, MSBFIRST); data[1] = readBits & 0xFF; data[4] = readBits >> 8; - readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, MSBFIRST); + readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, PD_SCK2, MSBFIRST); data[0] = readBits & 0xFF; data[3] = readBits >> 8; // Set the channel and the gain factor for the next reading using the clock pin. for (unsigned int i = 0; i < GAIN; i++) { digitalWrite(PD_SCK, HIGH); + if (PD_SCK2 != 255) + digitalWrite(PD_SCK2, HIGH); #if FAST_CPU delayMicroseconds(1); #endif digitalWrite(PD_SCK, LOW); + if (PD_SCK2 != 255) + digitalWrite(PD_SCK2, LOW); #if FAST_CPU delayMicroseconds(1); #endif @@ -194,21 +205,21 @@ void HX711_2::read(long* readValues, unsigned long timeout) { | static_cast(data[2]) << 16 | static_cast(data[1]) << 8 | static_cast(data[0]) ); - + readValues[0] = static_cast(value) - OFFSET; - + if (data[5] & 0x80) { filler = 0xFF; } else { filler = 0x00; - } - + } + // Construct a 32-bit signed integer value = ( static_cast(filler) << 24 | static_cast(data[5]) << 16 | static_cast(data[4]) << 8 | static_cast(data[3]) ); - + readValues[1] = static_cast(value) - OFFSET2; } @@ -271,7 +282,7 @@ void HX711_2::get_value(long* readValues, byte times) { void HX711_2::get_units(float* readValues, byte times) { long values[2]; read_average(values, times); - + readValues[0] = values[0] / (SCALE == 0 ? 1 : SCALE); readValues[1] = values[1] / (SCALE2 == 0 ? 1 : SCALE2); } @@ -305,12 +316,18 @@ void HX711_2::get_offset(long* offsetValues) { void HX711_2::power_down() { digitalWrite(PD_SCK, LOW); + if (PD_SCK2 != 255) + digitalWrite(PD_SCK2, LOW); #if FAST_CPU delayMicroseconds(1); -#endif +#endif digitalWrite(PD_SCK, HIGH); + if (PD_SCK2 != 255) + digitalWrite(PD_SCK2, HIGH); } void HX711_2::power_up() { digitalWrite(PD_SCK, LOW); + if (PD_SCK2 != 255) + digitalWrite(PD_SCK2, LOW); } diff --git a/src/HX711_2.h b/src/HX711_2.h index e2d69c2..0572995 100644 --- a/src/HX711_2.h +++ b/src/HX711_2.h @@ -20,6 +20,7 @@ class HX711_2 { private: byte PD_SCK; // Power Down and Serial Clock Input Pin + byte PD_SCK2; // Power Down and Serial Clock Input Pin byte DOUT; // Serial Data Output Pin byte DOUT2; // Serial Data Output Pin byte GAIN; // amplification factor @@ -39,7 +40,7 @@ class HX711_2 // - 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). - void begin(byte dout, byte dout2, byte pd_sck, byte gain = 128); + void begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2 = 255, 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 @@ -66,7 +67,7 @@ class HX711_2 void get_value(long* readValues, 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 + // times = how many readings to do void get_units(float* readValues, byte times = 1); // set the OFFSET value for tare weight; times = how many times to read the tare value From bfb0b0f386603be945c2795d9881c6fedc375817 Mon Sep 17 00:00:00 2001 From: lis0r <2305601+lis0r@users.noreply.github.com> Date: Sat, 30 Apr 2022 08:34:01 +0100 Subject: [PATCH 07/10] Allow HX711_2 to optionally drive two clocks, and thus two seperate boards. --- src/HX711_2.cpp | 505 +++++++++++++++++++++++++----------------------- 1 file changed, 264 insertions(+), 241 deletions(-) diff --git a/src/HX711_2.cpp b/src/HX711_2.cpp index a290fee..7f90ebe 100644 --- a/src/HX711_2.cpp +++ b/src/HX711_2.cpp @@ -6,7 +6,7 @@ * MIT License * (c) 2018 Bogdan Necula * -**/ + **/ #include #include "HX711_2.h" @@ -21,45 +21,51 @@ // 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) \ - ) +#define FAST_CPU \ + ( \ + ARCH_ESPRESSIF || \ + defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) || \ + defined(ARDUINO_ARCH_STM32) || defined(TEENSYDUINO)) #if HAS_ATOMIC_BLOCK // Acquire AVR-specific ATOMIC_BLOCK(ATOMIC_RESTORESTATE) macro. #include #endif -uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_t clockPin2, uint8_t bitOrder) { - uint8_t value = 0; - uint8_t value2 = 0; - uint8_t i; - - for(i = 0; i < 8; ++i) { - digitalWrite(clockPin, HIGH); - if (clockPin2 != 255) - digitalWrite(clockPin2, HIGH); - delayMicroseconds(1); - digitalWrite(clockPin, LOW); - if (clockPin2 != 255) - digitalWrite(clockPin2, LOW); - delayMicroseconds(1); - if(bitOrder == LSBFIRST) { - value |= digitalRead(dataPin) << i; - value2 |= digitalRead(dataPin2) << i; - } else { - value |= digitalRead(dataPin) << (7 - i); - value2 |= digitalRead(dataPin2) << (7 - i); - } +static inline void doubleWrite(uint8_t pin1, uint8_t pin2, bool level) +{ + digitalWrite(pin1, level); + if (pin1 != 255) + digitalWrite(pin2, level); +} + +uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_t clockPin2, uint8_t bitOrder) +{ + uint8_t value = 0; + uint8_t value2 = 0; + uint8_t i; + + for (i = 0; i < 8; ++i) + { + doubleWrite(clockPin, clockPin2, HIGH); + delayMicroseconds(1); + doubleWrite(clockPin, clockPin2, LOW); + delayMicroseconds(1); + if (bitOrder == LSBFIRST) + { + value |= digitalRead(dataPin) << i; + value2 |= digitalRead(dataPin2) << i; } + else + { + value |= digitalRead(dataPin) << (7 - i); + value2 |= digitalRead(dataPin2) << (7 - i); + } + } - return value2 << 8 | value; + return value2 << 8 | value; } - #ifdef ARCH_ESPRESSIF // ESP8266 doesn't read values between 0x20000 and 0x30000 when DOUT is pulled up. #define DOUT_MODE INPUT @@ -67,95 +73,103 @@ uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_ #define DOUT_MODE INPUT_PULLUP #endif - -HX711_2::HX711_2() { +HX711_2::HX711_2() +{ } -HX711_2::~HX711_2() { +HX711_2::~HX711_2() +{ } -void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2, byte gain) { - PD_SCK = pd_sck; - PD_SCK2 = pd_sck2; - DOUT = dout; - DOUT2 = dout2; +void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2, byte gain) +{ + PD_SCK = pd_sck; + PD_SCK2 = pd_sck2; + DOUT = dout; + DOUT2 = dout2; - pinMode(PD_SCK, OUTPUT); - if (PD_SCK2 != 255) - pinMode(PD_SCK2, OUTPUT); - pinMode(DOUT, DOUT_MODE); - pinMode(DOUT2, DOUT_MODE); + pinMode(PD_SCK, OUTPUT); + if (PD_SCK2 != 255) + pinMode(PD_SCK2, OUTPUT); + pinMode(DOUT, DOUT_MODE); + pinMode(DOUT2, DOUT_MODE); - set_gain(gain); + set_gain(gain); } -bool HX711_2::is_ready() { - if (digitalRead(DOUT2) == HIGH) { - return false; - } +bool HX711_2::is_ready() +{ + if (digitalRead(DOUT2) == HIGH) + { + return false; + } - return digitalRead(DOUT) == LOW; + return digitalRead(DOUT) == LOW; } -void HX711_2::set_gain(byte gain) { - switch (gain) { - case 128: // channel A, gain factor 128 - GAIN = 1; - break; - case 64: // channel A, gain factor 64 - GAIN = 3; - break; - case 32: // channel B, gain factor 32 - GAIN = 2; - break; - } - +void HX711_2::set_gain(byte gain) +{ + switch (gain) + { + case 128: // channel A, gain factor 128 + GAIN = 1; + break; + case 64: // channel A, gain factor 64 + GAIN = 3; + break; + case 32: // channel B, gain factor 32 + GAIN = 2; + break; + } } -void HX711_2::read(long* readValues, unsigned long timeout) { +void HX711_2::read(long *readValues, unsigned long timeout) +{ + + // Wait for the chip to become ready. + if (!wait_ready_timeout(timeout)) + { + return; + } + + // Define structures for reading data into. + unsigned long value = 0; + uint8_t data[6] = {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); - // Wait for the chip to become ready. - if (!wait_ready_timeout(timeout)) { - return; - } +#else + // Disable interrupts. + noInterrupts(); +#endif - // Define structures for reading data into. - unsigned long value = 0; - uint8_t data[6] = { 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); - - #else - // Disable interrupts. - noInterrupts(); - #endif - - // Pulse the clock pin 24 times to read the data. - uint16_t readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, PD_SCK2, MSBFIRST); + // Pulse the clock pin 24 times to read the data. + uint16_t readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, PD_SCK2, MSBFIRST); data[2] = readBits & 0xFF; data[5] = readBits >> 8; readBits = shiftInSlow(DOUT, DOUT2, PD_SCK, PD_SCK2, MSBFIRST); @@ -165,169 +179,178 @@ void HX711_2::read(long* readValues, unsigned long timeout) { data[0] = readBits & 0xFF; data[3] = readBits >> 8; - // Set the channel and the gain factor for the next reading using the clock pin. - for (unsigned int i = 0; i < GAIN; i++) { - digitalWrite(PD_SCK, HIGH); - if (PD_SCK2 != 255) - digitalWrite(PD_SCK2, HIGH); - #if FAST_CPU - delayMicroseconds(1); - #endif - digitalWrite(PD_SCK, LOW); - if (PD_SCK2 != 255) - digitalWrite(PD_SCK2, LOW); - #if FAST_CPU - delayMicroseconds(1); - #endif - } - - #if IS_FREE_RTOS - // End of critical section. - portEXIT_CRITICAL(&mux); - - #elif HAS_ATOMIC_BLOCK - } - - #else - // Enable interrupts again. - interrupts(); - #endif - - // 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(filler) << 24 - | static_cast(data[2]) << 16 - | static_cast(data[1]) << 8 - | static_cast(data[0]) ); + // Set the channel and the gain factor for the next reading using the clock pin. + for (unsigned int i = 0; i < GAIN; i++) + { + doubleWrite(PD_SCK, PD_SCK2, HIGH); +#if FAST_CPU + delayMicroseconds(1); +#endif + doubleWrite(PD_SCK, PD_SCK2, LOW); +#if FAST_CPU + delayMicroseconds(1); +#endif + } - readValues[0] = static_cast(value) - OFFSET; +#if IS_FREE_RTOS + // End of critical section. + portEXIT_CRITICAL(&mux); - if (data[5] & 0x80) { - filler = 0xFF; - } else { - filler = 0x00; - } +#elif HAS_ATOMIC_BLOCK +} - // Construct a 32-bit signed integer - value = ( static_cast(filler) << 24 - | static_cast(data[5]) << 16 - | static_cast(data[4]) << 8 - | static_cast(data[3]) ); +#else + // Enable interrupts again. + interrupts(); +#endif - readValues[1] = static_cast(value) - OFFSET2; + // 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(filler) << 24 | static_cast(data[2]) << 16 | static_cast(data[1]) << 8 | static_cast(data[0])); -void HX711_2::wait_ready(unsigned long 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); - } -} + readValues[0] = static_cast(value) - OFFSET; -bool HX711_2::wait_ready_retry(int retries, unsigned long 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()) { - return true; - } - delay(delay_ms); - count++; - } - return false; -} + if (data[5] & 0x80) + { + filler = 0xFF; + } + else + { + filler = 0x00; + } -bool HX711_2::wait_ready_timeout(unsigned long timeout, unsigned long delay_ms) { - // Wait for the chip to become ready until timeout. - // https://github.com/bogde/HX711/pull/96 - unsigned long stopAt = millis() + timeout; - while (millis() < stopAt) { - if (is_ready()) { - return true; - } - delay(delay_ms); - } - return false; -} + // Construct a 32-bit signed integer + value = (static_cast(filler) << 24 | static_cast(data[5]) << 16 | static_cast(data[4]) << 8 | static_cast(data[3])); -void HX711_2::read_average(long* readValues, byte times) { - long sum[2] = { 0 }; - for (byte i = 0; i < times; ++i) { - long values[2]; - read(values); - sum[0] += values[0]; - sum[1] += values[1]; - } - readValues[0] = sum[0] / times; - readValues[1] = sum[1] / times; -} + readValues[1] = static_cast(value) - OFFSET2; + } + + void HX711_2::wait_ready(unsigned long 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); + } + } + + bool HX711_2::wait_ready_retry(int retries, unsigned long 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()) + { + return true; + } + delay(delay_ms); + count++; + } + return false; + } + + bool HX711_2::wait_ready_timeout(unsigned long timeout, unsigned long delay_ms) + { + // Wait for the chip to become ready until timeout. + // https://github.com/bogde/HX711/pull/96 + unsigned long stopAt = millis() + timeout; + while (millis() < stopAt) + { + if (is_ready()) + { + return true; + } + delay(delay_ms); + } + return false; + } + + void HX711_2::read_average(long *readValues, byte times) + { + long sum[2] = {0}; + for (byte i = 0; i < times; ++i) + { + long values[2]; + read(values); + sum[0] += values[0]; + sum[1] += values[1]; + } + readValues[0] = sum[0] / times; + readValues[1] = sum[1] / times; + } -void HX711_2::get_value(long* readValues, byte times) { - read_average(readValues, times); -} + void HX711_2::get_value(long *readValues, byte times) + { + read_average(readValues, times); + } -void HX711_2::get_units(float* readValues, byte times) { - long values[2]; + void HX711_2::get_units(float *readValues, byte times) + { + long values[2]; read_average(values, times); readValues[0] = values[0] / (SCALE == 0 ? 1 : SCALE); readValues[1] = values[1] / (SCALE2 == 0 ? 1 : SCALE2); -} + } -void HX711_2::tare(byte times) { - long readValues[2]; + void HX711_2::tare(byte times) + { + long readValues[2]; set_offset(0, 0); read_average(readValues, times); set_offset(readValues[0], readValues[1]); -} + } -void HX711_2::set_scale(float scale, float scale2) { - SCALE = scale; - SCALE2 = scale2; -} + void HX711_2::set_scale(float scale, float scale2) + { + SCALE = scale; + SCALE2 = scale2; + } -void HX711_2::get_scale(float* scaleValues) { - scaleValues[0] = SCALE; + void HX711_2::get_scale(float *scaleValues) + { + scaleValues[0] = SCALE; scaleValues[1] = SCALE2; -} + } -void HX711_2::set_offset(long offset, long offset2) { - OFFSET = offset; - OFFSET2 = offset2; -} + void HX711_2::set_offset(long offset, long offset2) + { + OFFSET = offset; + OFFSET2 = offset2; + } -void HX711_2::get_offset(long* offsetValues) { - offsetValues[0] = OFFSET; + void HX711_2::get_offset(long *offsetValues) + { + offsetValues[0] = OFFSET; offsetValues[1] = OFFSET2; -} + } -void HX711_2::power_down() { - digitalWrite(PD_SCK, LOW); - if (PD_SCK2 != 255) - digitalWrite(PD_SCK2, LOW); + void HX711_2::power_down() + { + doubleWrite(PD_SCK, PD_SCK2, LOW); #if FAST_CPU - delayMicroseconds(1); + delayMicroseconds(1); #endif - digitalWrite(PD_SCK, HIGH); - if (PD_SCK2 != 255) - digitalWrite(PD_SCK2, HIGH); -} + doubleWrite(PD_SCK, PD_SCK2, HIGH); + } -void HX711_2::power_up() { - digitalWrite(PD_SCK, LOW); - if (PD_SCK2 != 255) - digitalWrite(PD_SCK2, LOW); -} + void HX711_2::power_up() + { + doubleWrite(PD_SCK, PD_SCK2, LOW); + } From 2dba7e5a67b13de8b0be71b5befe5dba7ea44bd3 Mon Sep 17 00:00:00 2001 From: Vas Date: Fri, 6 May 2022 16:03:02 -0500 Subject: [PATCH 08/10] Merge pull request #233 from nschurando/master --- src/HX711_2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HX711_2.cpp b/src/HX711_2.cpp index a290fee..30c88c8 100644 --- a/src/HX711_2.cpp +++ b/src/HX711_2.cpp @@ -60,7 +60,7 @@ uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_ } -#ifdef ARCH_ESPRESSIF +#if ARCH_ESPRESSIF // ESP8266 doesn't read values between 0x20000 and 0x30000 when DOUT is pulled up. #define DOUT_MODE INPUT #else From cf81533c54abe259ef61d457d7db6eef94f6ea25 Mon Sep 17 00:00:00 2001 From: "mr.toor" <42692077+Zer0-bit@users.noreply.github.com> Date: Mon, 4 Jul 2022 18:33:45 +0100 Subject: [PATCH 09/10] FAST_CPU clock output change to open drain (#4) * FAST_CPU clock output change to open drain * reworked the #define logic a bit * switching to a clock specific define as parameter * clock mode as function param * making clock_mode unsigned char * delay us macro changes Co-authored-by: Zer0-bit --- src/HX711_2.cpp | 19 +++++++++++-------- src/HX711_2.h | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/HX711_2.cpp b/src/HX711_2.cpp index a3b403a..7a9d807 100644 --- a/src/HX711_2.cpp +++ b/src/HX711_2.cpp @@ -32,6 +32,9 @@ #include #endif +// Defines the delay(us) between setting the HIGH/LOW modes of the clock pins +#define DELAY_MICROSECONDS 3 + static inline void doubleWrite(uint8_t pin1, uint8_t pin2, bool level) { digitalWrite(pin1, level); @@ -48,9 +51,9 @@ uint16_t shiftInSlow(uint8_t dataPin, uint8_t dataPin2, uint8_t clockPin, uint8_ for (i = 0; i < 8; ++i) { doubleWrite(clockPin, clockPin2, HIGH); - delayMicroseconds(1); + delayMicroseconds(DELAY_MICROSECONDS); doubleWrite(clockPin, clockPin2, LOW); - delayMicroseconds(1); + delayMicroseconds(DELAY_MICROSECONDS); if (bitOrder == LSBFIRST) { value |= digitalRead(dataPin) << i; @@ -81,16 +84,16 @@ HX711_2::~HX711_2() { } -void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2, byte gain) +void HX711_2::begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2, byte gain, unsigned char sck_mode) { PD_SCK = pd_sck; PD_SCK2 = pd_sck2; DOUT = dout; DOUT2 = dout2; - pinMode(PD_SCK, OUTPUT); + pinMode(PD_SCK, sck_mode); if (PD_SCK2 != 255) - pinMode(PD_SCK2, OUTPUT); + pinMode(PD_SCK2, sck_mode); pinMode(DOUT, DOUT_MODE); pinMode(DOUT2, DOUT_MODE); @@ -184,11 +187,11 @@ void HX711_2::read(long *readValues, unsigned long timeout) { doubleWrite(PD_SCK, PD_SCK2, HIGH); #if FAST_CPU - delayMicroseconds(1); + delayMicroseconds(DELAY_MICROSECONDS); #endif doubleWrite(PD_SCK, PD_SCK2, LOW); #if FAST_CPU - delayMicroseconds(1); + delayMicroseconds(DELAY_MICROSECONDS); #endif } @@ -345,7 +348,7 @@ void HX711_2::read(long *readValues, unsigned long timeout) { doubleWrite(PD_SCK, PD_SCK2, LOW); #if FAST_CPU - delayMicroseconds(1); + delayMicroseconds(DELAY_MICROSECONDS); #endif doubleWrite(PD_SCK, PD_SCK2, HIGH); } diff --git a/src/HX711_2.h b/src/HX711_2.h index 0572995..e301c03 100644 --- a/src/HX711_2.h +++ b/src/HX711_2.h @@ -40,7 +40,8 @@ class HX711_2 // - 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). - void begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2 = 255, byte gain = 128); + // Clock pins can be switched in different mode passing a mode MACRO as the last param, defaults to OUTPUT. + void begin(byte dout, byte dout2, byte pd_sck, byte pd_sck2 = 255, byte gain = 128, unsigned char sck_mode = OUTPUT); // Check if HX711 is ready // from the datasheet: When output data is not ready for retrieval, digital output pin DOUT is high. Serial clock From 64a60aed6f9b60e2004a99b914ca3ec433e10de6 Mon Sep 17 00:00:00 2001 From: evilbug Date: Wed, 10 May 2023 11:11:56 +0200 Subject: [PATCH 10/10] Update HX711_2.cpp fix optional doublewrite second pin check --- src/HX711_2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HX711_2.cpp b/src/HX711_2.cpp index 7a9d807..0652f1a 100644 --- a/src/HX711_2.cpp +++ b/src/HX711_2.cpp @@ -38,7 +38,7 @@ static inline void doubleWrite(uint8_t pin1, uint8_t pin2, bool level) { digitalWrite(pin1, level); - if (pin1 != 255) + if (pin2 != 255) digitalWrite(pin2, level); }