forked from Damme/LandLord
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpowermgmt.c
executable file
·123 lines (112 loc) · 5.77 KB
/
powermgmt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <stdio.h>
#include "powermgmt.h"
#include "timers.h"
#define xDelay100 ((TickType_t)100 / portTICK_PERIOD_MS)
#define IS_CHARGER_CONNECTED() (LPC_GPIO1->FIOPIN & (1<<21))
#define IS_CHARGER_ENABLED() (LPC_GPIO1->FIOPIN & (1<<23))
#define IS_CHARGING() (IS_CHARGER_CONNECTED() && IS_CHARGER_ENABLED())
#define ENABLE_CHARGER() do { LPC_GPIO1->FIOSET = (1<<23); } while(0)
#define DISABLE_CHARGER() do { LPC_GPIO1->FIOCLR = (1<<23); } while(0)
#define BATTERY_MAX_VOLTAGE 287
#define BATTERY_MIN_VOLTAGE 237
xQueueHandle xPowerMgmtMsgQueue;
int32_t lChargeCurrent;
int32_t lBatteryVoltage;
int32_t lBatteryTemperature;
void task_PowerMgmt(void *pvParameters)
{
xPowerMgmtMsgQueue = xQueueCreate(20, sizeof(xPowerMgmtMsg));
lChargeCurrent = INT32_MIN;
lBatteryVoltage = INT32_MIN;
lBatteryTemperature = INT32_MIN;
// P1.21 - Charger connected (input, high active)
// for approx. 2sec after connected to charger (led turns red), it is high
LPC_PINCON->PINMODE3 &= ~(3 << ((21 - 16) * 2));
LPC_PINCON->PINMODE3 |= (2 << ((21 - 16) * 2)); // no pullup/-down
LPC_PINCON->PINSEL3 &= ~(3 << ((21 - 16) * 2)); // plain gpio
LPC_GPIO1->FIODIR &= ~(1 << 21); // input
// P1.23 - Enable charger (output, high active)
LPC_PINCON->PINMODE3 &= ~(3 << ((23 - 16) * 2));
LPC_PINCON->PINMODE3 |= (2 << ((23 - 16) * 2)); // no pullup/-down
LPC_PINCON->PINSEL3 &= ~(3 << ((23 - 16) * 2)); // plain gpio
LPC_GPIO1->FIODIR |= (1 << 23); // output
DISABLE_CHARGER();
for (;;) {
xPowerMgmtMsg msg;
if (xQueueReceive(xPowerMgmtMsgQueue, &msg, xDelay100) == pdTRUE) {
switch (msg.xType) {
case (MEASUREMENT_BATTERY): {
/* https://hackaday.io/project/6717-project-landlord/discussion-58892 */
if (msg.measurement.lChargeCurrent != INT32_MIN) {
lChargeCurrent = msg.measurement.lChargeCurrent;
printf("Charge I: %4lumA\r\n", lChargeCurrent);
}
if (msg.measurement.lBatteryVoltage != INT32_MIN) {
// orig fw: v16_batteryLowV = 237; - 23.7V (fixed point) - 3.386V per cell
// orig fw: v18_batteryFullCharge = 287; - 28.7V (fixed point) - 4.1V per cell
lBatteryVoltage = msg.measurement.lBatteryVoltage;
printf("Battery U: %2lu.%01luV\r\n", lBatteryVoltage / 10, lBatteryVoltage % 10);
if ((lBatteryVoltage < BATTERY_MIN_VOLTAGE) && !IS_CHARGER_CONNECTED()) { /* below 23.7V - switch off to protect battery! */
/* issue shutdown to self */
xPowerMgmtMsg msg;
msg.xType = COMMAND_SHUTDOWN;
msg.shutdown.xDelay = xDelay100;
printf("Requesting shutdown to protect battery!\r\n");
xQueueSend(xPowerMgmtMsgQueue, &msg, (TickType_t)0);
} else if (lBatteryVoltage > BATTERY_MAX_VOLTAGE) { /* over 28.7V - stop charging! */
}
}
if (msg.measurement.lBatteryTemperature != INT32_MIN) {
lBatteryTemperature = msg.measurement.lBatteryTemperature;
if (lBatteryTemperature > 400) { /* above 40.0°C - switch off to protect battery! */
/* issue shutdown to self */
xPowerMgmtMsg msg;
msg.xType = COMMAND_SHUTDOWN;
msg.shutdown.xDelay = xDelay100;
printf("Requesting shutdown to protect battery!\r\n");
xQueueSend(xPowerMgmtMsgQueue, &msg, (TickType_t)0);
}
if (lBatteryTemperature >= 0) {
printf("Battery T: %3lu.%01lu%cC\r\n", lBatteryTemperature / 10, lBatteryTemperature % 10, '\xB0');
} else {
lBatteryTemperature = ~lBatteryTemperature;
printf("Battery T: -%3lu.%01lu%cC\r\n", lBatteryTemperature / 10, lBatteryTemperature % 10, '\xB0');
}
}
break;
}
case (COMMAND_SHUTDOWN): {
printf("Shutting down!\r\n");
vTaskDelay(msg.shutdown.xDelay);
LPC_GPIO1->FIOPIN &= ~(PIN(25)); // Shutdown
__disable_irq(); for (;;);
}
default:
printf("Unknown msg\r\n");
}
}
// on each loop (latest every 100ms), check if connected to charger
if (IS_CHARGER_CONNECTED()) {
if (!IS_CHARGER_ENABLED()) {
if ((lBatteryVoltage > (BATTERY_MIN_VOLTAGE - 10)) && (lBatteryVoltage < (BATTERY_MAX_VOLTAGE - 10))) {
printf("Start charging\r\n");
ENABLE_CHARGER();
}
} else {
if (lBatteryVoltage >= BATTERY_MAX_VOLTAGE) {
printf("Stop charging\r\n");
DISABLE_CHARGER();
}
}
} else {
if (IS_CHARGER_ENABLED()) {
printf("Charger disconnected\r\n");
DISABLE_CHARGER();
}
}
#if LOWSTACKWARNING
int stack = uxTaskGetStackHighWaterMark(NULL);
if (stack < 50) printf("Task task_PowerMgmt has %u words left in stack.\r\n", stack);
#endif
}
}