Add power management sensor INA226

This commit is contained in:
norbert-walter 2022-03-24 17:02:15 +01:00
parent 9150552b34
commit 55c69e37e5
5 changed files with 167 additions and 133 deletions

View File

@ -377,10 +377,14 @@ int AMS_5600::readOneByte(int in_adr)
Wire.write(in_adr); Wire.write(in_adr);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom(_ams5600_Address, (uint8_t) 1); Wire.requestFrom(_ams5600_Address, (uint8_t) 1);
/*
while (Wire.available() == 0) while (Wire.available() == 0)
; ;
retVal = Wire.read(); retVal = Wire.read();
*/
if(Wire.available() >= 1){
retVal = Wire.read();
}
return retVal; return retVal;
} }
@ -416,11 +420,20 @@ word AMS_5600::readTwoBytesTogether(int addr_in)
Wire.write(addr_in); Wire.write(addr_in);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom(_ams5600_Address, (uint8_t) 2); Wire.requestFrom(_ams5600_Address, (uint8_t) 2);
/*
while (Wire.available() < 2) while (Wire.available() < 2)
; ;
int highByte = Wire.read(); int highByte = Wire.read();
int lowByte = Wire.read(); int lowByte = Wire.read();
*/
int highByte = 0;
int lowByte = 0;
if (Wire.available() >= 2){
highByte = Wire.read();
lowByte = Wire.read();
}
// in case newer version of IC used the same address to // in case newer version of IC used the same address to
// store something else, get only the 3 bits // store something else, get only the 3 bits

View File

@ -22,11 +22,10 @@
// AS5600 // AS5600
#define AS5600_I2C_ADDR 0x36 // Addr. 0x36 (fix) #define AS5600_I2C_ADDR 0x36 // Addr. 0x36 (fix)
// INA226 // INA226
#define SHUNT_VOLTAGE 0.75 // 75mV by max. current #define SHUNT_VOLTAGE 0.075 // Shunt voltage in V by max. current (75mV)
#define INA226_I2C_ADDR1 0x40 // Addr. 0x40 (fix) #define INA226_I2C_ADDR1 0x41 // Addr. 0x41 (fix A0 = 5V, A1 = GND) for battery
#define INA226_I2C_ADDR2 0x41 // Addr. 0x41 (fix) #define INA226_I2C_ADDR2 0x44 // Addr. 0x44 (fix A0 = GND, A1 = 5V) for solar panels
#define INA226_I2C_ADDR3 0x44 // Addr. 0x44 (fix) #define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
#define INA226_I2C_ADDR4 0x45 // Addr. 0x45 (fix)
// SPI (E-Ink display, Extern Bus) // SPI (E-Ink display, Extern Bus)
#define OBP_SPI_CS 5 #define OBP_SPI_CS 5
#define OBP_SPI_DC 17 #define OBP_SPI_DC 17

View File

