FOSSASAT-1B
power_control.cpp
1 #include "power_control.h"
2 
3 powerConfigBits_t powerConfigBits = {
4  .lowPowerModeActive = LOW_POWER_MODE_ACTIVE,
5  .lowPowerModeEnabled = LOW_POWER_MODE_ENABLED,
6  .mpptTempSwitchEnabled = MPPT_TEMP_SWITCH_ENABLED,
7  .mpptKeepAliveEnabled = MPPT_KEEP_ALIVE_ENABLED,
8  .transmitEnabled = TRANSMIT_ENABLED
9 };
10 
12  .bits = powerConfigBits
13 };
14 
16  powerConfig.val = Persistent_Storage_Read<uint8_t>(EEPROM_POWER_CONFIG_ADDR);
17 }
18 
20  Persistent_Storage_Write<uint8_t>(EEPROM_POWER_CONFIG_ADDR, powerConfig.val);
21 }
22 
23 void Power_Control_Charge(bool charge) {
24  FOSSASAT_VERBOSE_PRINT(F("MPPT "));
25  FOSSASAT_VERBOSE_PRINTLN(charge);
26 
28  if(powerConfig.bits.mpptKeepAliveEnabled) {
29  // force MPPT to float regardless of anything else
30  FOSSASAT_VERBOSE_PRINTLN('K');
31  pinMode(DIGITAL_OUT_MPPT_PIN, INPUT);
32  } else if((Pin_Interface_Read_Temperature(BATTERY_TEMP_SENSOR_ADDR) < BATTERY_TEMPERATURE_LIMIT) && powerConfig.bits.mpptTempSwitchEnabled) {
33  // force MPPT low, only if temperature switch is enabled
34  FOSSASAT_VERBOSE_PRINTLN('L');
35  pinMode(DIGITAL_OUT_MPPT_PIN, OUTPUT);
36  digitalWrite(DIGITAL_OUT_MPPT_PIN, LOW);
37  } else if(charge){
38  // set MPPT to float
39  pinMode(DIGITAL_OUT_MPPT_PIN, INPUT);
40  } else {
41  // set MPPT to low
42  pinMode(DIGITAL_OUT_MPPT_PIN, OUTPUT);
43  digitalWrite(DIGITAL_OUT_MPPT_PIN, LOW);
44  }
45 }
46 
48  // sleep interval in ms (default for battery > 3.7 V)
49  uint32_t interval = 0;
50 
51  #ifdef ENABLE_INTERVAL_CONTROL
52  // get battery voltage
53  float batt = Power_Control_Get_Battery_Voltage();
54 
55  if(batt > 4.05f) {
56  interval = (uint32_t)20 * (uint32_t)1000;
57  } else if(batt > 4.0f) {
58  interval = (uint32_t)35 * (uint32_t)1000;
59  } else if(batt > 3.9f) {
60  interval = (uint32_t)100 * (uint32_t)1000;
61  } else if(batt > 3.8f) {
62  interval = (uint32_t)160 * (uint32_t)1000;
63  } else if(batt > 3.7f) {
64  interval = (uint32_t)180 * (uint32_t)1000;
65  } else {
66  interval = (uint32_t)240 * (uint32_t)1000;
67  }
68  #endif
69 
70  return(interval);
71 }
72 
73 void Power_Control_Delay(uint32_t ms, bool sleep, bool sleepRadio) {
74  if(ms == 0) {
75  return;
76  }
77 
78  // calculate number of required loops (rounded up)
79  float numLoops = 0.5f;
80  if(sleep) {
81  numLoops += (float)ms / 500.0;
82  } else {
83  numLoops += (float)ms / 50.0;
84  }
85 
86  // set radio to sleep
87  if(sleepRadio) {
88  radio.sleep();
89  }
90 
91  // perform all loops
92  for(uint32_t i = 0; i < (uint32_t)numLoops; i++) {
94  if(sleep) {
95  LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF);
96  } else {
97  delay(50);
98  }
99 
100  }
101 
102  // wake up radio
103  if(sleepRadio) {
104  radio.standby();
105  }
106 }
107 
109  ina.begin(INA_ADDR);
110  ina.configure(INA226_AVERAGES_1, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
111  ina.calibrate(INA_RSHUNT, INA_MAX_CURRENT);
112 }
113 
115  // attempt to read manufacturer ID register
116  Wire.beginTransmission(INA_ADDR);
117  Wire.write(INA_REG_MANUFACTURER_ID);
118  Wire.endTransmission();
119  delay(1);
120 
121  // try to read
122  Wire.requestFrom((uint8_t)INA_ADDR, (uint8_t)2);
123  if(Wire.available() != 2) {
124  return(false);
125  }
126 
127  // check value
128  uint8_t vha = Wire.read();
129  uint8_t vla = Wire.read();
130  uint16_t value = vha << 8 | vla;
131 
132  if(value != INA_MANUFACTURER_ID) {
133  return(false);
134  }
135 
136  return(true);
137 }
138 
140  // try to switch MPPT off (may be overridden by MPPT keep alive)
141  Power_Control_Charge(false);
142 
143  // get voltage
144  float val = -999;
146  val = ina.readBusVoltage();
147  }
148 
149  // try to switch MPPT on (may be overridden by temperature check)
150  Power_Control_Charge(true);
151 
152  return(val);
153 }
154 
157  return(-999.0);
158  }
159  return(ina.readBusVoltage());
160 }
161 
164  return(-999.0);
165  }
166  return(ina.readShuntCurrent());
167 }
168 
170  // load power configuration from EEPROM
172 
173  // check battery voltage
174  bool checkPassed = true;
175  if((Power_Control_Get_Battery_Voltage() <= BATTERY_VOLTAGE_LIMIT) && powerConfig.bits.lowPowerModeEnabled) {
176  // activate low power mode
177  powerConfig.bits.lowPowerModeActive = 1;
178  checkPassed = false;
179  } else {
180  // deactivate low power mode
181  powerConfig.bits.lowPowerModeActive = 0;
182  checkPassed = true;
183  }
184 
185  // save power configuration to EEPROM
187  return(checkPassed);
188 }
#define BATTERY_VOLTAGE_LIMIT
Definition: configuration.h:72
void Power_Control_Delay(uint32_t ms, bool sleep, bool sleepRadio=false)
This function delays the program execution for the given number of milliseconds, while maintaining th...
#define INA_ADDR
#define INA_RSHUNT
bool Power_Control_Check_Battery_Limit()
Checks whether battery voltage is below low power limit. Will enable low power mode if that is the ca...
void Pin_Interface_Watchdog_Heartbeat(bool manageBattery=false)
This function toggles the signal to the watchdog and writes it to the pin.
#define MPPT_KEEP_ALIVE_ENABLED
float Power_Control_Get_Charging_Current()
Gets the amperage which is being provided to the battery.
float Pin_Interface_Read_Temperature(uint8_t sensorAddr)
This function reads the TMP100&#39;s value from its wire address.
#define TRANSMIT_ENABLED
void Power_Control_Save_Configuration()
Saves the configuration bytes from RAM into EEPROM.
float Power_Control_Get_Battery_Voltage()
Get the battery voltage by switching the MPPT off and then on again after reading is taken...
void Power_Control_Load_Configuration()
Load the configuration bytes from the EEPROM into RAM.
INA226 ina
#define LOW_POWER_MODE_ACTIVE
Definition: configuration.h:98
void Power_Control_Charge(bool charge)
This function ensures that the battery is charging. "set MPPT to input which enables battery charging...
#define INA_MANUFACTURER_ID
#define INA_REG_MANUFACTURER_ID
powerConfig_t powerConfig
The current power configuration settings.
#define EEPROM_POWER_CONFIG_ADDR
Start AddressEnd Address 0x00010x0001
Power configuration strutcture, each entry is one bit long. Total 1 byte, lowPowerModeActive is the l...
Definition: power_control.h:15
#define INA_MAX_CURRENT
#define LOW_POWER_MODE_ENABLED
Definition: configuration.h:99
bool Power_Control_INA226_Check()
Check that the INA2256 is valid.
uint32_t Power_Control_Get_Sleep_Interval()
Get the amount of seconds to sleep for given the battery voltage.
float Power_Control_Get_Charging_Voltage()
Gets the charging voltage (from the solar panels) by not switching the MPPT off and taking an INA226 ...
Union to quickly access power configuration bits or the entire single-byte value. ...
Definition: power_control.h:26
#define BATTERY_TEMP_SENSOR_ADDR
#define MPPT_TEMP_SWITCH_ENABLED
void Power_Control_Setup_INA226()
Initializes the INA226 current sensor.
#define BATTERY_TEMPERATURE_LIMIT
Definition: configuration.h:74
#define DIGITAL_OUT_MPPT_PIN
SX1268 radio