2021-02-21 16:35:18 +00:00
# include <Arduino.h>
# include <Homie.h>
/*
* Wemos d1 mini
* Flash Size : 4 M ( 1 M SPIFFS )
*/
//Upload config: platformio run --target uploadfs
2021-03-14 16:04:24 +00:00
# define PIN_VBAT A0
unsigned long vbat_calib1_adc = 581 ; //adc value at vbat_calib_voltage (voltage at battery)
float vbat_calib1_voltage = 6.0 ; //voltage used for calibration
unsigned long vbat_calib2_adc = 782 ; //second calibration point (higher voltage)
float vbat_calib2_voltage = 8.0 ;
int vbat_raw_filtered = - 1 ; //-1 flags it as initialized
bool vbatSent = false ;
2021-03-16 19:39:56 +00:00
bool weight_updated = false ;
2021-03-16 19:59:29 +00:00
unsigned long last_weightchange = 10000 ; //give some headstart if startup takes a bit longer
2021-03-05 18:49:53 +00:00
# include <TM1637Display.h>
# define TM1637_CLK D5
# define TM1637_DIO D6
TM1637Display display ( TM1637_CLK , TM1637_DIO ) ;
const uint8_t SEG_DONE [ ] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G , // d
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F , // O
SEG_C | SEG_E | SEG_G , // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
} ;
const uint8_t SEG_POINT [ ] = { SEG_DP } ;
uint8_t display_data [ ] = { 0xff , 0xff , 0xff , 0xff } ;
uint8_t display_blank [ ] = { 0x00 , 0x00 , 0x00 , 0x00 } ;
2021-03-05 20:33:28 +00:00
uint8_t display_custom [ ] = { 0x00 , 0x00 , 0x00 , 0x00 } ;
2021-03-05 18:49:53 +00:00
unsigned long last_displayupdate = 0 ;
2021-03-05 19:11:19 +00:00
# define DISPLAYUPDATEINTERVAL 100 //maximum time to update display
# define DISPLAYUPDATEINTERVAL_MIN 10 //minimum display update time
bool update_display = true ;
2021-02-18 21:10:39 +00:00
2021-03-05 20:33:28 +00:00
uint8_t displaybrightness = 7 ; //0 to 7
unsigned long last_new_display_custom = 0 ;
unsigned long display_custom_duration = 1000 * 3 ;
unsigned long last_display_blink = 0 ; //for turning off shortly
unsigned long display_blink_duration = 100 ;
2021-02-22 18:34:18 +00:00
2021-02-18 21:10:39 +00:00
# include "HX711.h"
2021-02-22 19:39:44 +00:00
//#define SCALE_CALIBRATION 23805 //calibrated with 2.25kg weight. devide adc reading by calibration weight (in kg) to get this value (or other way around)
# define SCALE_CALIBRATION 23960 //8 club mate 0.5L bottles weight 7.097kg. scale returns units=340090 with 16 bottles -> 340090/(2*7.097kg) = 23960
2021-02-18 21:10:39 +00:00
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = D2 ;
const int LOADCELL_SCK_PIN = D3 ;
2021-02-21 16:35:18 +00:00
const int PIN_SELFENABLE = D1 ;
2021-02-18 21:10:39 +00:00
HX711 scale ;
2021-02-22 19:03:08 +00:00
float weight_current = 0 ; //last weight reading
2021-03-05 20:33:28 +00:00
float weight_filtered = 0 ;
float spread = 0 ;
2021-02-22 19:03:08 +00:00
2021-02-21 16:35:18 +00:00
# define MEASURE_INTERVAL 100 //ms
# define READING_FILTER_SIZE 40 //latency is about READING_FILTER_SIZE/2*MEASURE_INTERVAL
float weight_read [ READING_FILTER_SIZE ] = { 0 } ;
uint8_t weight_read_pos = 0 ;
2021-03-08 18:36:14 +00:00
# define MEANVALUECOUNT 5 //0<= meanvaluecount < READING_FILTER_SIZE/2. how many values will be used from sorted weight array from the center region. abour double this values reading are used
2021-02-21 16:35:18 +00:00
float weight_tare = 0 ; //minimal filtered weight
# define MIN_WEIGHT_DIFFERENCE 50 //minimum weight
float weight_max = 0 ; //max filtered weight
bool weight_sent = false ;
unsigned long weight_sent_time = 0 ;
# define MAXONTIME 60000*2 //turn off after ms
2021-02-22 19:03:08 +00:00
# define MQTT_SENDINTERVALL 500 //ms
unsigned long last_mqtt_send = 0 ;
bool livesend = false ; //if true, sends continuous data over mqtt
2021-02-21 16:35:18 +00:00
# define FW_NAME "scale"
# define FW_VERSION "0.0.1"
void loopHandler ( ) ;
HomieNode scaleNode ( " weight " , " Scale " , " scale " ) ; //paramters: topic, $name, $type
2021-03-14 16:04:24 +00:00
HomieNode displayNode ( " display " , " Display " , " scale " ) ; //paramters: topic, $name, $type
HomieNode hardwareNode ( " hardware " , " Hardware " , " scale " ) ; //paramters: topic, $name, $type
2021-02-21 16:35:18 +00:00
int sort_desc ( const void * cmp1 , const void * cmp2 ) ;
float getFilteredWeight ( ) ;
float getWeightSpread ( ) ;
void sendWeight ( float w ) ;
2021-02-22 18:34:18 +00:00
bool cmdHandler ( const HomieRange & range , const String & value ) ;
2021-03-05 20:33:28 +00:00
bool displayNodeHandler ( const HomieRange & range , const String & value ) ;
2021-02-22 18:34:18 +00:00
void powerOff ( ) ;
2021-03-05 19:00:16 +00:00
void displayNumber ( float numberdisplay ) ;
2021-03-14 16:04:24 +00:00
float getVBat ( ) ;
void updateVBat ( ) ;
void sendVBat ( ) ;
float mapFloat ( float x , float in_min , float in_max , float out_min , float out_max ) ;
2021-03-05 20:33:28 +00:00
2021-02-18 21:10:39 +00:00
void setup ( ) {
2021-02-21 16:35:18 +00:00
pinMode ( PIN_SELFENABLE , OUTPUT ) ;
digitalWrite ( PIN_SELFENABLE , HIGH ) ;
pinMode ( LED_BUILTIN , OUTPUT ) ;
digitalWrite ( LED_BUILTIN , HIGH ) ;
2021-02-18 21:10:39 +00:00
Serial . begin ( 115200 ) ;
2021-03-16 19:39:56 +00:00
Serial . println ( " Hello " ) ;
2021-02-21 16:35:18 +00:00
2021-03-05 18:49:53 +00:00
2021-03-05 20:33:28 +00:00
display . setBrightness ( displaybrightness , true ) ; //brightness 0 to 7
2021-03-05 18:49:53 +00:00
2021-02-21 16:35:18 +00:00
Homie . disableResetTrigger ( ) ; //disable config reset if pin 1 (D3) is low on startup
Homie_setFirmware ( FW_NAME , FW_VERSION ) ;
Homie_setBrand ( FW_NAME ) ;
2021-03-16 19:39:56 +00:00
Serial . println ( " setLoopFunction " ) ;
2021-02-21 16:35:18 +00:00
Homie . setLoopFunction ( loopHandler ) ;
2021-03-16 19:39:56 +00:00
2021-02-21 16:35:18 +00:00
2021-03-14 16:04:24 +00:00
2021-02-21 16:35:18 +00:00
scaleNode . advertise ( " human " ) ;
scaleNode . advertise ( " spread " ) ;
scaleNode . advertise ( " raw " ) ;
scaleNode . advertise ( " max " ) ;
2021-03-05 20:33:28 +00:00
displayNode . advertise ( " segments " ) . settable ( displayNodeHandler ) ;
2021-02-21 16:35:18 +00:00
2021-03-14 16:04:24 +00:00
hardwareNode . advertise ( " cmd " ) . settable ( cmdHandler ) ; //function inputHandler gets called on new message on topic/input/set
hardwareNode . advertise ( " vbat " ) ;
hardwareNode . advertise ( " vbatraw " ) ;
2021-03-16 19:39:56 +00:00
Serial . println ( " homie setup " ) ;
2021-02-21 16:35:18 +00:00
Homie . setup ( ) ;
2021-02-18 21:10:39 +00:00
scale . begin ( LOADCELL_DOUT_PIN , LOADCELL_SCK_PIN ) ;
2021-02-18 21:28:46 +00:00
//calibration
Serial . println ( " setup " ) ;
2021-02-22 18:34:18 +00:00
scale . set_scale ( SCALE_CALIBRATION ) ;
2021-02-18 21:28:46 +00:00
delay ( 500 ) ;
scale . tare ( ) ;
delay ( 2000 ) ;
Serial . println ( " tared. measuring... " ) ;
//after this taring put known weight on scale and get value from scale.get_units(10). then devide this value by the weight and use this number for set_scale(NUMBER)
2021-02-18 21:10:39 +00:00
}
void loop ( ) {
2021-02-21 16:35:18 +00:00
unsigned long loopmillis = millis ( ) ;
static unsigned long last_measure = 0 ;
if ( loopmillis > last_measure + MEASURE_INTERVAL ) {
last_measure = loopmillis ;
2021-03-14 16:04:24 +00:00
updateVBat ( ) ; //also update vbat reading
2021-03-05 18:49:53 +00:00
//Serial.print("reading=");
2021-02-22 19:03:08 +00:00
weight_current = 0 ;
2021-02-21 16:35:18 +00:00
if ( scale . wait_ready_timeout ( 1000 ) ) { //for non blocking mode
weight_read_pos + + ;
weight_read_pos % = READING_FILTER_SIZE ;
weight_current = scale . get_units ( 1 ) ;
weight_read [ weight_read_pos ] = weight_current ; //one reading takes 91ms
} else {
Serial . println ( " HX711 not found. " ) ;
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " HX711 not found " ) ; //can be done in main loop
2021-02-21 16:35:18 +00:00
}
2021-03-05 20:33:28 +00:00
weight_filtered = getFilteredWeight ( ) ;
spread = getWeightSpread ( ) ;
2021-02-21 16:35:18 +00:00
2021-03-05 18:49:53 +00:00
//Serial.println(weight_current);
//Serial.print("spread="); Serial.println(spread,3);
2021-02-21 16:35:18 +00:00
2021-03-16 19:45:14 +00:00
# define MAXSPREAD 0.2 //in kg
if ( spread < MAXSPREAD ) { //if reading is stable
if ( weight_filtered < weight_tare ) { //new min
weight_tare = weight_filtered ;
update_display = true ;
Serial . print ( " new tare= " ) ; Serial . println ( weight_tare , 3 ) ;
last_display_blink = loopmillis ; //blink
}
if ( weight_filtered > weight_max ) { //new max
weight_max = weight_filtered ;
update_display = true ;
Serial . print ( " new max= " ) ; Serial . println ( weight_max , 3 ) ;
last_display_blink = loopmillis ; //blink
}
2021-03-16 19:59:29 +00:00
} else {
last_weightchange = loopmillis ;
2021-03-16 19:45:14 +00:00
}
2021-02-21 16:35:18 +00:00
2021-03-16 19:39:56 +00:00
weight_updated = true ;
2021-02-21 16:35:18 +00:00
2021-03-16 19:39:56 +00:00
}
# define STAYONTIME_AFTER_SENT 5000
2021-03-16 19:59:29 +00:00
# define STAYONTIME_IDLE 20000 //how long to stay on (ms) after no change in weight detected
if ( millis ( ) > MAXONTIME | | ( weight_sent & & millis ( ) > weight_sent_time + STAYONTIME_AFTER_SENT ) | | millis ( ) > last_weightchange + STAYONTIME_IDLE ) {
2021-03-16 19:39:56 +00:00
powerOff ( ) ;
}
if ( ( loopmillis > last_displayupdate + DISPLAYUPDATEINTERVAL ) | ( update_display & & ( loopmillis > last_displayupdate + DISPLAYUPDATEINTERVAL_MIN ) ) ) {
last_displayupdate = loopmillis ;
update_display = false ; //reset flag
2021-03-16 19:45:14 +00:00
if ( ( loopmillis > = last_new_display_custom ) & & ( loopmillis < last_new_display_custom + display_custom_duration ) ) { //custom display message
2021-03-16 19:39:56 +00:00
display . setBrightness ( displaybrightness , true ) ; //enable display
display . setSegments ( display_custom ) ;
2021-03-16 19:45:14 +00:00
} else { //normale weight display
2021-03-16 19:59:29 +00:00
displayNumber ( weight_filtered - weight_tare ) ;
2021-03-16 19:39:56 +00:00
display . setSegments ( display_data ) ;
if ( ( loopmillis > = last_display_blink ) & & ( loopmillis < last_display_blink + display_blink_duration ) ) {
2021-03-16 19:59:29 +00:00
display . setBrightness ( 2 , true ) ; //dimmed
2021-03-16 19:39:56 +00:00
} else {
display . setBrightness ( displaybrightness , true ) ;
}
}
}
/*
scale . power_down ( ) ; // put the ADC in sleep mode
delay ( 5000 ) ;
scale . power_up ( ) ; */
Homie . loop ( ) ;
}
void loopHandler ( ) {
unsigned long loopmillis = millis ( ) ;
if ( weight_updated ) {
weight_updated = false ;
2021-03-16 19:45:14 +00:00
2021-02-21 16:35:18 +00:00
if ( ! weight_sent ) {
if ( weight_max - weight_tare > MIN_WEIGHT_DIFFERENCE ) {
2021-03-14 16:04:24 +00:00
if ( Homie . getMqttClient ( ) . connected ( ) ) {
sendWeight ( weight_max - weight_tare ) ;
} else {
Serial . println ( " Cannot send weight because mqtt not connected! " ) ;
}
2021-03-05 19:11:19 +00:00
update_display = true ;
2021-02-21 16:35:18 +00:00
}
}
2021-03-14 16:04:24 +00:00
if ( ! vbatSent & & loopmillis > 10000 ) { //send voltage some time after turn on
if ( Homie . getMqttClient ( ) . connected ( ) ) {
sendVBat ( ) ;
vbatSent = true ;
} else {
Serial . println ( " Cannot send vbat because mqtt not connected! " ) ;
}
}
2021-02-21 16:35:18 +00:00
}
2021-03-14 16:04:24 +00:00
if ( Homie . getMqttClient ( ) . connected ( ) & & livesend & & ( millis ( ) > last_mqtt_send + MQTT_SENDINTERVALL ) ) {
2021-02-22 19:03:08 +00:00
last_mqtt_send = millis ( ) ;
2021-02-22 19:24:50 +00:00
//float weight_filtered=getFilteredWeight();
2021-02-22 19:03:08 +00:00
float spread = getWeightSpread ( ) ;
char charBuf [ 10 ] ;
dtostrf ( weight_current , 4 , 3 , charBuf ) ;
scaleNode . setProperty ( " raw " ) . send ( charBuf ) ;
dtostrf ( spread , 4 , 3 , charBuf ) ;
scaleNode . setProperty ( " spread " ) . send ( charBuf ) ;
dtostrf ( weight_max - weight_tare , 4 , 3 , charBuf ) ;
scaleNode . setProperty ( " max " ) . send ( charBuf ) ; //filtered and auto tared
}
2021-02-18 21:10:39 +00:00
2021-02-21 16:35:18 +00:00
}
int sort_desc ( const void * cmp1 , const void * cmp2 ) //compare function for qsort
{
float a = * ( ( float * ) cmp1 ) ;
float b = * ( ( float * ) cmp2 ) ;
return a > b ? - 1 : ( a < b ? 1 : 0 ) ;
}
float getFilteredWeight ( ) {
float copied_values [ READING_FILTER_SIZE ] ;
for ( int i = 0 ; i < READING_FILTER_SIZE ; i + + ) {
copied_values [ i ] = weight_read [ i ] ; //TODO: maybe some value filtering/selection here
}
float copied_values_length = sizeof ( copied_values ) / sizeof ( copied_values [ 0 ] ) ;
qsort ( copied_values , copied_values_length , sizeof ( copied_values [ 0 ] ) , sort_desc ) ;
float mean = copied_values [ READING_FILTER_SIZE / 2 ] ;
for ( uint8_t i = 1 ; i < = MEANVALUECOUNT ; i + + ) {
mean + = copied_values [ READING_FILTER_SIZE / 2 - i ] + copied_values [ READING_FILTER_SIZE / 2 + i ] ; //add two values around center
}
mean / = ( 1 + MEANVALUECOUNT * 2 ) ;
return mean ;
}
float getWeightSpread ( ) { //absolute difference between lowest and highest value in buffer
float copied_values [ READING_FILTER_SIZE ] ;
for ( int i = 0 ; i < READING_FILTER_SIZE ; i + + ) {
copied_values [ i ] = weight_read [ i ] ; //TODO: maybe some value filtering/selection here
}
float copied_values_length = sizeof ( copied_values ) / sizeof ( copied_values [ 0 ] ) ;
qsort ( copied_values , copied_values_length , sizeof ( copied_values [ 0 ] ) , sort_desc ) ;
float diff = copied_values [ 0 ] - copied_values [ READING_FILTER_SIZE - 1 ] ;
if ( diff < 0 ) { //abs for float
diff * = - 1 ;
}
return diff ;
}
void sendWeight ( float w ) {
char charBuf [ 10 ] ;
dtostrf ( w , 4 , 3 , charBuf ) ;
scaleNode . setProperty ( " human " ) . send ( charBuf ) ;
weight_sent = true ;
weight_sent_time = millis ( ) ;
Serial . print ( " Weight sent= " ) ; Serial . println ( w , 3 ) ;
2021-02-22 18:34:18 +00:00
}
bool cmdHandler ( const HomieRange & range , const String & value ) {
if ( range . isRange ) {
return false ; //if range is given but index is not in allowed range
}
Homie . getLogger ( ) < < " cmd " < < " : " < < value < < endl ;
//boolean value
2021-02-22 19:15:25 +00:00
if ( value = = " reset " ) { //tares and resets calibration value. needed to prepare for calibration
2021-02-22 18:34:18 +00:00
if ( scale . wait_ready_timeout ( 1000 ) ) { //for non blocking mode
2021-02-22 19:15:25 +00:00
scale . set_scale ( ) ;
2021-02-22 18:34:18 +00:00
scale . tare ( ) ;
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " tared " ) ;
2021-02-22 18:34:18 +00:00
} else {
Serial . println ( " HX711 not found. " ) ;
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " HX711 not found " ) ;
2021-02-22 18:34:18 +00:00
}
2021-02-22 19:24:50 +00:00
} else if ( value = = " calibrate " ) { //get raw value. use "reset" first. then adc to get value for calibration to enter in SCALE_CALIBRATION
2021-02-22 18:34:18 +00:00
if ( scale . wait_ready_timeout ( 1000 ) ) { //for non blocking mode
2021-02-22 19:39:44 +00:00
long _units = scale . get_units ( 10 ) ; //if set_scale was called with no parameter before, get_units has not decimals
2021-02-22 19:24:50 +00:00
char charBuf [ 13 ] ;
2021-02-22 19:39:44 +00:00
dtostrf ( _units , 2 , 1 , charBuf ) ;
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( charBuf ) ;
2021-02-22 18:34:18 +00:00
} else {
Serial . println ( " HX711 not found. " ) ;
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " HX711 not found " ) ;
2021-02-22 18:34:18 +00:00
}
2021-02-22 19:15:25 +00:00
} else if ( value = = " live " ) {
2021-02-22 19:03:08 +00:00
livesend = ! livesend ;
if ( livesend ) {
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " live data enabled " ) ;
2021-02-22 19:03:08 +00:00
} else {
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " live data disabled " ) ;
2021-02-22 19:03:08 +00:00
}
2021-03-14 16:04:24 +00:00
} else if ( value = = " vbat " ) {
sendVBat ( ) ;
2021-02-22 19:15:25 +00:00
} else if ( value = = " off " ) {
2021-02-22 18:34:18 +00:00
powerOff ( ) ;
2021-03-14 16:04:24 +00:00
hardwareNode . setProperty ( " cmd " ) . send ( " shutting down " ) ;
2021-02-22 18:34:18 +00:00
} else {
Homie . getLogger ( ) < < " cmd not recognized " < < endl ;
return false ;
}
return true ;
}
2021-03-05 20:33:28 +00:00
bool displayNodeHandler ( const HomieRange & range , const String & value ) {
if ( range . isRange ) {
return false ; //if range is given but index is not in allowed range
}
Homie . getLogger ( ) < < " displayset " < < " : " < < value < < endl ;
if ( value . length ( ) ! = 8 * 4 ) { //treat as number to show
displayNumber ( value . toFloat ( ) ) ;
for ( uint8_t i = 0 ; i < 4 ; i + + ) {
display_custom [ i ] = display_data [ i ] ;
}
} else {
uint8_t number = 0 ;
for ( uint8_t i = 0 ; i < value . length ( ) ; i + + ) // for every character in the string strlen(s) returns the length of a char array
{
number * = 2 ; // double the result so far
if ( value [ i ] = = ' 1 ' ) {
number + + ; //add 1 if needed
Serial . print ( " 1( " ) ; Serial . print ( i ) ; Serial . print ( " ) " ) ;
}
if ( ( i + 1 ) % 8 = = 0 & & i ! = 0 ) { //was the last bit
display_custom [ i / 8 ] = number ; //use this number
Serial . print ( " -> " ) ; Serial . print ( i / 8 ) ; Serial . print ( " = " ) ; Serial . println ( number ) ;
number = 0 ; //reset number for next byte
}
}
}
last_new_display_custom = millis ( ) ; //save time when message arrived
return true ;
}
2021-02-22 18:34:18 +00:00
void powerOff ( ) {
2021-03-05 18:58:50 +00:00
Serial . println ( " Turning Off " ) ;
Serial . flush ( ) ;
2021-02-22 18:34:18 +00:00
delay ( 100 ) ;
digitalWrite ( PIN_SELFENABLE , LOW ) ;
2021-03-05 19:00:16 +00:00
}
void displayNumber ( float numberdisplay ) {
uint8_t displayresolution = 3 ; //how many digits after dot
bool _negative = false ;
if ( numberdisplay < 0 ) {
numberdisplay * = - 1 ;
_negative = true ;
}
if ( ( numberdisplay > 999.9 ) | ( displayresolution = = 0 ) ) {
display . showNumberDec ( ( int ) ( numberdisplay + 0.5 ) , false ) ; //just diplay number
} else {
uint8_t d1 = 0 ;
uint8_t d2 = 0 ;
uint8_t d3 = 0 ;
uint8_t d4 = 0 ;
if ( numberdisplay < 10 & & displayresolution > = 3 ) { // 5.241, 0.005 etc.
int _number = ( int ) ( numberdisplay * 1000 + 0.5 ) ; //in 1000th kg rounded
d1 = _number % 10 ;
d2 = ( _number / 10 ) % 10 ;
d3 = ( _number / 100 ) % 10 ;
d4 = ( _number / 1000 ) % 10 ;
display_data [ 3 ] = display . encodeDigit ( d1 ) ; //rightmost digit
display_data [ 2 ] = display . encodeDigit ( d2 ) ;
display_data [ 1 ] = display . encodeDigit ( d3 ) ;
display_data [ 0 ] = display . encodeDigit ( d4 ) ; //leftmost digit
display_data [ 0 ] | = SEG_DP ; //add decimal point after left most digit
} else if ( numberdisplay < 100 & & displayresolution > = 2 ) { //10.24, 99.20
int _number = ( int ) ( numberdisplay * 100 + 0.5 ) ; //in 100th kg rounded
d1 = _number % 10 ;
d2 = ( _number / 10 ) % 10 ;
d3 = ( _number / 100 ) % 10 ;
d4 = ( _number / 1000 ) % 10 ;
display_data [ 3 ] = display . encodeDigit ( d1 ) ; //rightmost digit
display_data [ 2 ] = display . encodeDigit ( d2 ) ;
display_data [ 1 ] = display . encodeDigit ( d3 ) ;
display_data [ 1 ] | = SEG_DP ; //add decimal point after second digit from the left
display_data [ 0 ] = display . encodeDigit ( d4 ) ; //leftmost digit
if ( d4 = = 0 ) { //number smaller than 1000
display_data [ 0 ] = { 0 } ; //turn off left segment
}
} else if ( numberdisplay < 1000 & & displayresolution > = 1 ) //100.0, 999.9
{
int _number = ( int ) ( numberdisplay * 10 + 0.5 ) ; //in 10th kg rounded
d1 = _number % 10 ;
d2 = ( _number / 10 ) % 10 ;
d3 = ( _number / 100 ) % 10 ;
d4 = ( _number / 1000 ) % 10 ;
display_data [ 3 ] = display . encodeDigit ( d1 ) ; //rightmost digit
display_data [ 2 ] = display . encodeDigit ( d2 ) ;
display_data [ 2 ] | = SEG_DP ; //add decimal point after second digit from the right
display_data [ 1 ] = display . encodeDigit ( d3 ) ;
display_data [ 0 ] = display . encodeDigit ( d4 ) ; //leftmost digit
if ( d4 = = 0 ) { //number smaller than 1000
display_data [ 0 ] = { 0 } ; //turn off left segment
if ( d3 = = 0 ) { //number smaller than 100
display_data [ 1 ] = { 0 } ; //turn off 2nd from left segment
}
}
}
if ( _negative ) { //show negative number by using rightmost dot
display_data [ 3 ] | = SEG_DP ;
}
2021-03-05 20:33:28 +00:00
2021-03-05 19:00:16 +00:00
}
2021-03-14 16:04:24 +00:00
}
float getVBat ( ) { //get filtered vbat value
return mapFloat ( vbat_raw_filtered , vbat_calib1_adc , vbat_calib2_adc , vbat_calib1_voltage , vbat_calib2_voltage ) ; //2-point mapping adc -> voltage;
}
void updateVBat ( ) { //continuous update for filtering
float vbat_filter = 0.95 ; //the closer to 1 the higher the filtering. 0 means no filtering
if ( vbat_raw_filtered < 0 ) { //at first reading (vbat_raw_filtered is initialized with value <0)
vbat_filter = 0 ; //use first reading with 100%
}
vbat_raw_filtered = vbat_raw_filtered * vbat_filter + analogRead ( PIN_VBAT ) * ( 1.0 - vbat_filter ) ;
}
void sendVBat ( ) {
char charBuf [ 10 ] ;
dtostrf ( vbat_raw_filtered , 1 , 0 , charBuf ) ;
hardwareNode . setProperty ( " vbatraw " ) . send ( charBuf ) ;
Serial . print ( " vbatraw= " ) ; Serial . println ( vbat_raw_filtered ) ;
dtostrf ( getVBat ( ) , 4 , 3 , charBuf ) ;
hardwareNode . setProperty ( " vbat " ) . send ( charBuf ) ;
Serial . print ( " vbat= " ) ; Serial . println ( getVBat ( ) , 3 ) ;
}
float mapFloat ( float x , float in_min , float in_max , float out_min , float out_max )
{
return ( x - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min ;
2021-02-18 21:10:39 +00:00
}