From df302ff5db962d8be94acbc6371b3999f331b053 Mon Sep 17 00:00:00 2001 From: Rafael Neri Date: Sat, 21 Mar 2015 15:52:03 -0300 Subject: [PATCH] hx711: Initial implementation HX711 24bit ADC module Signed-off-by: Rafael Neri Signed-off-by: Mihai Tudor Panu --- docs/images/hx711.jpeg | Bin 0 -> 42639 bytes examples/c++/CMakeLists.txt | 4 +- examples/c++/hx711.cxx | 43 ++++++++++ examples/javascript/hx711.js | 36 +++++++++ src/hx711/CMakeLists.txt | 5 ++ src/hx711/hx711.cxx | 148 +++++++++++++++++++++++++++++++++++ src/hx711/hx711.h | 135 ++++++++++++++++++++++++++++++++ src/hx711/jsupm_hx711.i | 10 +++ src/hx711/pyupm_hx711.i | 10 +++ 9 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 docs/images/hx711.jpeg create mode 100644 examples/c++/hx711.cxx create mode 100644 examples/javascript/hx711.js create mode 100644 src/hx711/CMakeLists.txt create mode 100644 src/hx711/hx711.cxx create mode 100644 src/hx711/hx711.h create mode 100644 src/hx711/jsupm_hx711.i create mode 100644 src/hx711/pyupm_hx711.i diff --git a/docs/images/hx711.jpeg b/docs/images/hx711.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..feff7840b9e34011ba70152dbd21c8e796781e81 GIT binary patch literal 42639 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 literal 0 HcmV?d00001 diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 53fc1291..0f18545d 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -103,6 +103,7 @@ add_executable (groveeldriver-example groveeldriver.cxx) add_executable (adafruitss-example adafruitss.cxx) add_executable (adafruitms1438-example adafruitms1438.cxx) add_executable (adafruitms1438-stepper-example adafruitms1438-stepper.cxx) +add_executable (hx711-example hx711.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -186,6 +187,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/pca9685) include_directories (${PROJECT_SOURCE_DIR}/src/groveeldriver) include_directories (${PROJECT_SOURCE_DIR}/src/adafruitss) include_directories (${PROJECT_SOURCE_DIR}/src/adafruitms1438) +include_directories (${PROJECT_SOURCE_DIR}/src/hx711) target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT}) @@ -290,4 +292,4 @@ target_link_libraries (groveeldriver-example groveeldriver ${CMAKE_THREAD_LIBS_I target_link_libraries (adafruitss-example adafruitss ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (adafruitms1438-example adafruitms1438 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (adafruitms1438-stepper-example adafruitms1438 ${CMAKE_THREAD_LIBS_INIT}) - +target_link_libraries (hx711-example hx711 ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/c++/hx711.cxx b/examples/c++/hx711.cxx new file mode 100644 index 00000000..531734b2 --- /dev/null +++ b/examples/c++/hx711.cxx @@ -0,0 +1,43 @@ +/* +* +* Author: Rafael da Mata Neri +* Copyright (c) 2015 Intel Corporation. +* +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include +#include +#include + +//! [Interesting] +#include "hx711.h" + +int +main(int argc, char **argv) +{ + upm::HX711 *scale = new upm::HX711(3, 2); + + // 2837: value obtained via calibration + scale->setScale(2837); + scale->tare(); + std::cout << scale->getUnits() << std::endl; + + return 0; +} +//! [Interesting] diff --git a/examples/javascript/hx711.js b/examples/javascript/hx711.js new file mode 100644 index 00000000..8393734c --- /dev/null +++ b/examples/javascript/hx711.js @@ -0,0 +1,36 @@ +/* +* +* Author: Rafael da Mata Neri +* Copyright (c) 2015 Intel Corporation. +* +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var hx711 = require('jsupm_hx711'); +// Instantiate a HX711 data on digital pin D3 and clock on digital pin D2 +var scale = new hx711.HX711(3, 2); + +setTimeout(function(){ + // 2837: value obtained via calibration + scale.setScale(2837); + scale.tare(2); + setInterval(function(){ + console.log(scale.getUnits()); + }, 1000); +}, 1000); diff --git a/src/hx711/CMakeLists.txt b/src/hx711/CMakeLists.txt new file mode 100644 index 00000000..8cdf95e7 --- /dev/null +++ b/src/hx711/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "hx711") +set (libdescription "HX711 24bit ADC") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/hx711/hx711.cxx b/src/hx711/hx711.cxx new file mode 100644 index 00000000..01fb7893 --- /dev/null +++ b/src/hx711/hx711.cxx @@ -0,0 +1,148 @@ +/* +* +* Author: Rafael da Mata Neri +* Copyright (c) 2015 Intel Corporation. +* +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include +#include +#include +#include +#include +#include "hx711.h" + +using namespace upm; +using namespace std; + +struct HX711Exception : public std::exception { + std::string message; + HX711Exception (std::string msg) : message (msg) { } + ~HX711Exception () throw () { } + const char* what() const throw () { return message.c_str(); } +}; + +HX711::HX711(uint8_t data, uint8_t sck, uint8_t gain) { + mraa_result_t error = MRAA_SUCCESS; + + this->m_dataPinCtx = mraa_gpio_init(data); + if (this->m_dataPinCtx == NULL) { + throw HX711Exception ("Couldn't initilize DATA pin."); + } + + this->m_sckPinCtx = mraa_gpio_init(sck); + if (this->m_sckPinCtx == NULL) { + throw HX711Exception ("Couldn't initilize CLOCK pin."); + } + + error = mraa_gpio_dir (this->m_dataPinCtx, MRAA_GPIO_IN); + if (error != MRAA_SUCCESS) { + throw HX711Exception ("Couldn't set direction for DATA pin."); + } + + error = mraa_gpio_dir (this->m_sckPinCtx, MRAA_GPIO_OUT); + if (error != MRAA_SUCCESS) { + throw HX711Exception ("Couldn't set direction for CLOCK pin."); + } + + this->setGain(gain); +} + +HX711::~HX711() { + mraa_result_t error = MRAA_SUCCESS; + + error = mraa_gpio_close (this->m_dataPinCtx); + if (error != MRAA_SUCCESS) { + mraa_result_print(error); + } + + error = mraa_gpio_close (this->m_sckPinCtx); + if (error != MRAA_SUCCESS) { + mraa_result_print(error); + } +} + +unsigned long HX711::read() { + unsigned long Count = 0; + + while (mraa_gpio_read(this->m_dataPinCtx)); + + for (int i=0; im_sckPinCtx, 1); + Count = Count << 1; + mraa_gpio_write(this->m_sckPinCtx, 0); + if(mraa_gpio_read(this->m_dataPinCtx)) + { + Count++; + } + } + + mraa_gpio_write(this->m_sckPinCtx, 1); + Count = Count ^ 0x800000; + mraa_gpio_write(this->m_sckPinCtx, 0); + + return (Count); +} + +void HX711::setGain(uint8_t gain){ + switch (gain) { + case 128: // channel A, gain factor 128 + GAIN = 24; + break; + case 64: // channel A, gain factor 64 + GAIN = 26; + break; + case 32: // channel B, gain factor 32 + GAIN = 25; + break; + } + + mraa_gpio_write(this->m_sckPinCtx, 0); + read(); +} + +unsigned long HX711::readAverage(uint8_t times){ + unsigned long sum = 0; + for (uint8_t i = 0; i < times; i++) { + sum += read(); + } + return sum / times; +} + +double HX711::getValue(uint8_t times){ + return readAverage(times) - OFFSET; +} + +float HX711::getUnits(uint8_t times){ + return getValue(times) / SCALE; +} + +void HX711::tare(uint8_t times){ + double sum = readAverage(times); + setOffset(sum); +} + +void HX711::setScale(float scale){ + SCALE = scale; +} + +void HX711::setOffset(long offset){ + OFFSET = offset; +} diff --git a/src/hx711/hx711.h b/src/hx711/hx711.h new file mode 100644 index 00000000..e061b073 --- /dev/null +++ b/src/hx711/hx711.h @@ -0,0 +1,135 @@ +/* +* +* Author: Rafael da Mata Neri +* Copyright (c) 2015 Intel Corporation. +* +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#pragma once + + +#include +#include +#include +#include +#include + +namespace upm { + + /** + * @brief HX711 24bit ADC library + * @defgroup hx711 libupm-hx711 + */ + + /** + * @brief C++ API for HX711 + * + * [HX711](http://www.dfrobot.com/image/data/SEN0160/hx711_english.pdf) is + * a precision 24-bit analog- to-digital converter (ADC) designed for weigh + * scales and industrial control applications to interface directly with a + * bridge sensor. This module was tested on the Intel Galileo Gen2. + * + * @ingroup hx711 hx711 + * @snippet hx711.cxx Interesting + * @image html hx711.jpeg + */ + class HX711 { + public: + /** + * HX711 module constructor + * + * @param data define the data pin + * @param sck define the clock pin + * @param gain define the gain factor + * Valid values are 128 or 64 for channel A; channel B works with 32 gain factor only + */ + HX711(uint8_t data, uint8_t sck, uint8_t gain = 128); + + /** + * HX711 module Destructor + */ + ~HX711(); + + + /** + * Waits for the chip to be ready and returns a reading + * + * @return raw adc read + */ + unsigned long read(); + + /** + * 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 + * @param gain define the gain factor + */ + void setGain(uint8_t gain = 128); + + /** + * Returns an average reading + * @param times define how many times to read + * @return the avarage reading + */ + unsigned long readAverage(uint8_t times = 10); + + /** + * Returns (readAverage() - OFFSET) + * @param times define how many readings to do + * @return the current value without the tare weight + */ + double getValue(uint8_t times = 10); + + /** + * Returns getValue() divided by SCALE + * @param times define how many readings to do + * @return the raw value divided by a value obtained via calibration + */ + float getUnits(uint8_t times = 1); + + /** + * Set the OFFSET value for tare weight + * @param times define how many times to read the tare value + */ + void tare(uint8_t times = 10); + + /** + * Set the SCALE value + * This value is used to convert the raw data to "human readable" data (measure units) + * @param scale value obtained via calibration + */ + void setScale(float scale = 1.f); + private: + mraa_gpio_context m_sckPinCtx; // Power Down and Serial Clock Input Pin + mraa_gpio_context m_dataPinCtx; // Serial Data Output Pin + + uint8_t GAIN; // amplification factor + unsigned long OFFSET; // used for tare weight + float SCALE; // used to return weight in grams, kg, ounces, whatever + + + /** + * Set the OFFSET value + * The value that's subtracted from the actual reading (tare weight) + * @param scale value obtained via calibration + */ + void setOffset(long offset = 0); + }; + +} diff --git a/src/hx711/jsupm_hx711.i b/src/hx711/jsupm_hx711.i new file mode 100644 index 00000000..ff8ec950 --- /dev/null +++ b/src/hx711/jsupm_hx711.i @@ -0,0 +1,10 @@ +//! [Interesting] +%module jsupm_hx711 +%include "../upm.i" + +%{ + #include "hx711.h" +%} + +%include "hx711.h" +//! [Interesting] diff --git a/src/hx711/pyupm_hx711.i b/src/hx711/pyupm_hx711.i new file mode 100644 index 00000000..7d8c7d7e --- /dev/null +++ b/src/hx711/pyupm_hx711.i @@ -0,0 +1,10 @@ +%module pyupm_hx711 +%include "../upm.i" +%include "stdint.i" + +%feature("autodoc", "3"); + +%include "hx711.h" +%{ + #include "hx711.h" +%}