Sim Youngwoo / HX711

Dependents:   torque_calibration_ywsim

Revision:
2:1af13a8a8275
Parent:
1:06652a775538
Child:
3:d246aa415f3a
--- a/HX711.cpp	Mon Sep 11 10:43:54 2017 +0000
+++ b/HX711.cpp	Tue Sep 12 14:38:13 2017 +0000
@@ -17,10 +17,9 @@
 #include "HX711.h"
 
 
-HX711::HX711 ( PinName PD_SCK, PinName DOUT, HX711_channel_gain_t myChannel_Gain )
+HX711::HX711 ( PinName PD_SCK, PinName DOUT )
     : _PD_SCK               ( PD_SCK )
     , _DOUT                 ( DOUT )
-    , _HX711_CHANNEL_GAIN   ( myChannel_Gain )
 {
 
 }
@@ -48,25 +47,25 @@
  * @author      Manuel Caballero
  * @date        11/September/2017
  * @version     11/September/2017   The ORIGIN
- * @pre         When PD_SCK pin changes from low to high and stays at high for 
+ * @pre         When PD_SCK pin changes from low to high and stays at high for
  *              longer than 60μs, HX711 enters power down mode.
- *              
- *              When PD_SCK returns to low, chip will reset and enter normal 
+ *
+ *              When PD_SCK returns to low, chip will reset and enter normal
  *              operation mode.
  * @warning     NaN.
  */
 HX711::HX711_status_t  HX711::HX711_Reset   ( void )
 {
     _PD_SCK  =  HX711_PIN_HIGH;
-    wait ( 0.120 );
+    wait_us ( 120 );                                                            // Datasheet p5. At least 60us ( Security Factor: 2*60us = 120us )
     _PD_SCK  =  HX711_PIN_LOW;
 
-    
-    
+
+
     if ( _DOUT == HX711_PIN_HIGH )
-       return   HX711_SUCCESS;
+        return   HX711_SUCCESS;
     else
-       return   HX711_FAILURE;
+        return   HX711_FAILURE;
 }
 
 
@@ -87,19 +86,461 @@
  * @author      Manuel Caballero
  * @date        11/September/2017
  * @version     11/September/2017   The ORIGIN
