Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: EXPO_ANDA EXPO_ANDA_Copilotoco
HX711.cpp
00001 /** 00002 * @brief HX711.h 00003 * @details 24-Bit Analog-to-Digital Converter (ADC) for Weigh Scales. 00004 * Function file. 00005 * 00006 * 00007 * @return NA 00008 * 00009 * @author Manuel Caballero 00010 * @date 11/September/2017 00011 * @version 11/September/2017 The ORIGIN 00012 * @pre NaN. 00013 * @warning NaN 00014 * @pre This code belongs to Nimbus Centre ( http://www.nimbus.cit.ie ). 00015 */ 00016 00017 #include "HX711.h" 00018 00019 00020 HX711::HX711 ( PinName PD_SCK, PinName DOUT ) 00021 : _PD_SCK ( PD_SCK ) 00022 , _DOUT ( DOUT ) 00023 { 00024 00025 } 00026 00027 00028 HX711::~HX711() 00029 { 00030 } 00031 00032 00033 00034 /** 00035 * @brief HX711_Reset ( void ) 00036 * 00037 * @details It performs an internal reset. 00038 * 00039 * @param[in] NaN. 00040 * 00041 * @param[out] NaN. 00042 * 00043 * 00044 * @return Status of HX711_Reset. 00045 * 00046 * 00047 * @author Manuel Caballero 00048 * @date 11/September/2017 00049 * @version 11/September/2017 The ORIGIN 00050 * @pre When PD_SCK pin changes from low to high and stays at high for 00051 * longer than 60μs, HX711 enters power down mode. 00052 * 00053 * When PD_SCK returns to low, chip will reset and enter normal 00054 * operation mode. 00055 * @warning NaN. 00056 */ 00057 HX711::HX711_status_t HX711::HX711_Reset ( void ) 00058 { 00059 _PD_SCK = HX711_PIN_HIGH; 00060 wait_us ( 120 ); // Datasheet p5. At least 60us ( Security Factor: 2*60us = 120us ) 00061 _PD_SCK = HX711_PIN_LOW; 00062 00063 00064 00065 if ( _DOUT == HX711_PIN_HIGH ) 00066 return HX711_SUCCESS; 00067 else 00068 return HX711_FAILURE; 00069 } 00070 00071 00072 00073 /** 00074 * @brief HX711_PowerDown ( void ) 00075 * 00076 * @details It puts the device in power-down mode. 00077 * 00078 * @param[in] NaN. 00079 * 00080 * @param[out] NaN. 00081 * 00082 * 00083 * @return Status of HX711_PowerDown. 00084 * 00085 * 00086 * @author Manuel Caballero 00087 * @date 11/September/2017 00088 * @version 11/September/2017 The ORIGIN 00089 * @pre When PD_SCK pin changes from low to high and stays at high for 00090 * longer than 60μs, HX711 enters power down mode. 00091 * @warning NaN. 00092 */ 00093 HX711::HX711_status_t HX711::HX711_PowerDown ( void ) 00094 { 00095 _PD_SCK = HX711_PIN_HIGH; 00096 wait_us ( 120 ); // Datasheet p5. At least 60us ( Security Factor: 2*60us = 120us ) 00097 00098 00099 00100 if ( _DOUT == HX711_PIN_HIGH ) 00101 return HX711_SUCCESS; 00102 else 00103 return HX711_FAILURE; 00104 } 00105 00106 00107 00108 /** 00109 * @brief HX711_SetChannelAndGain ( HX711_channel_gain_t myChannel_Gain ) 00110 * 00111 * @details It sets both the channel and the gain for the next measurement. 00112 * 00113 * @param[in] myChannel_Gain: Channel and Gain to perform the new measurement. 00114 * 00115 * @param[out] NaN. 00116 * 00117 * 00118 * @return Status of HX711_SetChannelAndGain. 00119 * 00120 * 00121 * @author Manuel Caballero 00122 * @date 11/September/2017 00123 * @version 11/September/2017 The ORIGIN 00124 * @pre NaN. 00125 * @warning NaN. 00126 */ 00127 HX711::HX711_status_t HX711::HX711_SetChannelAndGain ( HX711_channel_gain_t myChannel_Gain ) 00128 { 00129 uint32_t myPulses = 0; 00130 uint32_t i = 0; // Counter and timeout variable 00131 00132 // Select the gain/channel 00133 switch ( myChannel_Gain ) { 00134 default: 00135 case CHANNEL_A_GAIN_128 : 00136 _HX711_CHANNEL_GAIN = CHANNEL_A_GAIN_128 ; // Update the gain parameter 00137 myPulses = 25; 00138 break; 00139 00140 case CHANNEL_B_GAIN_32 : 00141 _HX711_CHANNEL_GAIN = CHANNEL_B_GAIN_32 ; // Update the gain parameter 00142 myPulses = 26; 00143 break; 00144 00145 case CHANNEL_A_GAIN_64 : 00146 _HX711_CHANNEL_GAIN = CHANNEL_A_GAIN_64 ; // Update the gain parameter 00147 myPulses = 27; 00148 break; 00149 } 00150 00151 00152 // Wait until the device is ready or timeout 00153 i = 23232323; 00154 _PD_SCK = HX711_PIN_LOW; 00155 while ( ( _DOUT == HX711_PIN_HIGH ) && ( --i ) ); 00156 00157 // Check if something is wrong with the device because of the timeout 00158 if ( i < 1 ) 00159 return HX711_FAILURE; 00160 00161 // Change the gain for the NEXT mesurement ( previous data will be ignored ) 00162 do { 00163 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00164 _PD_SCK = HX711_PIN_HIGH; 00165 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00166 _PD_SCK = HX711_PIN_LOW; 00167 00168 myPulses--; 00169 } while ( myPulses > 0 ); 00170 00171 00172 00173 00174 if ( _DOUT == HX711_PIN_HIGH ) 00175 return HX711_SUCCESS; 00176 else 00177 return HX711_FAILURE; 00178 } 00179 00180 00181 00182 /** 00183 * @brief HX711_GetChannelAndGain ( void ) 00184 * 00185 * @details It gets both the channel and the gain for the current measurement. 00186 * 00187 * @param[in] NaN. 00188 * 00189 * @param[out] NaN. 00190 * 00191 * 00192 * @return Channel and Gain. 00193 * 00194 * 00195 * @author Manuel Caballero 00196 * @date 12/September/2017 00197 * @version 12/September/2017 The ORIGIN 00198 * @pre NaN. 00199 * @warning NaN. 00200 */ 00201 HX711::HX711_channel_gain_t HX711::HX711_GetChannelAndGain ( void ) 00202 { 00203 return _HX711_CHANNEL_GAIN; 00204 } 00205 00206 00207 00208 /** 00209 * @brief HX711_ReadRawData ( HX711_channel_gain_t myChannel_Gain, Vector_count_t*, uint32_t ) 00210 * 00211 * @details It reads the raw data from the device according to the channel 00212 * and its gain. 00213 * 00214 * @param[in] myChannel_Gain: Channel and Gain to perform the new read. 00215 * @param[in] myAverage: How many measurement we have to get and deliver the average. 00216 * 00217 * @param[out] myNewRawData: The new value from the device. 00218 * 00219 * 00220 * @return Status of HX711_ReadRawData. 00221 * 00222 * 00223 * @author Manuel Caballero 00224 * @date 11/September/2017 00225 * @version 12/September/2017 Gain mode was fixed, now it gets the value 00226 * a given gain/channel. A timeout was added to 00227 * avoid the microcontroller gets stuck. 00228 * 11/September/2017 The ORIGIN 00229 * @pre NaN. 00230 * @warning NaN. 00231 */ 00232 HX711::HX711_status_t HX711::HX711_ReadRawData ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage ) 00233 { 00234 uint32_t i = 0; // Counter and timeout variable 00235 uint32_t ii = 0; // Counter variable 00236 uint32_t myAuxData = 0; 00237 uint32_t myPulses = 0; 00238 00239 00240 00241 myNewRawData->myRawValue = 0; // Reset variable at the beginning 00242 00243 // Check the gain if it is different, update it ( previous data will be ignored! ) 00244 if ( myChannel_Gain != _HX711_CHANNEL_GAIN ) 00245 HX711_SetChannelAndGain ( myChannel_Gain ); 00246 00247 00248 // Start collecting the new measurement as many as myAverage 00249 for ( ii = 0; ii < myAverage; ii++ ) { 00250 // Reset the value 00251 myAuxData = 0; 00252 00253 // Wait until the device is ready or timeout 00254 i = 23232323; 00255 _PD_SCK = HX711_PIN_LOW; 00256 while ( ( _DOUT == HX711_PIN_HIGH ) && ( --i ) ); 00257 00258 // Check if something is wrong with the device because of the timeout 00259 if ( i < 1 ) 00260 return HX711_FAILURE; 00261 00262 00263 // Read the data 00264 for ( i = 0; i < 24; i++ ) { 00265 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00266 _PD_SCK = HX711_PIN_HIGH; 00267 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00268 myAuxData <<= 1; 00269 _PD_SCK = HX711_PIN_LOW; 00270 00271 // High or Low bit 00272 if ( _DOUT == HX711_PIN_HIGH ) 00273 myAuxData++; 00274 } 00275 00276 // Last bit to release the bus 00277 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00278 _PD_SCK = HX711_PIN_HIGH; 00279 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00280 _PD_SCK = HX711_PIN_LOW; 00281 00282 00283 // Depending on the Gain we have to generate more CLK pulses 00284 switch ( _HX711_CHANNEL_GAIN ) { 00285 default: 00286 case CHANNEL_A_GAIN_128 : 00287 myPulses = 25; 00288 break; 00289 00290 case CHANNEL_B_GAIN_32 : 00291 myPulses = 26; 00292 break; 00293 00294 case CHANNEL_A_GAIN_64 : 00295 myPulses = 27; 00296 break; 00297 } 00298 00299 // Generate those extra pulses for the next measurement 00300 for ( i = 25; i < myPulses; i++ ) { 00301 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00302 _PD_SCK = HX711_PIN_HIGH; 00303 wait_us ( 1 ); // Datasheet p5. T3 and T4 ( Min. 0.2us | Typ. 1us ) 00304 _PD_SCK = HX711_PIN_LOW; 00305 } 00306 00307 // Update data to get the average 00308 myAuxData ^= 0x800000; 00309 myNewRawData->myRawValue += myAuxData; 00310 } 00311 00312 myNewRawData->myRawValue /= ( float )myAverage; 00313 00314 00315 00316 if ( _DOUT == HX711_PIN_HIGH ) 00317 return HX711_SUCCESS; 00318 else 00319 return HX711_FAILURE; 00320 } 00321 00322 00323 00324 /** 00325 * @brief HX711_ReadData_WithCalibratedMass ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage ) 00326 * 00327 * @details It reads data with a calibrated mass on the load cell. 00328 * 00329 * @param[in] myChannel_Gain: Gain/Channel to perform the new measurement. 00330 * @param[in] myAverage: How many data to read. 00331 * 00332 * @param[out] myNewRawData: myRawValue_WithCalibratedMass ( ADC code taken with calibrated mass ). 00333 * 00334 * 00335 * @return Status of HX711_ReadData_WithCalibratedMass. 00336 * 00337 * 00338 * @author Manuel Caballero 00339 * @date 12/September/2017 00340 * @version 12/September/2017 The ORIGIN 00341 * @pre NaN. 00342 * @warning NaN. 00343 */ 00344 HX711::HX711_status_t HX711::HX711_ReadData_WithCalibratedMass ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage ) 00345 { 00346 HX711_status_t aux; 00347 00348 // Perform a new bunch of readings 00349 aux = HX711_ReadRawData ( myChannel_Gain, myNewRawData, myAverage ); 00350 00351 00352 // Update the value with a calibrated mass 00353 myNewRawData->myRawValue_WithCalibratedMass = myNewRawData->myRawValue; 00354 00355 00356 00357 if ( aux == HX711_SUCCESS ) 00358 return HX711_SUCCESS; 00359 else 00360 return HX711_FAILURE; 00361 } 00362 00363 00364 00365 /** 00366 * @brief HX711_ReadData_WithoutMass ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage ) 00367 * 00368 * @details It reads data without any mass on the load cell. 00369 * 00370 * @param[in] myChannel_Gain: Gain/Channel to perform the new measurement. 00371 * @param[in] myAverage: How many data to read. 00372 * 00373 * @param[out] myNewRawData: myRawValue_WithoutCalibratedMass ( ADC code taken without any mass ). 00374 * 00375 * 00376 * @return Status of HX711_ReadData_WithoutMass. 00377 * 00378 * 00379 * @author Manuel Caballero 00380 * @date 12/September/2017 00381 * @version 12/September/2017 The ORIGIN 00382 * @pre NaN. 00383 * @warning NaN. 00384 */ 00385 HX711::HX711_status_t HX711::HX711_ReadData_WithoutMass ( HX711_channel_gain_t myChannel_Gain, Vector_count_t* myNewRawData, uint32_t myAverage ) 00386 { 00387 HX711_status_t aux; 00388 00389 // Perform a new bunch of readings 00390 aux = HX711_ReadRawData ( myChannel_Gain, myNewRawData, myAverage ); 00391 00392 00393 // Update the value without any mass 00394 myNewRawData->myRawValue_WithoutCalibratedMass = myNewRawData->myRawValue; 00395 00396 00397 00398 if ( aux == HX711_SUCCESS ) 00399 return HX711_SUCCESS; 00400 else 00401 return HX711_FAILURE; 00402 } 00403 00404 00405 00406 /** 00407 * @brief HX711_CalculateMass ( Vector_count_t* myNewRawData, uint32_t myCalibratedMass, HX711_scale_t myScaleCalibratedMass ) 00408 * 00409 * @details It calculates the mass. 00410 * 00411 * @param[in] myNewRawData: It has myRawValue_WithCalibratedMass ( ADC code taken with calibrated mass ), 00412 * myRawValue_WithoutCalibratedMass ( ADC code taken without any mass ) and 00413 * myRawValue ( the current data taken by the system ). 00414 * @param[in] myCalibratedMass: A known value for the calibrated mass when myRawValue_WithCalibratedMass was 00415 * calculated. 00416 * @param[in] myScaleCalibratedMass: The range of the calibrated mass ( kg, g, mg or ug ). 00417 * 00418 * @param[out] NaN. 00419 * 00420 * 00421 * @return The calculated mass. 00422 * 00423 * 00424 * @author Manuel Caballero 00425 * @date 12/September/2017 00426 * @version 13/September/2017 Adapt the scale was fixed, myFactor now works as expected. 00427 * 12/September/2017 The ORIGIN 00428 * @pre NaN. 00429 * @warning NaN. 00430 */ 00431 HX711::Vector_mass_t HX711::HX711_CalculateMass ( Vector_count_t* myNewRawData, float myCalibratedMass, HX711_scale_t myScaleCalibratedMass ) 00432 { 00433 // Terminology by Texas Instruments: sbau175a.pdf, p8 2.1.1 Calculation of Mass 00434 float m, w_zs; 00435 float c_zs, w_fs, c_fs, w_t; 00436 float c = 0; 00437 float myFactor = 1.0; 00438 00439 Vector_mass_t w; 00440 00441 00442 // Adapt the scale ( kg as reference ) 00443 switch ( myScaleCalibratedMass ) { 00444 default: 00445 case HX711_SCALE_kg : 00446 // myFactor = 1.0; 00447 break; 00448 00449 case HX711_SCALE_g : 00450 myFactor /= 1000.0; 00451 break; 00452 00453 case HX711_SCALE_mg : 00454 myFactor /= 1000000.0; 00455 break; 00456 00457 case HX711_SCALE_ug : 00458 myFactor /= 1000000000.0; 00459 break; 00460 00461 } 00462 00463 00464 // Calculate the Calibration Constant ( m ) 00465 w_fs = ( myCalibratedMass / myFactor ); // User-specified calibration mass 00466 c_zs = myNewRawData->myRawValue_WithoutCalibratedMass; // ADC measurement taken with no load 00467 c_fs = myNewRawData->myRawValue_WithCalibratedMass; // ADC code taken with the calibration mass applied 00468 00469 m = ( float )( w_fs / ( ( c_fs ) - c_zs ) ); // The Calibration Constant 00470 00471 00472 // Calculate the zero-scale mass ( w_zs ) 00473 w_zs = - ( m * c_zs ); 00474 00475 00476 // Calculate the mass ( w ) 00477 w_t = myNewRawData->myRawValue_TareWeight; // ADC code taken without any mass after the system is calibrated; 00478 c = myNewRawData->myRawValue; // The ADC code 00479 00480 w.myMass = ( m * c ) + w_zs - w_t; // The mass according to myScaleCalibratedMass 00481 00482 00483 // Update Internal Parameters 00484 _HX711_USER_CALIBATED_MASS = myCalibratedMass; 00485 _HX711_SCALE = myScaleCalibratedMass; 00486 00487 00488 00489 return w; 00490 } 00491 00492 00493 00494 /** 00495 * @brief HX711_SetAutoTare ( HX711_channel_gain_t ,float ,HX711_scale_t ,Vector_count_t* ,float ) 00496 * 00497 * @details It reads data without any mass on the load cell after the system is calibrated to calculate the tare weight. 00498 * 00499 * @param[in] myChannel_Gain: Gain/Channel to perform the new measurement. 00500 * @param[in] myCalibratedMass: A known value for the calibrated mass when myRawValue_WithCalibratedMass was 00501 * calculated. 00502 * @param[in] myScaleCalibratedMass: The range of the calibrated mass ( kg, g, mg or ug ). 00503 * @param[in] myTime: How long the auto-set lasts. 00504 * 00505 * @param[out] myNewRawData: myRawValue_TareWeight ( ADC code taken without any mass ). 00506 * 00507 * 00508 * @return Status of HX711_SetAutoTare. 00509 * 00510 * 00511 * @author Manuel Caballero 00512 * @date 12/September/2017 00513 * @version 12/September/2017 The ORIGIN 00514 * @pre NaN. 00515 * @warning NaN. 00516 */ 00517 HX711::HX711_status_t HX711::HX711_SetAutoTare ( HX711_channel_gain_t myChannel_Gain, float myCalibratedMass, HX711_scale_t myScaleCalibratedMass, Vector_count_t* myNewRawData, float myTime ) 00518 { 00519 HX711_status_t aux; 00520 Vector_mass_t myCalculatedMass; 00521 float myAuxData = 0; 00522 uint32_t i = 0; 00523 00524 00525 // Perform a new bunch of readings every 1 second 00526 for ( i = 0; i < myTime; i++ ) { 00527 aux = HX711_ReadRawData ( myChannel_Gain, myNewRawData, 10 ); 00528 myAuxData += myNewRawData->myRawValue; 00529 wait(1); 00530 } 00531 00532 myNewRawData->myRawValue = ( float )( myAuxData / myTime ); 00533 00534 // Turn it into mass 00535 myCalculatedMass = HX711_CalculateMass ( myNewRawData, myCalibratedMass, myScaleCalibratedMass ); 00536 00537 // Update the value without any mass 00538 myNewRawData->myRawValue_TareWeight = myCalculatedMass.myMass; 00539 00540 00541 // Update Internal Parameters 00542 _HX711_USER_CALIBATED_MASS = myCalibratedMass; 00543 _HX711_SCALE = myScaleCalibratedMass; 00544 00545 00546 00547 if ( aux == HX711_SUCCESS ) 00548 return HX711_SUCCESS; 00549 else 00550 return HX711_FAILURE; 00551 } 00552 00553 00554 00555 /** 00556 * @brief HX711_SetManualTare ( float myTareWeight ) 00557 * 00558 * @details It sets a tare weight manually. 00559 * 00560 * @param[in] myTareWeight: Tare weight. 00561 * 00562 * @param[out] NaN. 00563 * 00564 * 00565 * @return myRawValue_TareWeight. 00566 * 00567 * 00568 * @author Manuel Caballero 00569 * @date 12/September/2017 00570 * @version 12/September/2017 The ORIGIN 00571 * @pre NaN. 00572 * @warning NaN. 00573 */ 00574 HX711::Vector_count_t HX711::HX711_SetManualTare ( float myTareWeight ) 00575 { 00576 Vector_count_t myNewTareWeight; 00577 00578 // Update the value defined by the user 00579 myNewTareWeight.myRawValue_TareWeight = myTareWeight; 00580 00581 00582 00583 return myNewTareWeight; 00584 } 00585 00586 00587 00588 /** 00589 * @brief HX711_CalculateVoltage ( Vector_count_t* ,float ) 00590 * 00591 * @details It calculates the mass. 00592 * 00593 * @param[in] myChannel_Gain: Gain/Channel of the measurement. 00594 * @param[in] myNewRawData: myRawValue ( the current data taken by the system ). 00595 * @param[in] myVoltageReference: The voltage at the converter reference input. 00596 * 00597 * @param[out] NaN. 00598 * 00599 * 00600 * @return The calculated voltage. 00601 * 00602 * 00603 * @author Manuel Caballero 00604 * @date 12/September/2017 00605 * @version 12/September/2017 The ORIGIN 00606 * @pre NaN. 00607 * @warning NaN. 00608 */ 00609 HX711::Vector_voltage_t HX711::HX711_CalculateVoltage ( Vector_count_t* myNewRawData, float myVoltageReference ) 00610 { 00611 // Terminology by Texas Instruments: sbau175a.pdf, p12 3.2 Measurement Modes Raw 00612 float x, B, A; 00613 00614 Vector_voltage_t v; 00615 00616 00617 x = myNewRawData->myRawValue; 00618 B = ( 16777216.0 - 1.0 ); 00619 00620 // Adatp the gain 00621 switch ( _HX711_CHANNEL_GAIN ) { 00622 default: 00623 case CHANNEL_A_GAIN_128 : 00624 A = 128.0; 00625 break; 00626 00627 case CHANNEL_B_GAIN_32 : 00628 A = 32.0; 00629 break; 00630 00631 case CHANNEL_A_GAIN_64 : 00632 A = 64.0; 00633 break; 00634 } 00635 00636 00637 // Calculate the voltage ( v ) 00638 v.myVoltage = ( float )( ( x / B ) * ( myVoltageReference / A ) ); // The voltage 00639 00640 00641 00642 00643 return v; 00644 }
Generated on Thu Jul 14 2022 09:09:44 by
