Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
PowerSensor2
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ResearchAndDevelopment
PowerSensor2
Commits
f3dd552c
Commit
f3dd552c
authored
7 years ago
by
Bram Veenboer
Browse files
Options
Downloads
Patches
Plain Diff
Update library files and Makefile
parent
047fe715
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
Makefile
+26
-9
26 additions, 9 deletions
Makefile
PowerSensor.cc
+371
-90
371 additions, 90 deletions
PowerSensor.cc
PowerSensor.h
+77
-29
77 additions, 29 deletions
PowerSensor.h
with
474 additions
and
128 deletions
Makefile
+
26
−
9
View file @
f3dd552c
ARCH
=
$(
shell
arch
)
CXX
=
g++
CXXFLAGS
=
-O2
-g
-pthread
-fopenmp
CXXFLAGS
=
-std
=
c++11
-O2
-g
-pthread
-fopenmp
obj/$(ARCH)/%.o
:
%.cc
@
mkdir
-p
obj/
$(
ARCH
)
$(
CXX
)
-c
$(
CXXFLAGS
)
$<
-o
$@
all
::
lib/$(ARCH)/libPowerSensor.a bin/$(ARCH)/testPowerSensor arduino
all
::
lib/$(ARCH)/libPowerSensor.a
\
bin/$(ARCH)/psconfig
\
bin/$(ARCH)/psrun
\
bin/$(ARCH)/pstest
\
arduino
lib/$(ARCH)/libPowerSensor.a
:
obj/$(ARCH)/PowerSensor.o lib/$(ARCH)
lib/$(ARCH)/libPowerSensor.a
:
obj/$(ARCH)/PowerSensor.o
-
mkdir
-p
lib/
$(
ARCH
)
$(
AR
)
cr
$@
$<
bin/$(ARCH)/testPowerSensor
:
obj/$(ARCH)/testPowerSensor.o lib/$(ARCH)/libPowerSensor.a bin/$(ARCH)
$(
CXX
)
$(
CXXFLAGS
)
obj/
$(
ARCH
)
/testPowerSensor.o
-Llib
/
$(
ARCH
)
-lPowerSensor
-o
$@
bin/$(ARCH)/psconfig
:
obj/$(ARCH)/psconfig.o lib/$(ARCH)/libPowerSensor.a
-
mkdir
-p
bin/
$(
ARCH
)
$(
CXX
)
$(
CXXFLAGS
)
obj/
$(
ARCH
)
/psconfig.o
-Llib
/
$(
ARCH
)
-lPowerSensor
-o
$@
obj/$(ARCH)/testPowerSensor.o
:
testPowerSensor.cc PowerSensor.h obj/$(ARCH)
bin/$(ARCH)/psrun
:
obj/$(ARCH)/psrun.o lib/$(ARCH)/libPowerSensor.a
-
mkdir
-p
bin/
$(
ARCH
)
$(
CXX
)
$(
CXXFLAGS
)
obj/
$(
ARCH
)
/psrun.o
-Llib
/
$(
ARCH
)
-lPowerSensor
-o
$@
obj/$(ARCH)/PowerSensor.o
:
PowerSensor.cc PowerSensor.h obj/$(ARCH)
bin/$(ARCH)/pstest
:
obj/$(ARCH)/pstest.o lib/$(ARCH)/libPowerSensor.a
-
mkdir
-p
bin/
$(
ARCH
)
$(
CXX
)
$(
CXXFLAGS
)
obj/
$(
ARCH
)
/pstest.o
-Llib
/
$(
ARCH
)
-lPowerSensor
-o
$@
obj/$(ARCH) lib/$(ARCH) bin/$(ARCH)
:
mkdir
-p
$@
obj/$(ARCH)/psconfig.o
:
psconfig.cc PowerSensor.h
obj/$(ARCH)/psrun.o
:
psrun.cc PowerSensor.h
obj/$(ARCH)/pstest.o
:
pstest.cc PowerSensor.h
obj/$(ARCH)/PowerSensor.o
:
PowerSensor.cc PowerSensor.h Semaphore.h
arduino
::
+make
-C
Arduino
...
...
@@ -28,3 +44,4 @@ upload:: all
clean
::
make
-C
Arduino clean
$(
RM
)
-r
bin/
$(
ARCH
)
lib/
$(
ARCH
)
obj/
$(
ARCH
)
This diff is collapsed.
Click to expand it.
PowerSensor.cc
+
371
−
90
View file @
f3dd552c
...
...
@@ -22,44 +22,130 @@
#include
<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<iostream>
#include
<byteswap.h>
#include
<errno.h>
#include
<fcntl.h>
#include
<omp.h>
#include
<sys/
types
.h>
#include
<sys/
file
.h>
#include
<sys/stat.h>
#include
<sys/types.h>
#include
<sys/wait.h>
#include
<termios.h>
#include
<unistd.h>
namespace
PowerSensor
{
PowerSensor
::
PowerSensor
(
const
char
*
device
,
const
char
*
dumpFileName
)
:
dumpFile
(
dumpFileName
==
0
?
0
:
new
std
::
ofstream
(
dumpFileName
)),
stop
(
false
)
void
PowerSensor
::
Sensor
::
readFromEEPROM
(
int
fd
)
{
lastState
.
microSeconds
=
0
;
struct
EEPROM
eeprom
;
ssize_t
retval
,
bytesRead
=
0
;
do
{
if
((
retval
=
::
read
(
fd
,
(
char
*
)
&
eeprom
+
bytesRead
,
sizeof
eeprom
-
bytesRead
))
<
0
)
{
perror
(
"read device"
);
exit
(
1
);
}
}
while
((
bytesRead
+=
retval
)
<
sizeof
eeprom
);
#if defined __BIG_ENDIAN__
eeprom
.
volt
=
__bswap_32
(
eeprom
.
volt
);
eeprom
.
type
=
__bswap_32
(
eeprom
.
type
);
eeprom
.
nullLevel
=
__bswap_32
(
eeprom
.
nullLevel
);
#endif
setVolt
(
eeprom
.
volt
);
setType
(
eeprom
.
type
);
setNullLevel
(
eeprom
.
nullLevel
);
}
void
PowerSensor
::
Sensor
::
writeToEEPROM
(
int
fd
)
const
{
struct
EEPROM
eeprom
;
eeprom
.
volt
=
volt
;
eeprom
.
type
=
type
;
eeprom
.
nullLevel
=
nullLevel
;
#if defined __BIG_ENDIAN__
eeprom
.
volt
=
__bswap_32
(
eeprom
.
volt
);
eeprom
.
type
=
__bswap_32
(
eeprom
.
type
);
eeprom
.
nullLevel
=
__bswap_32
(
eeprom
.
nullLevel
);
#endif
ssize_t
retval
,
bytesWritten
=
0
;
do
{
if
((
retval
=
::
write
(
fd
,
(
char
*
)
&
eeprom
+
bytesWritten
,
sizeof
eeprom
-
bytesWritten
))
<
0
)
{
perror
(
"write device"
);
exit
(
1
);
}
}
while
((
bytesWritten
+=
retval
)
<
sizeof
eeprom
);
}
void
PowerSensor
::
Sensor
::
updateDerivedValues
()
{
weight
=
volt
!=
0
?
2.5
/
512
*
volt
/
type
:
0
;
consumedEnergy
=
0
;
wattAtlastMeasurement
=
0
;
timeAtLastMeasurement
=
omp_get_wtime
();
}
void
PowerSensor
::
Sensor
::
setVolt
(
float
volt
)
{
this
->
volt
=
volt
;
updateDerivedValues
();
}
void
PowerSensor
::
Sensor
::
setType
(
float
type
)
{
this
->
type
=
type
;
updateDerivedValues
();
}
void
PowerSensor
::
Sensor
::
setNullLevel
(
float
nullLevel
)
{
this
->
nullLevel
=
nullLevel
;
updateDerivedValues
();
}
int
PowerSensor
::
openDevice
(
const
char
*
device
)
{
int
fd
;
if
((
fd
=
open
(
device
,
O_RDWR
))
<
0
)
{
perror
(
"open device"
);
exit
(
1
);
}
if
(
flock
(
fd
,
LOCK_EX
)
<
0
)
{
perror
(
"flock"
);
exit
(
1
);
}
//Configure port for 8N1 transmission
struct
termios
options
;
tcgetattr
(
fd
,
&
options
);
//Gets the current options for the port
cfsetispeed
(
&
options
,
B
20000
00
);
//Sets the Input Baud Rate
cfsetospeed
(
&
options
,
B
20000
00
);
//Sets the Output Baud Rate
cfsetispeed
(
&
options
,
B
96
00
);
//Sets the Input Baud Rate
cfsetospeed
(
&
options
,
B
96
00
);
//Sets the Output Baud Rate
options
.
c_cflag
=
(
options
.
c_cflag
&
~
CSIZE
)
|
CS8
;
options
.
c_iflag
=
IGNBRK
;
options
.
c_lflag
=
0
;
options
.
c_oflag
=
0
;
options
.
c_cflag
|=
CLOCAL
|
CREAD
;
options
.
c_cc
[
VMIN
]
=
sizeof
(
State
::
MC_State
)
;
options
.
c_cc
[
VMIN
]
=
2
;
options
.
c_cc
[
VTIME
]
=
0
;
options
.
c_iflag
&=
~
(
IXON
|
IXOFF
|
IXANY
);
options
.
c_cflag
&=
~
(
PARENB
|
PARODD
);
...
...
@@ -67,173 +153,368 @@ PowerSensor::PowerSensor(const char *device, const char *dumpFileName)
/* commit the options */
tcsetattr
(
fd
,
TCSANOW
,
&
options
);
#if defined UNO
/* Wait for the Arduino to reset */
sleep
(
2
);
#endif
/* Flush anything already in the serial buffer */
tcflush
(
fd
,
TCIFLUSH
);
if
((
errno
=
pthread_mutex_init
(
&
mutex
,
0
))
!=
0
)
{
perror
(
"pthread_mutex_init"
);
exit
(
1
);
return
fd
;
}
doMeasurement
();
// initialise
if
((
errno
=
pthread_create
(
&
thread
,
0
,
&
PowerSensor
::
IOthread
,
this
))
!=
0
)
{
perror
(
"pthread_create"
);
exit
(
1
);
}
PowerSensor
::
PowerSensor
(
const
char
*
device
)
:
startTime
(
omp_get_wtime
()),
fd
(
openDevice
(
device
)),
thread
(
nullptr
)
{
startCleanupProcess
();
readSensorsFromEEPROM
();
startIOthread
();
}
PowerSensor
::~
PowerSensor
()
{
stop
=
true
;
if
((
errno
=
pthread_join
(
thread
,
0
))
!=
0
)
perror
(
"pthread_join"
);
if
((
errno
=
pthread_mutex_destroy
(
&
mutex
))
!=
0
)
perror
(
"pthread_mutex_destroy"
);
stopIOthread
();
if
(
close
(
fd
))
perror
(
"close device"
);
}
if
(
dumpFile
!=
0
)
delete
dumpFile
;
void
PowerSensor
::
readSensorsFromEEPROM
()
{
if
(
write
(
fd
,
"r"
,
1
)
!=
1
)
{
perror
(
"write device"
);
exit
(
1
);
}
for
(
Sensor
&
sensor
:
sensors
)
sensor
.
readFromEEPROM
(
fd
);
}
void
PowerSensor
::
lock
()
void
PowerSensor
::
writeSensorsToEEPROM
()
{
if
((
errno
=
pthread_mutex_lock
(
&
mutex
))
!=
0
)
{
perror
(
"pthread_mutex_lock"
);
stopIOthread
();
if
(
write
(
fd
,
"w"
,
1
)
!=
1
)
{
perror
(
"write device"
);
exit
(
1
);
}
#if defined UNO
struct
termios
options
;
usleep
(
200000
);
tcgetattr
(
fd
,
&
options
);
cfsetospeed
(
&
options
,
B115200
);
tcsetattr
(
fd
,
TCSANOW
,
&
options
);
#endif
for
(
const
Sensor
&
sensor
:
sensors
)
sensor
.
writeToEEPROM
(
fd
);
#if defined UNO
usleep
(
200000
);
tcgetattr
(
fd
,
&
options
);
cfsetospeed
(
&
options
,
B2000000
);
tcsetattr
(
fd
,
TCSANOW
,
&
options
);
#endif
startIOthread
();
}
void
PowerSensor
::
unlock
()
void
PowerSensor
::
startCleanupProcess
()
{
if
((
errno
=
pthread_mutex_unlock
(
&
mutex
))
!=
0
)
{
perror
(
"pthread_mutex_unlock"
);
// spawn child process to make sure that the Arduino receives a 'T', no matter how the application terminates
int
pipe_fds
[
2
];
if
(
pipe
(
pipe_fds
)
<
0
)
{
perror
(
"pipe"
);
exit
(
1
);
}
switch
(
fork
())
{
ssize_t
retval
;
case
-
1
:
perror
(
"fork"
);
exit
(
1
);
case
0
:
// detach from the parent process, so signals to the parent are not caught by the child
setsid
();
// close all file descriptors, except pipe read end and Arduino fd
for
(
int
i
=
3
,
last
=
getdtablesize
();
i
<
last
;
i
++
)
if
(
i
!=
fd
&&
i
!=
pipe_fds
[
0
])
close
(
i
);
// wait until parent closes pipe_fds[1] so that read fails
char
byte
;
retval
=
::
read
(
pipe_fds
[
0
],
&
byte
,
sizeof
byte
);
// tell Arduino to stop sending data
retval
=
write
(
fd
,
"T"
,
1
);
// drain garbage
usleep
(
100000
);
tcflush
(
fd
,
TCIFLUSH
);
exit
(
0
);
default:
close
(
pipe_fds
[
0
]);
}
}
void
*
PowerSensor
::
IOthread
(
void
*
arg
)
bool
PowerSensor
::
Sensor
::
inUse
()
const
{
return
static_cast
<
PowerSensor
*>
(
arg
)
->
IOthread
()
;
return
volt
!=
0
;
}
void
*
PowerSensor
::
IOthread
(
)
void
PowerSensor
::
Sensor
::
updateLevel
(
int16_t
level
)
{
while
(
!
stop
)
doMeasurement
();
double
now
=
omp_get_wtime
();
return
0
;
wattAtlastMeasurement
=
(
level
-
512
)
*
weight
-
nullLevel
;
consumedEnergy
+=
wattAtlastMeasurement
*
(
now
-
timeAtLastMeasurement
);
timeAtLastMeasurement
=
now
;
}
void
PowerSensor
::
doMeasurement
()
double
PowerSensor
::
Sensor
::
totalEnergy
(
double
now
)
const
{
State
::
MC_State
currentState
;
return
/* weight == 0 ? 0 : */
consumedEnergy
+
wattAtlastMeasurement
*
(
now
-
timeAtLastMeasurement
);
}
ssize_t
retval
,
bytesRead
=
0
;
if
(
write
(
fd
,
"s"
,
1
)
!=
1
)
{
perror
(
"write device"
);
exit
(
1
)
;
double
PowerSensor
::
Sensor
::
currentWatt
()
const
{
return
/* weight == 0 ? 0 : */
wattAtlastMeasurement
;
}
do
{
if
((
retval
=
::
read
(
fd
,
(
char
*
)
&
currentState
.
consumedEnergy
+
bytesRead
,
sizeof
(
State
::
MC_State
)
-
bytesRead
))
<
0
)
{
bool
PowerSensor
::
readLevelFromDevice
(
unsigned
&
sensorNumber
,
unsigned
&
level
)
{
uint8_t
msg
[
2
];
ssize_t
retval
,
bytesRead
=
0
;
while
(
true
)
{
if
((
retval
=
::
read
(
fd
,
(
char
*
)
&
msg
+
bytesRead
,
sizeof
msg
-
bytesRead
))
<
0
)
{
perror
(
"read device"
);
exit
(
1
);
}
else
if
((
bytesRead
+=
retval
)
==
sizeof
msg
)
{
if
(
msg
[
0
]
==
0xFF
&&
msg
[
1
]
==
0xE0
)
{
return
false
;
}
else
if
((
sensorNumber
=
msg
[
0
]
>>
5
)
<
MAX_SENSORS
&&
(
msg
[
1
]
&
0xE0
)
==
0xE0
)
{
level
=
((
msg
[
0
]
&
0x1F
)
<<
5
)
|
(
msg
[
1
]
&
0x1F
);
return
true
;
}
else
{
msg
[
0
]
=
msg
[
1
];
// byte lost? drop first byte and try again
bytesRead
=
1
;
}
}
}
}
void
PowerSensor
::
dumpCurrentWattToFile
()
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
dumpFileMutex
);
double
totalWatt
=
0
;
double
time
=
omp_get_wtime
();
*
dumpFile
<<
"S "
<<
time
-
startTime
;
#if 1
static
double
previousTime
;
*
dumpFile
<<
' '
<<
1e6
*
(
time
-
previousTime
);
previousTime
=
time
;
#endif
for
(
const
Sensor
&
sensor
:
sensors
)
if
(
sensor
.
inUse
())
{
*
dumpFile
<<
' '
<<
sensor
.
currentWatt
();
totalWatt
+=
sensor
.
currentWatt
();
}
*
dumpFile
<<
' '
<<
totalWatt
<<
std
::
endl
;
}
void
PowerSensor
::
IOthread
()
{
threadStarted
.
up
();
unsigned
sensorNumber
,
level
;
while
(
readLevelFromDevice
(
sensorNumber
,
level
))
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
mutex
);
sensors
[
sensorNumber
].
updateLevel
(
level
);
if
(
dumpFile
!=
nullptr
)
dumpCurrentWattToFile
();
}
}
}
while
((
bytesRead
+=
retval
)
<
sizeof
(
State
::
MC_State
));
lock
();
if
(
lastState
.
microSeconds
!=
currentState
.
microSeconds
)
{
previousState
=
lastState
;
lastState
=
currentState
;
void
PowerSensor
::
startIOthread
()
{
if
(
thread
==
nullptr
)
{
thread
=
new
std
::
thread
(
&
PowerSensor
::
IOthread
,
this
);
if
(
dumpFile
!=
0
)
*
dumpFile
<<
"S "
<<
currentState
.
microSeconds
/
1e6
<<
' '
<<
(
currentState
.
consumedEnergy
-
previousState
.
consumedEnergy
)
*
(
65536.0
/
512
)
/
(
currentState
.
microSeconds
-
previousState
.
microSeconds
)
<<
std
::
endl
;
if
(
write
(
fd
,
"S"
,
1
)
!=
1
)
{
perror
(
"write device"
);
exit
(
1
);
}
}
#if 0
static double lastTime;
static unsigned count;
++ count;
threadStarted
.
down
();
// wait for the IOthread to run smoothly
}
if (lastTime + 1 < omp_get_wtime()) {
#pragma omp critical (cout)
std::cout << "nr times read = " << count << std::endl;
lastTime = omp_get_wtime();
count = 0;
void
PowerSensor
::
stopIOthread
()
{
if
(
thread
!=
nullptr
)
{
if
(
write
(
fd
,
"X"
,
1
)
<
0
)
{
perror
(
"write"
);
exit
(
1
);
}
#endif
unlock
();
thread
->
join
();
delete
thread
;
thread
=
0
;
}
}
void
PowerSensor
::
dump
(
const
char
*
dumpFileName
)
{
dumpFile
=
std
::
unique_ptr
<
std
::
ofstream
>
(
dumpFileName
!=
nullptr
?
new
std
::
ofstream
(
dumpFileName
)
:
nullptr
);
}
void
PowerSensor
::
mark
(
const
State
&
state
,
const
char
*
name
,
unsigned
tag
)
void
PowerSensor
::
mark
(
const
State
&
state
,
const
char
*
name
,
unsigned
tag
)
const
{
if
(
dumpFile
!=
0
)
{
lock
();
*
dumpFile
<<
"M "
<<
state
.
lastState
.
microSeconds
*
1e-6
<<
' '
<<
tag
<<
"
\"
"
<<
(
name
==
0
?
""
:
name
)
<<
'"'
<<
std
::
endl
;
unlock
();
if
(
dumpFile
!=
nullptr
)
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
dumpFileMutex
);
*
dumpFile
<<
"M "
<<
state
.
timeAtRead
-
startTime
<<
' '
<<
tag
<<
"
\"
"
<<
(
name
==
nullptr
?
""
:
name
)
<<
'"'
<<
std
::
endl
;
}
}
void
PowerSensor
::
mark
(
const
State
&
startState
,
const
State
&
stopState
,
const
char
*
name
,
unsigned
tag
)
void
PowerSensor
::
mark
(
const
State
&
startState
,
const
State
&
stopState
,
const
char
*
name
,
unsigned
tag
)
const
{
if
(
dumpFile
!=
0
)
{
lock
();
*
dumpFile
<<
"M "
<<
startState
.
lastState
.
microSeconds
*
1e-6
<<
' '
<<
stopState
.
lastState
.
microSeconds
*
1e-6
<<
' '
<<
tag
<<
"
\"
"
<<
(
name
==
0
?
""
:
name
)
<<
'"'
<<
std
::
endl
;
unlock
();
if
(
dumpFile
!=
nullptr
)
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
dumpFileMutex
);
*
dumpFile
<<
"M "
<<
startState
.
timeAtRead
-
startTime
<<
' '
<<
stopState
.
timeAtRead
<<
' '
<<
tag
<<
"
\"
"
<<
(
name
==
nullptr
?
""
:
name
)
<<
'"'
<<
std
::
endl
;
}
}
PowerSensor
::
State
PowerSensor
::
read
()
State
PowerSensor
::
read
()
const
{
State
state
;
lock
();
state
.
previousState
=
previousState
;
state
.
lastState
=
lastState
;
std
::
unique_lock
<
std
::
mutex
>
lock
(
mutex
);
state
.
timeAtRead
=
omp_get_wtime
();
unlock
();
for
(
unsigned
sensorID
=
0
;
sensorID
<
MAX_SENSORS
;
sensorID
++
)
state
.
consumedEnergy
[
sensorID
]
=
sensors
[
sensorID
].
totalEnergy
(
state
.
timeAtRead
);
return
state
;
}
double
PowerSensor
::
Joules
(
const
State
&
firstState
,
const
State
&
secondState
)
double
Joules
(
const
State
&
firstState
,
const
State
&
secondState
,
int
sensorID
)
{
return
Watt
(
firstState
,
secondState
)
*
seconds
(
firstState
,
secondState
);
if
(
sensorID
>=
(
signed
)
MAX_SENSORS
)
return
0
;
if
(
sensorID
>=
0
)
return
secondState
.
consumedEnergy
[
sensorID
]
-
firstState
.
consumedEnergy
[
sensorID
];
double
joules
=
0
;
for
(
double
consumedEnergy
:
secondState
.
consumedEnergy
)
joules
+=
consumedEnergy
;
for
(
double
consumedEnergy
:
firstState
.
consumedEnergy
)
joules
-=
consumedEnergy
;
return
joules
;
}
double
PowerSensor
::
seconds
(
const
State
&
firstState
,
const
State
&
secondState
)
double
seconds
(
const
State
&
firstState
,
const
State
&
secondState
)
{
return
secondState
.
timeAtRead
-
firstState
.
timeAtRead
;
}
double
PowerSensor
::
Watt
(
const
State
&
firstState
,
const
State
&
secondState
)
double
Watt
(
const
State
&
firstState
,
const
State
&
secondState
,
int
sensorID
)
{
return
Joules
(
firstState
,
secondState
,
sensorID
)
/
seconds
(
firstState
,
secondState
);
}
float
PowerSensor
::
getVolt
(
unsigned
sensorID
)
const
{
return
sensorID
<
MAX_SENSORS
?
sensors
[
sensorID
].
volt
:
0
;
}
void
PowerSensor
::
setVolt
(
unsigned
sensorID
,
float
volt
)
{
if
(
sensorID
<
MAX_SENSORS
)
{
sensors
[
sensorID
].
setVolt
(
volt
);
writeSensorsToEEPROM
();
}
}
float
PowerSensor
::
getType
(
unsigned
sensorID
)
const
{
return
sensorID
<
MAX_SENSORS
?
sensors
[
sensorID
].
type
:
0
;
}
void
PowerSensor
::
setType
(
unsigned
sensorID
,
float
type
)
{
if
(
sensorID
<
MAX_SENSORS
)
{
sensors
[
sensorID
].
setType
(
type
);
writeSensorsToEEPROM
();
}
}
float
PowerSensor
::
getNullLevel
(
unsigned
sensorID
)
const
{
uint32_t
microSeconds
=
secondState
.
lastState
.
microSeconds
-
firstState
.
lastState
.
microSeconds
;
return
sensorID
<
MAX_SENSORS
?
sensors
[
sensorID
].
nullLevel
:
0
;
}
void
PowerSensor
::
setNullLevel
(
unsigned
sensorID
,
float
nullLevel
)
{
if
(
sensorID
<
MAX_SENSORS
)
{
sensors
[
sensorID
].
setNullLevel
(
nullLevel
);
writeSensorsToEEPROM
();
}
}
bool
PowerSensor
::
inUse
(
unsigned
sensorID
)
const
{
return
sensorID
<
MAX_SENSORS
&&
sensors
[
sensorID
].
inUse
();
}
if
(
microSeconds
!=
0
)
return
(
secondState
.
lastState
.
consumedEnergy
-
firstState
.
lastState
.
consumedEnergy
)
*
(
65536.0
/
512
)
/
microSeconds
;
else
// very short time
return
(
secondState
.
lastState
.
consumedEnergy
-
secondState
.
previousState
.
consumedEnergy
)
*
(
65536.0
/
512
)
/
(
secondState
.
lastState
.
microSeconds
-
secondState
.
previousState
.
microSeconds
);
}
This diff is collapsed.
Click to expand it.
PowerSensor.h
+
77
−
29
View file @
f3dd552c
...
...
@@ -21,50 +21,98 @@
#if !defined POWER_SENSOR_H
#define POWER_SENSOR_H
#include
"Semaphore.h"
#include
<inttypes.h>
#include
<pthread.h>
#include
<fstream>
#include
<mutex>
#include
<thread>
namespace
PowerSensor
{
const
static
unsigned
MAX_SENSORS
=
5
;
class
PowerSensor
{
public:
struct
State
{
struct
MC_State
{
int32_t
consumedEnergy
;
uint32_t
microSeconds
;
}
previousState
,
lastState
;
double
consumedEnergy
[
MAX_SENSORS
];
double
timeAtRead
;
};
PowerSensor
(
const
char
*
device
=
"/dev/ttyACM0"
,
const
char
*
dumpFileName
=
0
);
class
PowerSensor
{
public:
PowerSensor
(
const
char
*
device
=
"/dev/ttyACM0"
);
~
PowerSensor
();
State
read
();
void
mark
(
const
State
&
,
const
char
*
name
=
0
,
unsigned
tag
=
0
);
void
mark
(
const
State
&
start
,
const
State
&
stop
,
const
char
*
name
=
0
,
unsigned
tag
=
0
);
State
read
()
const
;
static
double
Joules
(
const
State
&
firstState
,
const
State
&
secondState
);
static
double
seconds
(
const
State
&
firstState
,
const
State
&
secondState
);
static
double
Watt
(
const
State
&
firstState
,
const
State
&
secondState
);
void
dump
(
const
char
*
dumpFileName
);
// dumpFileName == 0 --> stop dumping
void
mark
(
const
State
&
,
const
char
*
name
=
0
,
unsigned
tag
=
0
)
const
;
void
mark
(
const
State
&
start
,
const
State
&
stop
,
const
char
*
name
=
0
,
unsigned
tag
=
0
)
const
;
float
getVolt
(
unsigned
sensorID
)
const
;
void
setVolt
(
unsigned
sensorID
,
float
volt
);
float
getType
(
unsigned
sensorID
)
const
;
void
setType
(
unsigned
sensorID
,
float
type
);
float
getNullLevel
(
unsigned
sensorID
)
const
;
void
setNullLevel
(
unsigned
sensorID
,
float
nullLevel
);
bool
inUse
(
unsigned
sensorID
)
const
;
private:
struct
Sensor
{
struct
EEPROM
{
float
volt
__attribute__
((
packed
));
float
type
__attribute__
((
packed
));
float
nullLevel
__attribute__
((
packed
));
};
float
volt
,
type
,
nullLevel
;
double
weight
;
double
consumedEnergy
;
double
wattAtlastMeasurement
;
double
timeAtLastMeasurement
;
bool
inUse
()
const
;
void
readFromEEPROM
(
int
fd
),
writeToEEPROM
(
int
fd
)
const
;
void
setVolt
(
float
),
setType
(
float
),
setNullLevel
(
float
);
void
updateDerivedValues
();
void
updateLevel
(
int16_t
level
);
double
totalEnergy
(
double
now
)
const
;
double
currentWatt
()
const
;
}
sensors
[
MAX_SENSORS
];
double
startTime
;
int
fd
;
std
::
ofstream
*
dumpFile
;
pthread_t
thread
;
pthread_mutex_t
mutex
;
volatile
bool
stop
;
State
::
MC_State
previousState
,
lastState
;
std
::
unique_ptr
<
std
::
ofstream
>
dumpFile
;
//volatile bool stop;
mutable
std
::
mutex
mutex
,
dumpFileMutex
;
Semaphore
threadStarted
;
std
::
thread
*
thread
;
void
startIOthread
(),
stopIOthread
();
int
openDevice
(
const
char
*
device
);
double
totalEnergy
()
const
;
void
readSensorsFromEEPROM
(),
writeSensorsToEEPROM
();
bool
readLevelFromDevice
(
unsigned
&
sensorNumber
,
unsigned
&
level
);
void
dumpCurrentWattToFile
();
void
IOthread
();
void
startCleanupProcess
();
};
void
lock
(),
unlock
();
static
void
*
IOthread
(
void
*
);
void
*
IOthread
();
void
doMeasurement
();
};
double
Joules
(
const
State
&
firstState
,
const
State
&
secondState
,
int
sensorID
=
-
1
/* default: all sensors */
);
double
seconds
(
const
State
&
firstState
,
const
State
&
secondState
);
double
Watt
(
const
State
&
firstState
,
const
State
&
secondState
,
int
sensorID
=
-
1
/* default: all sensors */
);
}
#endif
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment