@ -54,6 +54,58 @@ class CSE7766Sensor : public BaseSensor {
return _inverted ;
}
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void expectedCurrent ( double expected ) {
if ( ( expected > 0 ) & & ( _current > 0 ) ) {
_ratioC = _ratioC * ( expected / _current ) ;
}
}
void expectedVoltage ( unsigned int expected ) {
if ( ( expected > 0 ) & & ( _voltage > 0 ) ) {
_ratioV = _ratioV * ( expected / _voltage ) ;
}
}
void expectedPower ( unsigned int expected ) {
if ( ( expected > 0 ) & & ( _active > 0 ) ) {
_ratioP = _ratioP * ( expected / _active ) ;
}
}
void setCurrentRatio ( double value ) {
_ratioC = value ;
} ;
void setVoltageRatio ( double value ) {
_ratioV = value ;
} ;
void setPowerRatio ( double value ) {
_ratioP = value ;
} ;
double getCurrentRatio ( ) {
return _ratioC ;
} ;
double getVoltageRatio ( ) {
return _ratioV ;
} ;
double getPowerRatio ( ) {
return _ratioP ;
} ;
void resetRatios ( ) {
_ratioC = _ratioV = _ratioP = 1.0 ;
}
void resetEnergy ( ) {
_energy = 0 ;
}
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ / Sensor API
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -65,9 +117,13 @@ class CSE7766Sensor : public BaseSensor {
if ( _serial ) delete _serial ;
_serial = new SoftwareSerial ( _pin_rx , SW_SERIAL_UNUSED_PIN , _inverted , 32 ) ;
_serial - > enableIntTx ( false ) ;
_serial - > begin ( CSE7766_BAUDRATE ) ;
if ( 1 = = _pin_rx ) {
Serial . begin ( CSE7766_BAUDRATE ) ;
} else {
_serial = new SoftwareSerial ( _pin_rx , SW_SERIAL_UNUSED_PIN , _inverted , 32 ) ;
_serial - > enableIntTx ( false ) ;
_serial - > begin ( CSE7766_BAUDRATE ) ;
}
_ready = true ;
_dirty = false ;
@ -77,7 +133,11 @@ class CSE7766Sensor : public BaseSensor {
/ / Descriptive name of the sensor
String description ( ) {
char buffer [ 28 ] ;
snprintf ( buffer , sizeof ( buffer ) , " CSE7766 @ SwSerial(%u,NULL) " , _pin_rx ) ;
if ( 1 = = _pin_rx ) {
snprintf ( buffer , sizeof ( buffer ) , " CSE7766 @ HwSerial " ) ;
} else {
snprintf ( buffer , sizeof ( buffer ) , " CSE7766 @ SwSerial(%u,NULL) " , _pin_rx ) ;
}
return String ( buffer ) ;
}
@ -137,11 +197,21 @@ class CSE7766Sensor : public BaseSensor {
void _process ( ) {
/ / Sample data :
/ / 55 5 A 02 E9 50 00 03 31 00 3 E 9 E 00 0 D 30 4F 44 F8 00 12 65 F1 81 76 72 ( w / load )
/ / F2 5 A 02 E9 50 00 03 2 B 00 3 E 9 E 02 D7 7 C 4F 44 F8 CF A5 5 D E1 B3 2 A B4 ( w / o load )
# if SENSOR_DEBUG
DEBUG_MSG ( " [SENSOR] CSE7766: _process: " ) ;
for ( byte i = 0 ; i < 24 ; i + + ) DEBUG_MSG ( " %02X " , _data [ i ] ) ;
DEBUG_MSG ( " \n " ) ;
# endif
/ / Checksum
if ( ! _checksum ( ) ) {
_error = SENSOR_ERROR_CRC ;
# if SENSOR_DEBUG
DEBUG_MSG_P ( PSTR ( " [SENSOR] CSE7766: Checksum error " ) ) ;
DEBUG_MSG ( " [SENSOR] CSE7766: Checksum error \n " ) ;
# endif
return ;
}
@ -150,7 +220,7 @@ class CSE7766Sensor : public BaseSensor {
if ( 0xAA = = _data [ 0 ] ) {
_error = SENSOR_ERROR_CALIBRATION ;
# if SENSOR_DEBUG
DEBUG_MSG_P ( PSTR ( " [SENSOR] CSE7766: Chip not calibrated " ) ) ;
DEBUG_MSG ( " [SENSOR] CSE7766: Chip not calibrated \n " ) ;
# endif
return ;
}
@ -158,39 +228,35 @@ class CSE7766Sensor : public BaseSensor {
if ( ( _data [ 0 ] & 0xFC ) > 0xF0 ) {
_error = SENSOR_ERROR_OTHER ;
# if SENSOR_DEBUG
if ( 0xF1 = = _data [ 0 ] & 0xF1 ) DEBUG_MSG_P ( PSTR ( " [SENSOR] CSE7766: Abnormal coefficient storage area " ) ) ;
if ( 0xF2 = = _data [ 0 ] & 0xF2 ) DEBUG_MSG_P ( PSTR ( " [SENSOR] CSE7766: Power cycle exceeded range " ) ) ;
if ( 0xF4 = = _data [ 0 ] & 0xF4 ) DEBUG_MSG_P ( PSTR ( " [SENSOR] CSE7766: Current cycle exceeded range " ) ) ;
if ( 0xF8 = = _data [ 0 ] & 0xF8 ) DEBUG_MSG_P ( PSTR ( " [SENSOR] CSE7766: Voltage cycle exceeded range " ) ) ;
if ( 0xF1 = = _data [ 0 ] & 0xF1 ) DEBUG_MSG ( " [SENSOR] CSE7766: Abnormal coefficient storage area \n " ) ;
if ( 0xF2 = = _data [ 0 ] & 0xF2 ) DEBUG_MSG ( " [SENSOR] CSE7766: Power cycle exceeded range \n " ) ;
if ( 0xF4 = = _data [ 0 ] & 0xF4 ) DEBUG_MSG ( " [SENSOR] CSE7766: Current cycle exceeded range \n " ) ;
if ( 0xF8 = = _data [ 0 ] & 0xF8 ) DEBUG_MSG ( " [SENSOR] CSE7766: Voltage cycle exceeded range \n " ) ;
# endif
return ;
}
/ / Calibration coefficients
if ( 0 = = _coefV ) {
_coefV = ( _data [ 2 ] < < 16 | _data [ 3 ] < < 8 | _data [ 4 ] ) / 100 ;
_coefV * = 100 ;
_coefC = ( _data [ 8 ] < < 16 | _data [ 9 ] < < 8 | _data [ 10 ] ) ;
_coefP = ( _data [ 14 ] < < 16 | _data [ 15 ] < < 8 | _data [ 16 ] ) / 1000 ;
_coefP * = 1000 ;
}
unsigned long _coefV = ( _data [ 2 ] < < 16 | _data [ 3 ] < < 8 | _data [ 4 ] ) ; / / 190770
unsigned long _coefC = ( _data [ 8 ] < < 16 | _data [ 9 ] < < 8 | _data [ 10 ] ) ; / / 16030
unsigned long _coefP = ( _data [ 14 ] < < 16 | _data [ 15 ] < < 8 | _data [ 16 ] ) ; / / 5195000
/ / Adj : this looks like a sampling report
uint8_t adj = _data [ 20 ] ;
uint8_t adj = _data [ 20 ] ; / / F1 11110001
/ / Calculate voltage
_voltage = 0 ;
if ( ( adj & 0x40 ) = = 0x40 ) {
unsigned long voltage_cycle = _data [ 5 ] < < 16 | _data [ 6 ] < < 8 | _data [ 7 ] ;
_voltage = _coefV / voltage_cycle / CSE7766_V2R ;
unsigned long voltage_cycle = _data [ 5 ] < < 16 | _data [ 6 ] < < 8 | _data [ 7 ] ; / / 817
_voltage = _ratioV * _ coefV / voltage_cycle / CSE7766_V2R ; / / 190700 / 817 = 233.41
}
/ / Calculate power
_active = 0 ;
if ( ( adj & 0x10 ) = = 0x10 ) {
if ( ( _data [ 0 ] & 0xF2 ) ! = 0xF2 ) {
unsigned long power_cycle = _data [ 17 ] < < 16 | _data [ 18 ] < < 8 | _data [ 19 ] ;
_active = _coefP / power_cycle / CSE7766_V1R / CSE7766_V2R ;
unsigned long power_cycle = _data [ 17 ] < < 16 | _data [ 18 ] < < 8 | _data [ 19 ] ; / / 4709
_active = _ratioP * _ coefP / power_cycle / CSE7766_V1R / CSE7766_V2R ; / / 5195000 / 4709 = 1103.20
}
}
@ -198,19 +264,17 @@ class CSE7766Sensor : public BaseSensor {
_current = 0 ;
if ( ( adj & 0x20 ) = = 0x20 ) {
if ( _active > 0 ) {
unsigned long current_cycle = _data [ 11 ] < < 16 | _data [ 12 ] < < 8 | _data [ 13 ] ;
_current = _coefC / current_cycle / CSE7766_V1R ;
unsigned long current_cycle = _data [ 11 ] < < 16 | _data [ 12 ] < < 8 | _data [ 13 ] ; / / 3376
_current = _ratioC * _ coefC / current_cycle / CSE7766_V1R ; / / 16030 / 3376 = 4.75
}
}
/ / Calculate energy
/*
static unsigned long cf_pulses_last = 0 ;
unsigned long cf_pulses = _data [ 21 ] < < 8 | _data [ 22 ] ;
unsigned long frequency = cf_pulses - cf_pulses_last ;
if ( 0 = = cf_pulses_last ) cf_pulses_last = cf_pulses ;
_energy + = ( cf_pulses - cf_pulses_last ) * ( float ) _coefP / 1000000.0 ;
cf_pulses_last = cf_pulses ;
_energy + = ( 100000 * frequency * _coefP ) ;
*/
}
@ -221,26 +285,35 @@ class CSE7766Sensor : public BaseSensor {
static unsigned char index = 0 ;
static unsigned long last = millis ( ) ;
while ( _serial - > available ( ) ) {
while ( _serial_ available ( ) ) {
/ / A 24 bytes message takes ~ 55 ms to go through at 4800 bps
/ / Reset counter if more than 1000 ms have passed since last byte .
if ( millis ( ) - last > CSE7766_SYNC_INTERVAL ) index = 0 ;
last = millis ( ) ;
uint8_t byte = _serial - > read ( ) ;
uint8_t byte = _serial_read ( ) ;
/ / first byte must be 0x55 or 0xF ?
if ( 0 = = index ) {
if ( ( 0x55 ! = byte ) & & ( byte < 0xF0 ) ) {
continue ;
}
/ / second byte in packet must be 0x5A
if ( ( 1 = = index ) & & ( 0xA5 ! = byte ) ) {
index = 0 ;
} else {
_data [ index + + ] = byte ;
if ( index > 23 ) {
_serial - > flush ( ) ;
break ;
/ / second byte must be 0x5A
} else if ( 1 = = index ) {
if ( 0x5A ! = byte ) {
index = 0 ;
continue ;
}
}
_data [ index + + ] = byte ;
if ( index > 23 ) {
_serial_flush ( ) ;
break ;
}
}
/ / Process packet
@ -253,6 +326,32 @@ class CSE7766Sensor : public BaseSensor {
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool _serial_available ( ) {
if ( 1 = = _pin_rx ) {
return Serial . available ( ) ;
} else {
return _serial - > available ( ) ;
}
}
void _serial_flush ( ) {
if ( 1 = = _pin_rx ) {
return Serial . flush ( ) ;
} else {
return _serial - > flush ( ) ;
}
}
uint8_t _serial_read ( ) {
if ( 1 = = _pin_rx ) {
return Serial . read ( ) ;
} else {
return _serial - > read ( ) ;
}
}
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned int _pin_rx = CSE7766_PIN ;
bool _inverted = CSE7766_PIN_INVERSE ;
SoftwareSerial * _serial = NULL ;
@ -262,9 +361,9 @@ class CSE7766Sensor : public BaseSensor {
double _current = 0 ;
double _energy = 0 ;
unsigned long _coefV = 0 ;
unsigned long _coefC = 0 ;
unsigned long _coefP = 0 ;
double _ratioV = 1. 0;
double _ratioC = 1. 0;
double _ratioP = 1. 0;
unsigned char _data [ 24 ] ;