Multi-functional Power Box

I am excited to unveil a newly developed multi-functional power box, designed speficially for engineering-related projects.
This versatile device is equipped with several key features to streamline your work.

Key Features

  • Dual Relay System:

    • Outlet 1: Connected to a solid-state relay, perfect for use in PID control systems.
    • Outlet 2: Equipped with a mechanical relay, ideal for simple on/off power operations.
  • Integrated AC Power Meter:

    • Provides instant and accurate measurements of current and voltage, with a precision of ±1 W.
  • Expandable with Arduino Mega:

    • The embedded Arduino Mega board allows for easy expansion. You can add modules for monitoring temperature, pressure, and more, making this power box highly adaptable for future developments.

For a closer look, check out the images of the power box below:

Power Box

Arduino Code

The board comes pre-loaded with essential Arduino code, ensuring the power box is ready to use straight out of the box.

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
/*
Title: Dual Relay Controller
Made by: YX
Location: Melbourne
Date: 20241010
Description: This program is designed to control two relays, one mechanical and one SSR (Solid State Relay),
allowing for triggering via serial commands.
Expansion: The function can be extended to measure AC power, voltage, current when using PZEM004T.
*/
#include <PWM.h> //download https://code.google.com/archive/p/arduino-pwm-frequency-library/downloads
// edit ATimerDefs.h and add '(0,0,0,0,0), // TIMER1C' after Line 107
// if applied to Arduino Mega 2560
#include <PZEM004Tv30.h> // Power meter library
#include <math.h>
/*
This code runs on mega and uno.
*/
PZEM004Tv30 pzemOT1(68, 69); // power meter

float power1;
float voltage1;
float current1;
float factor1;

float powerx;
int relayPin = 28;

// initializ the SSRs
//use pin 11 on the Mega instead, otherwise there is a frequency cap at 31 Hz
// ledTimer0 Pins 13, 4 might influence the internal clock
int ledTimer1 = 5; // Pins 11, 12 16-bits timer
int32_t frequency = 1; //PWM frequency (in Hz)

int mark = 0;
// String comdata = ""; // initialize input string
int numdata[2] = { 0 };
float DutyCircle;
const byte numChars = 32;
char comdata[numChars];

boolean newData = false;

void setup() {
//initialize all timers except for 0, to save time keeping functions
InitTimersSafe();
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW);
//sets the frequency for the specified pin
bool success1 = SetPinFrequencySafe(ledTimer1, frequency);
Serial.begin(115200); // set up communication
digitalWrite(ledTimer1, LOW);
Serial.println("Power box");

}

void loop() {
int j = 0;
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
recvWithStartEndMarkers();
if (newData == true) {
if (comdata[0] == 'P' && comdata[1] == 'W') {
Serial.println("power reading");
powerx = pzemOT1.power();
// voltage1 = pzemOT1.voltage();
// current1 = pzemOT1.current();
// power1 = voltage1 * current1;
power1 = pzemOT1.power();
// factor1 = pzemOT1.powerfactor();
if (!isnan(power1)) {
// Serial.print("1: ");
Serial.print(power1);
Serial.println();
} else {

Serial.println("1: OFF");
// Serial.print(voltage1); Serial.println();
// Serial.print(current1); Serial.println();
}
mark = 0;
}

if (comdata[0] == 'S' && comdata[1] == 'O' && comdata[2] == '1') {
delay(2);
mark = 1;
char* commaPtr = strchr(comdata,',');
// Check if the comma exists
if (commaPtr != NULL) {
float value = atof(commaPtr + 1); // Convert string after the comma
// Now you can use 'value' as a float
if (value < 256){
pwmWrite(ledTimer1, value); // change the duty circle
float DutyCycle = float(value) / 255 * 100;
Serial.print("SSR Relay Activate and The Duty Cycle is ");
Serial.println(DutyCycle);
} else {
Serial.println("Exceeds 255; ignoring.");
}
} else {
Serial.println("SSR Relay Deactivate");
}
}

if (comdata[0] == 'S' && comdata[1] == 'O' && comdata[2] == '2') {
delay(2);
Serial.println("Relay On");
delay(10);
digitalWrite(relayPin, HIGH);
mark = 0;
}

if (comdata[0] == 'S' && comdata[1] == 'F' && comdata[2] == '2') {
delay(2);
Serial.println("Relay Off");
delay(10);
digitalWrite(relayPin, LOW);
mark = 0;
}
newData = false;
}
}



void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;

// if (Serial.available() > 0) {
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
delay(2);

if (recvInProgress == true) {
if (rc != endMarker) {
comdata[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
} else {
comdata[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}

else if (rc == startMarker) {
recvInProgress = true;
}
}
mark = 1;
}

I also attach a demo MATLAB code in the following.

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
function s = serialRelayControl(action, varargin)
% serialRelayControl Handle serial port actions
% Created by YX on 2024.10.12
%
% Copyright (c) 2024 YX
% All rights reserved.
% Commerical use is prohibited without explicit permission
% Examples:
% Create: s = serialRelayControl('create', 'COM7');
% Write: serialRelayControl('write', s, 'yourCommand');
% Remove: s = serialRelayControl('remove', s);

action = lower(action);
switch action
case 'create'
port = varargin{1};
s = createPort(port);
readFromPort(s);
case 'write'
s = varargin{1};
command = varargin{2};
writeToPort(s, command);
readFromPort(s);
case 'remove'
s = varargin{1};
removePort(s);
otherwise
error('Unknown action.');
end
end

function s = createPort(port)
try
s = serialport(port, 115200);
s.Timeout = 5;
catch ME
warning('Failed to create serial port: %s', ME.message);
s = [];
end
end

function writeToPort(s, command)
if ~isempty(s) && isvalid(s)
try
pause(.1);
writeline(s, command);
pause(.1);
catch ME
warning('Failed to write to serial port: %s', ME.message);
end
else
disp('No active serial port connection.');
end
end

function readFromPort(s)
if ~isempty(s) && isvalid(s)
try
pause(.1);
if s.NumBytesAvailable > 0
output = readline(s);
pause(.1);
disp(['Received: ', output]);
else
disp('No data available.');
end
catch
warning('Error reading from serial port.');
end
else
disp('No active serial port connection.');
end
end

function removePort(s)
if ~isempty(s) && isvalid(s)
delete(s);
disp('Serial port connection removed.');
else
disp('No active serial port connection to remove.');
end
end
打赏
  • © 2020-2025 Yu Xia
  • Powered by Hexo Theme Ayer
    • PV:
    • UV:

Buy me a cup of coffee~

支付宝
微信