- * @pre         When PD_SCK pin changes from low to high and stays at high for 
+ * @pre         When PD_SCK pin changes from low to high and stays at high for
  *              longer than 60μs, HX711 enters power down mode.
  * @warning     NaN.
  */
 HX711::HX711_status_t  HX711::HX711_PowerDown   ( void )
 {
     _PD_SCK  =  HX711_PIN_HIGH;
-    wait ( 0.120 );
+    wait_us ( 120 );                                                            // Datasheet p5. At least 60us ( Security Factor: 2*60us = 120us )
+
+
+
+    if ( _DOUT == HX711_PIN_HIGH )
+        return   HX711_SUCCESS;
+    else
+        return   HX711_FAILURE;
+}
+
+
+
+/**
+ * @brief       HX711_SetChannelAndGain   ( HX711_channel_gain_t myChannel_Gain )
+ *
+ * @details     It sets both the channel and the gain for the next measurement.
+ *
+ * @param[in]    myChannel_Gain:    Channel and Gain to perform the new measurement.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HX711_SetChannelAndGain.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        11/September/2017
+ * @version     11/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::HX711_status_t  HX711::HX711_SetChannelAndGain    ( HX711_channel_gain_t myChannel_Gain )
+{
+    uint32_t myPulses   =    0;
+    uint32_t i          =    0;                                                 // Counter and timeout variable
+
+    // Select the gain/channel
+    switch ( myChannel_Gain ) {
+        default:
+        case CHANNEL_A_GAIN_128:
+            _HX711_CHANNEL_GAIN  =   CHANNEL_A_GAIN_128;                        // Update the gain parameter
+            myPulses             =   25;
+            break;
+
+        case CHANNEL_B_GAIN_32:
+            _HX711_CHANNEL_GAIN  =   CHANNEL_B_GAIN_32;                         // Update the gain parameter
+            myPulses             =   26;
+            break;
+
+        case CHANNEL_A_GAIN_64:
+            _HX711_CHANNEL_GAIN  =   CHANNEL_A_GAIN_64;                         // Update the gain parameter
+            myPulses             =   27;
+            break;
+    }
+
+
+    // Wait until the device is ready or timeout
+    i        =   23232323;
+    _PD_SCK  =  HX711_PIN_LOW;
+    while ( ( _DOUT == HX711_PIN_HIGH ) && ( --i ) );
+
+    // Check if something is wrong with the device because of the timeout
+    if ( i < 1 )
+        return   HX711_FAILURE;
+
+    // Change the gain for the NEXT mesurement ( previous data will be ignored )
+    do {
+        wait_us ( 1 );                                                          // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+        _PD_SCK  =  HX711_PIN_HIGH;
+        wait_us ( 1 );                                                          // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+        _PD_SCK  =  HX711_PIN_LOW;
+
+        myPulses--;
+    } while ( myPulses > 0 );
+
+
+
+
+    if ( _DOUT == HX711_PIN_HIGH )
+        return   HX711_SUCCESS;
+    else
+        return   HX711_FAILURE;
+}
+
+
+
+/**
+ * @brief       HX711_GetChannelAndGain   ( void )
+ *
+ * @details     It gets both the channel and the gain for the current measurement.
+ *
+ * @param[in]    NaN.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Channel and Gain.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        12/September/2017
+ * @version     12/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::HX711_channel_gain_t  HX711::HX711_GetChannelAndGain ( void )
+{
+    return   _HX711_CHANNEL_GAIN;
+}
 
-    
-    
+
+
+/**
+ * @brief       HX711_ReadRawData   ( HX711_channel_gain_t myChannel_Gain, Vector_count_t*, uint32_t )
+ *
+ * @details     It reads the raw data from the device according to the channel
+ *              and its gain.
+ *
+ * @param[in]    myChannel_Gain:    Channel and Gain to perform the new read.
+ * @param[in]    myAverage:         How many measurement we have to get and deliver the average.
+ *
+ * @param[out]   myNewRawData:      The new value from the device.
+ *
+ *
+ * @return       Status of HX711_ReadRawData.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        11/September/2017
+ * @version     12/September/2017   Gain mode was fixed, now it gets the value
+ *                                  a given gain/channel. A timeout was added to
+ *                                  avoid the microcontroller gets stuck.
+ *              11/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::HX711_status_t  HX711::HX711_ReadRawData    ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage )
+{
+    uint32_t i           =   0;                                                 // Counter and timeout variable
+    uint32_t ii          =   0;                                                 // Counter variable
+    uint32_t myAuxData   =   0;
+    uint32_t myPulses    =   0;
+
+
+
+    myNewRawData->myRawValue    =   0;                                          // Reset variable at the beginning
+
+    // Check the gain if it is different, update it ( previous data will be ignored! )
+    if ( myChannel_Gain != CHANNEL_A_GAIN_128 )
+        HX711_SetChannelAndGain ( myChannel_Gain );
+
+
+    // Start collecting the new measurement as many as myAverage
+    for ( ii = 0; ii < myAverage; ii++ ) {
+        // Reset the value
+        myAuxData    =   0;
+
+        // Wait until the device is ready or timeout
+        i        =   23232323;
+        _PD_SCK  =  HX711_PIN_LOW;
+        while ( ( _DOUT == HX711_PIN_HIGH ) && ( --i ) );
+
+        // Check if something is wrong with the device because of the timeout
+        if ( i < 1 )
+            return   HX711_FAILURE;
+
+
+        // Read the data
+        for ( i = 0; i < 24; i++ ) {
+            wait_us ( 1 );                                                      // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+            _PD_SCK  =  HX711_PIN_HIGH;
+            wait_us ( 1 );                                                      // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+            myAuxData    <<=     1;
+            _PD_SCK  =  HX711_PIN_LOW;
+
+            // High or Low bit
+            if ( _DOUT == HX711_PIN_HIGH )
+                myAuxData++;
+        }
+
+        // Last bit to release the bus
+        wait_us ( 1 );                                                          // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+        _PD_SCK  =  HX711_PIN_HIGH;
+        wait_us ( 1 );                                                          // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+        _PD_SCK  =  HX711_PIN_LOW;
+
+
+        // Depending on the Gain we have to generate more CLK pulses
+        switch ( _HX711_CHANNEL_GAIN ) {
+            default:
+            case CHANNEL_A_GAIN_128:
+                myPulses             =   25;
+                break;
+
+            case CHANNEL_B_GAIN_32:
+                myPulses             =   26;
+                break;
+
+            case CHANNEL_A_GAIN_64:
+                myPulses             =   27;
+                break;
+        }
+
+        // Generate those extra pulses for the next measurement
+        for ( i = 25; i < myPulses; i++ ) {
+            wait_us ( 1 );                                                      // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+            _PD_SCK  =  HX711_PIN_HIGH;
+            wait_us ( 1 );                                                      // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us )
+            _PD_SCK  =  HX711_PIN_LOW;
+        }
+
+        // Update data to get the average
+        myAuxData                  ^=    0x800000;
+        myNewRawData->myRawValue   +=    myAuxData;
+    }
+
+    myNewRawData->myRawValue    /=    ( float )myAverage;
+
+
+
     if ( _DOUT == HX711_PIN_HIGH )
-       return   HX711_SUCCESS;
+        return   HX711_SUCCESS;
+    else
+        return   HX711_FAILURE;
+}
+
+
+
+/**
+ * @brief       HX711_ReadData_WithCalibratedMass ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage )
+ *
+ * @details     It reads data with a calibrated mass on the load cell.
+ *
+ * @param[in]    myChannel_Gain:        Gain/Channel to perform the new measurement.
+ * @param[in]    myAverage:             How many data to read.
+ *
+ * @param[out]   myNewRawData:          myRawValue_WithCalibratedMass ( ADC code taken with calibrated mass ).
+ *
+ *
+ * @return       Status of HX711_ReadData_WithCalibratedMass.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        12/September/2017
+ * @version     12/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::HX711_status_t  HX711::HX711_ReadData_WithCalibratedMass   ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage )
+{
+    HX711_status_t        aux;
+
+    // Perform a new bunch of readings
+    aux  =   HX711_ReadRawData ( myChannel_Gain, myNewRawData, myAverage );
+
+
+    // Update the value with a calibrated mass
+    myNewRawData->myRawValue_WithCalibratedMass  =   myNewRawData->myRawValue;
+
+
+
+    if ( aux == HX711_SUCCESS )
+        return   HX711_SUCCESS;
+    else
+        return   HX711_FAILURE;
+}
+
+
+
+/**
+ * @brief       HX711_ReadData_WithoutMass ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage )
+ *
+ * @details     It reads data without any mass on the load cell.
+ *
+ * @param[in]    myChannel_Gain:        Gain/Channel to perform the new measurement.
+ * @param[in]    myAverage:             How many data to read.
+ *
+ * @param[out]   myNewRawData:          myRawValue_WithoutCalibratedMass ( ADC code taken without any mass ).
+ *
+ *
+ * @return       Status of HX711_ReadData_WithoutMass.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        12/September/2017
+ * @version     12/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::HX711_status_t  HX711::HX711_ReadData_WithoutMass   ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage )
+{
+    HX711_status_t        aux;
+
+    // Perform a new bunch of readings
+    aux  =   HX711_ReadRawData ( myChannel_Gain, myNewRawData, myAverage );
+
+
+    // Update the value without any mass
+    myNewRawData->myRawValue_WithoutCalibratedMass  =   myNewRawData->myRawValue;
+
+
+
+    if ( aux == HX711_SUCCESS )
+        return   HX711_SUCCESS;
     else
-       return   HX711_FAILURE;
-}
\ No newline at end of file
+        return   HX711_FAILURE;
+}
+
+
+
+/**
+ * @brief       HX711_CalculateMass ( Vector_count_t* myNewRawData, uint32_t myCalibratedMass, HX711_scale_t myScaleCalibratedMass )
+ *
+ * @details     It calculates the mass.
+ *
+ * @param[in]    myNewRawData:              It has myRawValue_WithCalibratedMass ( ADC code taken with calibrated mass ),
+ *                                          myRawValue_WithoutCalibratedMass ( ADC code taken without any mass ) and
+ *                                          myRawValue ( the current data taken by the system ).
+ * @param[in]    myCalibratedMass:          A known value for the calibrated mass when myRawValue_WithCalibratedMass was
+ *                                          calculated.
+ * @param[in]    myScaleCalibratedMass:     The range of the calibrated mass ( kg, g, mg or ug ).
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       The calculated mass.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        12/September/2017
+ * @version     12/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::Vector_mass_t  HX711::HX711_CalculateMass ( Vector_count_t* myNewRawData, float myCalibratedMass, HX711_scale_t myScaleCalibratedMass )
+{
+    // Terminology by Texas Instruments: sbau175a.pdf, p8 2.1.1 Calculation of Mass
+    float m, w_zs;
+    float c_zs, w_fs, c_fs, w_t;
+    float c = 0;
+    float myFactor   =   0;
+
+    Vector_mass_t w;
+
+
+    // Adapt the scale ( kg as reference )
+    switch ( myScaleCalibratedMass ) {
+        default:
+        case HX711_SCALE_kg:
+            myFactor     =   1.0;
+            break;
+
+        case HX711_SCALE_g:
+            myFactor     /=   1000.0;
+            break;
+
+        case HX711_SCALE_mg:
+            myFactor     /=   1000000.0;
+            break;
+
+        case HX711_SCALE_ug:
+            myFactor     /=   1000000000.0;
+            break;
+
+    }
+
+
+    // Calculate the Calibration Constant ( m )
+    w_fs    =    ( myCalibratedMass / myFactor );                               // User-specified calibration mass
+    c_zs    =    myNewRawData->myRawValue_WithoutCalibratedMass;                // ADC measurement taken with no load
+    c_fs    =    myNewRawData->myRawValue_WithCalibratedMass;                   // ADC code taken with the calibration mass applied
+
+    m       =    ( float )( w_fs / ( ( c_fs ) - c_zs  ) );                      // The Calibration Constant
+
+
+    // Calculate the zero-scale mass ( w_zs )
+    w_zs    =    - ( m * c_zs );
+
+
+    // Calculate the mass ( w )
+    w_t     =    myNewRawData->myRawValue_TareWeight;                           // ADC code taken without any mass after the system is calibrated;
+    c       =    myNewRawData->myRawValue;                                      // The ADC code
+
+    w.myMass   =    ( m * c ) + w_zs - w_t;                                     // The mass according to myScaleCalibratedMass
+
+
+    // Update Internal Parameters
+    _HX711_USER_CALIBATED_MASS   =   myCalibratedMass;
+    _HX711_SCALE                 =   myScaleCalibratedMass;
+
+
+
+    return   w;
+}
+
+
+
+/**
+ * @brief       HX711_SetAutoTare ( HX711_channel_gain_t , Vector_count_t* , float )
+ *
+ * @details     It reads data without any mass on the load cell after the system is calibrated to calculate the tare weight.
+ *
+ * @param[in]    myChannel_Gain:        Gain/Channel to perform the new measurement.
+ * @param[in]    myTime:                How long the auto-set lasts.
+ *
+ * @param[out]   myNewRawData:          myRawValue_TareWeight ( ADC code taken without any mass ).
+ *
+ *
+ * @return       Status of HX711_SetAutoTare.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        12/September/2017
+ * @version     12/September/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HX711::HX711_status_t  HX711::HX711_SetAutoTare   ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, float myTime )
+{
+    HX711_status_t        aux;
+    Vector_mass_t         myCalculatedMass;
+    float                 myAuxData = 0;
+    uint32_t              i = 0;
+
+
+    // Perform a new bunch of readings every 1 second
+    for ( i = 0; i < myTime; i++ ) {
+        aux          =   HX711_ReadRawData ( myChannel_Gain, myNewRawData, 10 );
+        myAuxData   +=   myNewRawData->myRawValue;
+        wait(1);
+    }
+    
+    myNewRawData->myRawValue    =    ( float )( myAuxData / myTime );
+    
+    // Turn it into mass
+    myCalculatedMass     =   HX711_CalculateMass ( myNewRawData, _HX711_USER_CALIBATED_MASS, _HX711_SCALE );
+
+    // Update the value without any mass
+    myNewRawData->myRawValue_TareWeight  =   myCalculatedMass.myMass;
+
+
+
+    if ( aux == HX711_SUCCESS )
+        return   HX711_SUCCESS;
+    else
+        return   HX711_FAILURE;
+}
+
+
+
+