-
Notifications
You must be signed in to change notification settings - Fork 1
/
PowerSupplyMonitor.ino
177 lines (143 loc) · 6.03 KB
/
PowerSupplyMonitor.ino
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <LiquidCrystal_I2C.h> // from https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
#include <Wire.h> // Standard Arduino Library
#include <Adafruit_ADS1015.h> // Must use the soligen2010 fork at https://github.com/soligen2010/Adafruit_ADS1X15
#include <PWM.h> // From https://code.google.com/archive/p/arduino-pwm-frequency-library/downloads
#include "PowerSupplyMonitorCalibration.h"
#define EN_PIN 2
#define RW_PIN 1
#define RS_PIN 0
#define D4_PIN 4
#define D5_PIN 5
#define D6_PIN 6
#define D7_PIN 7
#define BL_PIN 3 //Backlight
LiquidCrystal_I2C lcd(0x27, // Set the LCD I2C address
EN_PIN,
RW_PIN,
RS_PIN,
D4_PIN,
D5_PIN,
D6_PIN,
D7_PIN,
BL_PIN,
POSITIVE);
Adafruit_ADS1115 ads;
float adsMVperStep;
int fanSpeed = 210;
void setup() {
bool success = SetPinFrequencySafe(9,25000); // set fan PWM frequency to 25 kHz
//Serial.begin(115200);
setupADC();
lcd.begin(16, 2);
lcd.clear();
}
void loop() {
int a;
int overSampleCount = 16; // number of over-samples to take before updating display
int16_t voltReading = 0;
int16_t ampReading = 0;
int16_t ampSetReading = 0;
int32_t voltOverSample = 0;
int32_t ampOverSample = 0;
int32_t ampSetOverSample = 0;
float voltIn = 0.0;
float ampIn = 0.0;
float ampSetIn = 0.0;
float watts = 0.0;
// display only over-sampled readings
// this reduces display jitter
// AIN0 - voltage
// AIN1 - Before shunt resistor
// AIN2 - amp current limit set
// AIN3 - GND (After shunt resistor)
//Take readings all at once so ADC does not have to switch inputs with each reading
//Also take a priming read so inputs settle
voltReading = ads.readADC_Differential_0_3();
for(a = 0; a < overSampleCount; a = a + 1) {
voltReading = ads.readADC_Differential_0_3();
voltOverSample = voltOverSample + voltReading;
}
ampReading = ads.readADC_Differential_1_3();
for(a = 0; a < overSampleCount; a = a + 1) {
ampReading = ads.readADC_Differential_1_3();
ampOverSample = ampOverSample + ampReading;
}
ampSetReading = ads.readADC_Differential_2_3();
for(a = 0; a < overSampleCount; a = a + 1) {
ampSetReading = ads.readADC_Differential_2_3();
ampSetOverSample = ampSetOverSample + ampSetReading;
}
voltIn = (((((float) voltOverSample) / (float) a) * adsMVperStep) * VOLT_SET_MULTIPLIER) + VOLT_SET_OFFSET;
voltIn -= ((((float) ampOverSample) / (float) a * adsMVperStep)); // Adjust by the voltage drop accross the shunt resistor
ampIn = (((((float) ampOverSample) / (float) a * adsMVperStep)) / SHUNT_RESISTOR) + SHUNT_OFFSET;
ampSetIn = (((((float) ampSetOverSample) / (float) a * adsMVperStep)) * AMP_SET_ADJUST) + AMP_SET_OFFSET;
//Amp set changes slightly per amp actually being drawn so add to the display based on this
ampSetIn = ampSetIn + (ampIn * AMP_SET_LOAD_COMPENSATION);
// Avoid display jitter when there is nothng connected
if (ampSetIn < 0.0007) {ampSetIn = 0.0;}
if (ampIn < 0.0007) {ampIn = 0.0;}
if (voltIn < 0.008) {voltIn = 0.0;}
watts = voltIn * ampIn;
adjustFanSpeed(watts, ampIn);
display(voltIn, ampIn, ampSetIn, watts);
}
void display(float volt, float amp, float ampSet, float watt) {
if (true) {
lcd.setCursor(0, 1);lcd.print(" I=");
lcd.setCursor(3, 1);lcd.print(amp, 3);
}
if (true) {
lcd.setCursor(0, 0);lcd.print("CL=");
lcd.setCursor(3, 0);lcd.print(ampSet, 3);
}
if (true) {
lcd.setCursor(8, 1);lcd.print(" W=");
if (watt > 10.0) {
lcd.setCursor(11, 1);lcd.print(watt, 2);
}
else {
lcd.setCursor(11, 1);lcd.print(" ");
lcd.setCursor(12, 1);lcd.print(watt, 2);
}
lcd.setCursor(8, 0);lcd.print(" V=");
float voltDisplay = volt;
if (voltDisplay > 10.0) {
lcd.setCursor(11, 0);lcd.print(voltDisplay, 2);
}
else {
lcd.setCursor(11, 0);lcd.print(" ");
lcd.setCursor(12, 0);lcd.print(voltDisplay, 2);
}
}
}
void setupADC() {
// The ADC input range (or gain) can be changed via the following
// functions, but be careful never to exceed VDD +0.3V max, or to
// exceed the upper and lower limits if you adjust the input range!
// Setting these values incorrectly may destroy your ADC!
// ADS1015 ADS1115
// ------- -------
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default)
// ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV
// ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV
ads.begin();
ads.setGain(GAIN_TWO);
adsMVperStep = ads.voltsPerBit();
ads.setSPS(ADS1115_DR_250SPS); // 860 Samples per second
}
void adjustFanSpeed (float watts, float amps) {
int newFanSpeed;
#define FAN_IDLE_SPEED 155
#define FAN_MAX_SPEED 255
// scale fan speed based on how much heat is generated. The transistor's dsipation is based on watts, but the shunt
// resistor disipation is based on the amps. Choose fan speed based on whichever is higher
newFanSpeed = max (FAN_IDLE_SPEED + (float ((watts/MAX_WATTS) * (float (FAN_MAX_SPEED - FAN_IDLE_SPEED)))) ,
FAN_IDLE_SPEED + (float ((amps/MAX_AMPS) * (float (FAN_MAX_SPEED - FAN_IDLE_SPEED)))) );
if (newFanSpeed != fanSpeed) {
fanSpeed = newFanSpeed;
pwmWrite(9,fanSpeed);
}
}