@ -68,7 +68,7 @@ void sensorTask(void *param){
Adafruit_BMP085 bmp085; // Evironment sensor BMP085 and BMP180 Adafruit_BMP085 bmp085; // Evironment sensor BMP085 and BMP180
HTU21D sht21(HTU21D_RES_RH12_TEMP14); // Environment sensor SHT21 and HTU21 HTU21D sht21(HTU21D_RES_RH12_TEMP14); // Environment sensor SHT21 and HTU21
AMS_5600 as5600; // Rotation sensor AS5600 AMS_5600 as5600; // Rotation sensor AS5600
INA226 ina226_1(INA226_I2C_ADDR1);// Power management IC INA226 INA226 ina226_1(INA226_I2C_ADDR1);// Power management sensor INA226
// Init sensor stuff // Init sensor stuff
bool gps_ready = false; // GPS initialized and ready to use bool gps_ready = false; // GPS initialized and ready to use
@ -211,6 +211,7 @@ void sensorTask(void *param){
float shuntResistor = 1.0; // Default value for shunt resistor float shuntResistor = 1.0; // Default value for shunt resistor
float current = 10.0; // Default value for max. current float current = 10.0; // Default value for max. current
float corrFactor = 1; // Correction factor for fix calibration
if(String(powsensor1) == "INA226"){ if(String(powsensor1) == "INA226"){
if (!ina226_1.begin()){ if (!ina226_1.begin()){
@ -218,13 +219,15 @@ void sensorTask(void *param){
} }
else{ else{
api->getLogger()->logDebug(GwLog::LOG,"Modul 1 INA226 found"); api->getLogger()->logDebug(GwLog::LOG,"Modul 1 INA226 found");
shuntResistor = 0.075 / float(shunt1.toInt()); // Calculate shunt resisitor for max. shunt voltage 75mV shuntResistor = SHUNT_VOLTAGE / float(shunt1.toInt()); // Calculate shunt resisitor for max. shunt voltage 75mV
current = float(shunt1.toInt()); current = float(shunt1.toInt());
api->getLogger()->logDebug(GwLog::LOG,"Calibation INA226, Imax:%3.0fA Rs:%7.5fOhm Us:0.075V", current, shuntResistor); api->getLogger()->logDebug(GwLog::LOG,"Calibation INA226, Imax:%3.0fA Rs:%7.5fOhm Us:%5.3f", current, shuntResistor, SHUNT_VOLTAGE);
ina226_1.setMaxCurrentShunt(current, shuntResistor); // ina226_1.setMaxCurrentShunt(current, shuntResistor);
ina226_1.setMaxCurrentShunt(10, 0.01); // Calibration with fix values (because the original values outer range)
corrFactor = (current / 10) * (0.001 / shuntResistor) / (current / 100); // correction factor for fix calibration
sensors.batteryVoltage = ina226_1.getBusVoltage(); sensors.batteryVoltage = ina226_1.getBusVoltage();
sensors.batteryCurrent = ina226_1.getCurrent(); sensors.batteryCurrent = ina226_1.getCurrent() * corrFactor;
sensors.batteryPower = ina226_1.getPower(); sensors.batteryPower = ina226_1.getPower() * corrFactor;
INA226_1_ready = true; INA226_1_ready = true;
} }
} }
@ -262,128 +265,144 @@ void sensorTask(void *param){
} }
// Read sensors and set values in sensor data // Read sensors and set values in sensor data
// Send supplay voltage value all 1s // Send supplay voltage value all 1s
if(millis() > starttime5 + 1000){ if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
starttime5 = millis(); starttime5 = millis();
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
// Send to NMEA200 bus
if(!isnan(sensors.batteryVoltage)){
SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, N2kDoubleNA, N2kDoubleNA, 1);
api->sendN2kMessage(N2kMsg);
}
}
// Send data from environment sensor all 1s
if(millis() > starttime6 + 2000){
starttime6 = millis();
unsigned char TempSource = 2; // Inside temperature
unsigned char PressureSource = 0; // Atmospheric pressure
unsigned char HumiditySource=0; // Inside humidity
if(envsensor == "BME280" && BME280_ready == true){
sensors.airTemperature = bme280.readTemperature();
sensors.airPressure = bme280.readPressure()/100;
sensors.airHumidity = bme280.readHumidity();
// Send to NMEA200 bus // Send to NMEA200 bus
if(!isnan(sensors.batteryVoltage)){ if(!isnan(sensors.airTemperature)){
SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, N2kDoubleNA, N2kDoubleNA, 1); SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airHumidity)){
SetN2kPGN130313(N2kMsg, 0, 0,(tN2kHumiditySource) HumiditySource, sensors.airHumidity, N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg); api->sendN2kMessage(N2kMsg);
} }
} }
else if(envsensor == "BMP280" && BMP280_ready == true){
// Send data from environment sensor all 1s sensors.airTemperature = bmp280.readTemperature();
if(millis() > starttime6 + 2000){ sensors.airPressure =bmp280.readPressure()/100;
starttime6 = millis(); // Send to NMEA200 bus
unsigned char TempSource = 2; // Inside temperature if(!isnan(sensors.airTemperature)){
unsigned char PressureSource = 0; // Atmospheric pressure SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
unsigned char HumiditySource=0; // Inside humidity api->sendN2kMessage(N2kMsg);
if(envsensor == "BME280" && BME280_ready == true){
sensors.airTemperature = bme280.readTemperature();
sensors.airPressure = bme280.readPressure()/100;
sensors.airHumidity = bme280.readHumidity();
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airHumidity)){
SetN2kPGN130313(N2kMsg, 0, 0,(tN2kHumiditySource) HumiditySource, sensors.airHumidity, N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
} }
else if(envsensor == "BMP280" && BMP280_ready == true){ if(!isnan(sensors.airPressure)){
sensors.airTemperature = bmp280.readTemperature(); SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
sensors.airPressure =bmp280.readPressure()/100; api->sendN2kMessage(N2kMsg);
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
} }
else if((envsensor == "BMP085" || envsensor == "BMP180") && BMP180_ready == true){
sensors.airTemperature = bmp085.readTemperature();
sensors.airPressure =bmp085.readPressure()/100;
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
}
else if((envsensor == "SHT21" || envsensor == "HTU21") && SHT21_ready == true){
sensors.airHumidity = sht21.readCompensatedHumidity();
sensors.airHumidity = sht21.readTemperature();
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airHumidity)){
SetN2kPGN130313(N2kMsg, 0, 0,(tN2kHumiditySource) HumiditySource, sensors.airHumidity, N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
}
} }
else if((envsensor == "BMP085" || envsensor == "BMP180") && BMP180_ready == true){
sensors.airTemperature = bmp085.readTemperature();
sensors.airPressure =bmp085.readPressure()/100;
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
}
else if((envsensor == "SHT21" || envsensor == "HTU21") && SHT21_ready == true){
sensors.airHumidity = sht21.readCompensatedHumidity();
sensors.airHumidity = sht21.readTemperature();
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airHumidity)){
SetN2kPGN130313(N2kMsg, 0, 0,(tN2kHumiditySource) HumiditySource, sensors.airHumidity, N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
}
}
// Send rotation angle all 500ms // Send rotation angle all 500ms
if(millis() > starttime7 + 500){ if(millis() > starttime7 + 500){
starttime7 = millis(); starttime7 = millis();
double rotationAngle=0; double rotationAngle=0;
if(String(rotsensor) == "AS5600" && AS5600_ready == true && as5600.detectMagnet() == 1){ if(String(rotsensor) == "AS5600" && AS5600_ready == true && as5600.detectMagnet() == 1){
rotationAngle = as5600.getRawAngle() * 0.087; // 0...4095 segments = 0.087 degree rotationAngle = as5600.getRawAngle() * 0.087; // 0...4095 segments = 0.087 degree
// Offset correction // Offset correction
if(rotoffset >= 0){ if(rotoffset >= 0){
rotationAngle = rotationAngle + rotoffset; rotationAngle = rotationAngle + rotoffset;
rotationAngle = int(rotationAngle) % 360; rotationAngle = int(rotationAngle) % 360;
}
else{
rotationAngle = rotationAngle + 360 + rotoffset;
rotationAngle = int(rotationAngle) % 360;
}
// Send to NMEA200 bus as rudder angle values
if(!isnan(rotationAngle) && String(rotfunction) == "Rudder"){
double rudder = rotationAngle - 180; // Center position is 180°
// Rudder limits to +/-45°
if(rudder < -45){
rudder = -45;
}
if(rudder > 45){
rudder = 45;
}
SetN2kRudder(N2kMsg, DegToRad(rudder), 0, N2kRDO_NoDirectionOrder, PI);
api->sendN2kMessage(N2kMsg);
}
// Send to NMEA200 bus as wind angle values
if(!isnan(rotationAngle) && String(rotfunction) == "Wind"){
SetN2kWindSpeed(N2kMsg, 1, 0, DegToRad(rotationAngle), N2kWind_Apprent);
api->sendN2kMessage(N2kMsg);
}
// Send to NMEA200 bus as trim angle values in [%]
if(!isnan(rotationAngle) && (String(rotfunction) == "Mast" || String(rotfunction) == "Keel" || String(rotfunction) == "Trim" || String(rotfunction) == "Boom")){
int trim = rotationAngle * 100 / 360; // 0...360° -> 0...100%
SetN2kTrimTab(N2kMsg, trim, trim);
api->sendN2kMessage(N2kMsg);
}
sensors.rotationAngle = DegToRad(rotationAngle); // Data take over to page
sensors.validRotAngle = true; // Valid true, magnet present
} }
else{ else{
sensors.rotationAngle = 0; // Center position 0° rotationAngle = rotationAngle + 360 + rotoffset;
sensors.validRotAngle = false; // Valid false, magnet missing rotationAngle = int(rotationAngle) % 360;
} }
// Send to NMEA200 bus as rudder angle values
if(!isnan(rotationAngle) && String(rotfunction) == "Rudder"){
double rudder = rotationAngle - 180; // Center position is 180°
// Rudder limits to +/-45°
if(rudder < -45){
rudder = -45;
}
if(rudder > 45){
rudder = 45;
}
SetN2kRudder(N2kMsg, DegToRad(rudder), 0, N2kRDO_NoDirectionOrder, PI);
api->sendN2kMessage(N2kMsg);
}
// Send to NMEA200 bus as wind angle values
if(!isnan(rotationAngle) && String(rotfunction) == "Wind"){
SetN2kWindSpeed(N2kMsg, 1, 0, DegToRad(rotationAngle), N2kWind_Apprent);
api->sendN2kMessage(N2kMsg);
}
// Send to NMEA200 bus as trim angle values in [%]
if(!isnan(rotationAngle) && (String(rotfunction) == "Mast" || String(rotfunction) == "Keel" || String(rotfunction) == "Trim" || String(rotfunction) == "Boom")){
int trim = rotationAngle * 100 / 360; // 0...360° -> 0...100%
SetN2kTrimTab(N2kMsg, trim, trim);
api->sendN2kMessage(N2kMsg);
}
sensors.rotationAngle = DegToRad(rotationAngle); // Data take over to page
sensors.validRotAngle = true; // Valid true, magnet present
} }
else{
sensors.rotationAngle = 0; // Center position 0°
sensors.validRotAngle = false; // Valid false, magnet missing
}
}
// Send power management value all 1s
if(millis() > starttime8 + 1000 && (String(powsensor1) == "INA219" || String(powsensor1) == "INA226")){
starttime8 = millis();
if(String(powsensor1) == "INA226" && INA226_1_ready == true){
sensors.batteryVoltage = ina226_1.getBusVoltage();
sensors.batteryCurrent = ina226_1.getCurrent() * corrFactor;
sensors.batteryPower = ina226_1.getPower() * corrFactor;
}
// Send battery data to NMEA200 bus
if(!isnan(sensors.batteryVoltage) && !isnan(sensors.batteryCurrent)){
// SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, sensors.batteryCurrent, N2kDoubleNA, 1);
SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, sensors.batteryCurrent, sensors.batteryPower, 1);
api->sendN2kMessage(N2kMsg);
}
}
shared->setSensorData(sensors); shared->setSensorData(sensors);
} }

View File

@ -263,10 +263,10 @@
}, },
{ {
"name": "usePowSensor1", "name": "usePowSensor1",
"label": "Pow. Sensor 1", "label": "Bat. Sensor 1",
"type": "list", "type": "list",
"default": "off", "default": "off",
"description": "Use external power management sensor via I2C bus [off|INA219|INA226|]", "description": "Use external power management sensor via I2C bus for battery [off|INA219|INA226|]",
"list": [ "list": [
"off", "off",
"INA219", "INA219",
@ -282,13 +282,14 @@
"label": "Shunt Sensor 1", "label": "Shunt Sensor 1",
"type": "list", "type": "list",
"default": "10", "default": "10",
"description": "Shunt current value [10A|50A|100A|200A|300A|500A]", "description": "Shunt current value [10A|50A|100A|200A|300A|400A|500A]",
"list": [ "list": [
"10", "10",
"50", "50",
"100", "100",
"200", "200",
"300", "300",
"400",
"500" "500"
], ],
"category": "OBP60 Hardware", "category": "OBP60 Hardware",
@ -298,10 +299,10 @@
}, },
{ {
"name": "usePowSensor2", "name": "usePowSensor2",
"label": "Pow. Sensor 2", "label": "Solar Sensor 2",
"type": "list", "type": "list",
"default": "off", "default": "off",
"description": "Use external power management sensor via I2C bus [off|INA219|INA226|]", "description": "Use external power management sensor via I2C bus for solar panels [off|INA219|INA226|]",
"list": [ "list": [
"off", "off",
"INA219", "INA219",
@ -317,13 +318,14 @@
"label": "Shunt Sensor 2", "label": "Shunt Sensor 2",
"type": "list", "type": "list",
"default": "10", "default": "10",
"description": "Shunt current value [10A|50A|100A|200A|300A|500A]", "description": "Shunt current value [10A|50A|100A|200A|300A|400A|500A]",
"list": [ "list": [
"10", "10",
"50", "50",
"100", "100",
"200", "200",
"300", "300",
"400",
"500" "500"
], ],
"category": "OBP60 Hardware", "category": "OBP60 Hardware",
@ -333,10 +335,10 @@
}, },
{ {
"name": "usePowSensor3", "name": "usePowSensor3",
"label": "Pow. Sensor 3", "label": "Gen. Sensor 3",
"type": "list", "type": "list",
"default": "off", "default": "off",
"description": "Use external power management sensor via I2C bus [off|INA219|INA226|]", "description": "Use external power management sensor via I2C bus for generator [off|INA219|INA226|]",
"list": [ "list": [
"off", "off",
"INA219", "INA219",
@ -352,13 +354,14 @@
"label": "Shunt Sensor 3", "label": "Shunt Sensor 3",
"type": "list", "type": "list",
"default": "10", "default": "10",
"description": "Shunt current value [10A|50A|100A|200A|300A|500A]", "description": "Shunt current value [10A|50A|100A|200A|300A|400A|500A]",
"list": [ "list": [
"10", "10",
"50", "50",
"100", "100",
"200", "200",
"300", "300",
"400",
"500" "500"
], ],
"category": "OBP60 Hardware", "category": "OBP60 Hardware",

View File

@ -20,7 +20,7 @@ DECLARE_INITFUNCTION(OBP60Init);
// OBP60 Task // OBP60 Task
void OBP60Task(GwApi *param); void OBP60Task(GwApi *param);
DECLARE_USERTASK_PARAM(OBP60Task, 10000) // Need 10k RAM as stack size DECLARE_USERTASK_PARAM(OBP60Task, 15000) // Need 15k RAM as stack size
DECLARE_CAPABILITY(obp60,true); DECLARE_CAPABILITY(obp60,true);
#endif #endif