Detailed Software Description

weaverchurchΛογισμικό & κατασκευή λογ/κού

15 Αυγ 2012 (πριν από 5 χρόνια και 2 μήνες)

295 εμφανίσεις

Detailed Software Description


Java

Application


The software program is the heart of the SAMDS. It receives raw data from all
devices connected to the system via the Central Unit and transforms this raw data into a
u
sable form to be vie
wed and evaluated
by the user. Netbeans 5.0 was used to design the
program entirely in Java. Although much custom code was written to implement the
custom functionality needed to suit the needs of the project, the extensive Java libraries
and the nature of the Netbeans 5.
0 design environment made it unnecessary to implement
some of the basic functionality of the program such as the layout of the items on the
screen and event listeners that trigger function calls when buttons or check boxes are
activated by the user.


The d
esign of the main program relied heavily on using multiple execution
threads to accomplish many tasks simultaneously
. Upon

startup of the program
, it
originally contains only one thread

the

main execution thread.

The main execution
thread is n
ot the work
horse of the program; instead, i
ts primary purpose is to initialize
and configure connections to the necessary resources, such as the connection to the USB
and the connection to the SQL database
. This main execution thread also explicitly starts
the addit
ional threads that
.


The life cycle of the main execution thread is as follows:

1)

Initialize variables for use later in the program

(much of this is
automatically done by Netbean
s
)
.

2)

Establish and configure USB connection.

3)

Establish and configure connection
to MySQL database.

4)

Determine how many devices are connected to the system.

5)

Begin a separate thread for each device connected to the system for
independent monitoring of each device.

6)

Begin a thread for controlling the data logging process.

7)

Listen for events

(button presses, check boxes, etc.) by the user for the
remainder of the life of the program instance (As mentioned before,
Netbeans automatically implements the event listener for you).

As alluded to in step 5 above, a separate execution thread is starte
d for each
device connected to the system. These threads
are responsible for gathering raw current
and voltage data from each device and

transforming it to usable data (Refer to Software
Appendix for detailed description and flow chart of its operation).

The class for the read device thread extends the Java Thread class and overrides
the native run method for implementation of custom code. The run method simply runs
in an infinite while loop to continuously gather data from the connected devices.
Each
de
vice connected to the system has an associated thread running to manage the data the
device is sending and receiving.

The device read thread begins by checking if the USB connection is available. If
the USB connection is not available, the thread waits
until it becomes available and then
continues execution. When the USB connection becomes available, the thread locks
the
USB connection so other threads running concurrently cannot interrupt the reading and
writing process (Essential to maintaining the in
tegrity of the voltage and current data
received from the device). The thread then prompts its associated device to send a packet
containing raw current samples (each packet contains 180 current samples). A similar
request is sent to get the voltage data

from the device. The thread then releases the lock
on the USB connection to allow other threads to use it while calculations are being
completed on the data retrieved.

After retrieving the data from the device, the raw data must be converted before
fur
ther calculations and modifications can be carried out.
Since each data sample is 4
characters long (representing a 4 digit hexadecimal value), the string containing the
retrieved
data is parsed into 4 character strings and sent to a helper function which

converts 4 digit hexadecimal values into a do
uble precision decimal number. After the
conversion is complete for both the current and voltage values, the maximum and
minimum value for each is calculated. The root mean square (RMS) value of the current
d
ata is also calculated.

Next, the thread attempts to identify what device is plugged into the system. This
is accomplished by querying an
SQL database containing the device voltage and current
characteristics for various appliances. The voltage and cur
rent minimums and maximums
as well as the RMS value for the current calculated previously are compared with the
values in the database and the device is identified if the recorded values fall within
specified ranges of the data retrieved from the database.

If the device cannot be
accurately identified using the data contained in the device database table, subsequent
repetitions of the thread’s run method will continue attempting to identify the device.

Once a device has been identified, the user has the op
tion to lock that device in by
checking a check box on the main screen of the program. If this check box is selected,
subsequent repetitions of the read thread’s run method will not try to identify the
connected device, but instead check to see if the dev
ice is still operating within the
current and voltage specs from the device table in the database
.
As of this version of the
SAMDS
-
OS, a device is considered to be malfunctioning if its current consumption is
drastically above the expected value. More ri
gorous requirements for determining a
malfunction will be added in subsequent versions of the SAMDS
-
OS.

When a device malfunction is detected, the SAMD
-
OS program and email is sent
to
nuthesis@cox.net

with details
of the malfunction. Further revisions of the SAMDS
-
OS program will include the option to specify what email address or cell phone number
the
notification
will be sent
to. The
JavaMail
class files
used for
composing and sending email messages from a Java
application were retrieved from
www.javasoft.com
.

After the device has been identified or its operation verified, the power usage data
for that device is written to the power usage tables in the SQL database.

The

remainder
of the read device thread is spent using the values calculated from the raw data and the
device information from the database to update the appropriate labels on the main screen
as well as graphing the voltage and current data in the graphing pa
nels.

Graphing the voltage and current data required that a custom component be
designed to accommodate the needs of the SAMDS system. A DrawingPanel class was
designed solely for the purpose of graphing the current and voltage data. The
DrawingPanel cla
ss extends the javax.swing.JPanel component, overriding its paint
function. The DrawingPanel class contains a function called drawGraph which handles
the necessary steps for rendering the graph to the screen.
The grid lines and labels on the
graph are ca
lculated and drawn using the current height and width of the window on the
screen.
As mentioned above, the read device thread converts the raw data received from
the device to double precision decimal numbers. The drawGraph panel is passed this
array of
double precision decimal values and
uses these values to determine the scale and
label values shown on the graph. Furthermore, the data passed to the drawGraph function
is used to calculate the shape of the graph shown on the panel (refer to source code i
n
Software Appendix for algorithms).

The SAMDS
-
OS program also has the capability of turning the selected device on
and off

and scheduling devices to
autonomously turn on or off at a
specified time
. On the SAMDS
-
OS main screen, there is a toggle
butto
n in the device description
section of the screen giving the
user direct control over the status
of the device.

If, however, the user wants to schedule a device to turn on or off
autonomously
, the user
may press the Schedule
button in the lower left
hand
part of the Device
Description section on the
SAMDS
-
OS main screen.
This will bring up the
device schedule screen for
that device. An instance of
this screen is created during
the program initialization
for each device connected to the system so each dev
ice can have its own schedule.

A
user may select when they wish a device to be toggled on or off by selecting the
appropriate options in the Add Event panel in the lower left of the screen. When the Add
Event button is pressed, the event is added to the
list on the left and a Date object is
formed for when the device is to be toggled. Using this date, an instance of the
EventRunner

class is instantiated. The
EventRunner

class extends Java’s native
TimerTask

class. The basic operation of the
EventRunner

class is as follows. A da
te is
passed to the constructor. T
he instance of the class creates another thread that waits until
the specified date then executes the contents of the class’s run method. The overridden
run method contains the code to toggle t
he device on and off. After the run method has
been executed and the device toggled, the thread dies. The event is then removed from
the schedule list.

Another key aspect of the SAMDS
-
OS program is the power usage monitoring
capabilities. If the user

activates the More
Details button on the
main screen of the
SAMDS
-
OS program in
the Usage Statistics
panel, the user can view
the power consumption of various devices.

As with the custom panel used to draw the graph on the main screen of the
SAMDS
-
OS prog
ram, the panel used to show the power consumption history is also a
customized panel. The
BarGraphPanel

class extends the
javax
.
swing
.
JPanel

Java class
and, similar to the
DrawingPanel

class used for rendering the current and volta
ge
waveforms on the main

screen, contains a helper function inside the class which
overrides the native paint function of the
JPanel
. This function is also called
drawGraph
.

The operation of the
drawGraph

function for the
BarGraphPanel

is as follows.
The background of the graph

is rendered based on the size of the panel (background
color, gridlines, etc.). Based upon the maximum value of the data to be graphed, the Y
axis gr
id labels are calculated. Then, based on the scale of the graph and the number of
data elements to be gr
aphed, the heights of the co
rresponding bars are calculated and the
bars are drawn.

The
BarGraphPanel

is
contained

inside another custom created class called the
MoreDetailsFrame
. The
MoreDetailsFrame

class extends the
javax
.
swing
.
JFrame

class. The
More
DetailsFrame

class controls what data is graphed on the
BarGraphPanel
. When
initialized, the
MoreDetailsFrame

establishes its own
connection with the
SQL database for
accessing power usage
information. It then
idles and waits for the
user to press the Sh
ow
Data button.

When the user presses the Show Data button, this action triggers a member
function of the
MoreDetailsFrame

called
doGraphingFunc
. The basic functionality of
the
doGraphingFunc

method is as follows.
Based on the options selected, regarding

the
time period and device name, the appropriate power usage values for that device and time
period are retrieved from the SQL database. The information retrieved from the
database is arranged into an array and, along with an array of labels for the X a
xis, is
passed to the
drawGraph

function in the
BarGraphPanel

to be graphed appropriately.

The final aspect of the SAMDS
-
OS program occurs in the background. As
mentioned at the beginning of this section, when first started, the main thread begins a
separ
ate thread to control the data logging.
This thread is called the
usageLogThread
.
The main purpose of this thread is to continuously organize data in the SQL database.
Although the code for this thread is quite lengthy, the idea behind how it operates i
s not.
The SQL database contains six tables used for storing device power usage information.
The tables are appropriately named
hourlyusage
,
dailyusage
,
weeklyusage
,
monthlyusage
,
yearlyusage
, and
totalusage
.

As the read device thread continuously places

data into the
hourlyusage

table
with fields denoting device name, power usage, and the time the sample was taken. Only
the
hourlyusage

table is directly modified by the read device thread. The
usageLogThread’s

main operation then becomes continuously co
nsolidating this
information from the
hourlyusage

table into the
dailyusage

table, consolidating
information from the
dailyusage

table to the weekly usage table and so on. Each time
the minute of an hour ticks from 59 to 00, the information from that hour

is then summed
and added to the
dailyusage

table. Similarly, when the clock ticks from 11:59 PM to
12:00 AM of the next day, all the information from the
dailyusage

table is consolidated
and added to the
weeklyusage

table. A similar process occurs for t
he
monthlyusage

and
yearlyusage

tables.

This is the main operation of the SAMDS
-
OS program
. As mentioned before, the
Netbeans 5.0 programming utility greatly increased coding efficiency by automatically
taking care of menial, yet necessary, functions inhe
rent to all Java programs. The next
subsection details the software used on the Atmel AT89C55WD microcontroller.

Microcontroller Code

There are two main subsections of microcontroller programming; that of the RMU, and
that of the CRU.


The RMU.

The m
ain function of the RMU is to continuously obtain data from the
analog
-
to
-
digital converter (ADC) channels defined by the following two statements:

#define VOLTAGE_ADC_CHANNEL 7

#define CURRENT_ADC_CHANNEL 3

These statically define the channels from which
the data is obtained, and must correspond
to the hardware on the RMU.

NOTE:

Since the ADC uses a 1 through 8 notation externally, and a zero
-
offset 0
through 7 internally, it is important to understand that channel 7 corresponds, in
binary, to channel 6,
and so on.

The following statement defines the size of the data array taken from each of the ADC
channels:


#define DATA_ARRAY_SIZE 180


The

main()

function

simply initializes the hardware on the RMU, and begins the
continuous collection of data. The foll
owing code executes

in the main() function:


int main() {


i
nit()



w
hile(

1 )
{


NOTBUSY = 1;


for( currentIndex = 0; currentIndex < ( DATA_ARRAY_SIZE * 2 ); currentIndex++ )



currentQueue[currentIndex] = read_adc( CURRENT_ADC_CHANNEL );



for( curr
entIndex = 0; currentIndex < ( DATA_ARRAY_SIZE * 2 ); currentIndex++ )



voltageQueue[currentIndex] = read_adc( VOLTAGE_ADC_CHANNEL );



}

}


As can be seen in the code above, the program executes

the
init()

function to initialize
the system, and procee
ds to execute continuously the process of data retrieval.

NOTE
: It is important to understand that the
hardware of the RMU is interrupt
-
based
, such that
when the UART receives a byte of data on the RX line, an Interrupt Service Routine (ISR) is
called
to han
dle the interrupt. T
he
voltage and current queues (in the above code) are twice the
size of the
DATA_ARRAY_SIZE
, because when the interrupt is generated, this ensures that t
here
are
DATA_ARRAY_SIZE

consecutive data elements (in one of the halves of
the queue). If the program is
interrupted requesting data during collection of the first half of the queue (
currentIndex
<

DATA_ARRAY_SIZE
), then the data is pulled from the second half of both of the queues. Likewise,
when interrupted during the buildi
ng of the second half, the first halves are used.


NOTE:

Three important variables are declared as static to ensure global access:
currentIndex
,
currentQueue[]
, and
voltageQueue[]
.
The latter two are declared static in external data
memory, as only 256 b
ytes exist internally in the microcontroller.
These are declared as such to
be available both inside the main function, and also inside the
serialISR()

routine that executes
when a serial interrupt occurs.



Th
e line
s

of code inside

the
for

loops simply c
all the
read_adc(channel
)

function and st
ores the result into one of two data
array
s

in external data memory
. The
read_adc(channel)

function requests data from the ADC on the

channel given as an
argument. When making a call to the
read_adc()

function, th
e microcontroller transmits
first the channel information to the ADC, using the
write_adc(
)

function

explained
below
, then begins to read the data in from the serial port. With 1 leading zero bit, 3
channel bits, and 12 data bits, the total ADC data recei
ved
for each sample
is 16 bits long.



By the close of the second
for

loop, both the current and voltage

queues contain two
whole consecu
tive arrays of
DATA_ARRAY_SIZE

length.

At this point, the RMU clears the
currentIndex
, and begins to sample data agai
n.


The AN7890
-
10 (Analog
-
to
-
Digital Converter) contains a serial interface that is
used to transmit and receive data to and from the microcontroller. Since the hardware
was set up as a manual UART (See Detailed
Hardware

Description, p ), the
SCLK

signal

must be set and cleared manually using the
pulseSCLK()

function. The
pulseSCLK()

function is shown here:


v
oid pulseSCLK()


{



SCLK = 0;



SCLK = 1;

}

This method simply pulses the
SCLK

signal.

NOTE:

Using this method as the only interface to the SCLK

signal ensures that the SCLK will
always be a known value (at idle a logic 1).


The
read_adc(channel)

function

is in charge of beginning, completing, and
repeating the process of obtaining
DATA_ARRAY_SIZE

samples of data for the purpose of
having data rea
dily available upon request from the Main System Application.

The first requirement of the ADC is that the appropriate channel be set in its control
buffer. For instance, if data is to read from channel 3, a binary
010

must be transmitted
in a Control Wor
d (CW) to the device prior to retrieving the sampling data. As a signal
to prepare the ADC for data flow, it also acts as a trigger to begin the sampling of data
inside the ADC, after which 5.9us are required for conversion of the signal from analog
to di
gital. This CW trigger is transmitted inside the
write_adc(channel)

function.

After returning from the
write_adc(channel)

routine, the next step is to accept the bit
values returned serially from the ADC.

As explained above, 2 bytes are returned by the
A
DC in the aforementioned sequence. This value is returned as a 2
-
byte
int
.



The
serialISR()

function is the most important function in making the device
communicate to the outside world. This ISR is run every time a character shows up in
the wireless s
erial input buffer. Because this could any of 256 various characters, a
system of simple ‘commands’ was put in place to act as somewhat of a protocol for
communication between the two devices. The commands are as follows:


Character

Command Description

R


Enable System Relay

r


Disable System Relay

V


Request MAX_ARRAY_SIZE samples from VOLTAGE_ADC_CHANNEL



A


Request MAX_ARRAY_SIZE samples from CURRENT_ADC_CHANNEL



S


Request Status of Relay (1
-
ON; 0
-
OFF)



T


Quick Memory Test (returns 89AB on success
)


The
xtransmit(x) functions

contain the programming necessary to
transmit data across
the wireless serial medium in various forms, as shown here:


btransmit
(
bit
)



transmits a bit of data (transmitted as an ASCII ‘0’ or ‘1’)
.

transmit
(char
)



transmits a

byte of data
.

wtransmit
(int
)



transmits 2 bytes of data
.

stransmit
(char*)


transmits a null
-
terminated string of data
.


See Appendix
yadayada

for the unabridged code in its entirety.


The CRU
.

The second crucial piece of software is the router code use
d in the Central
Routing Unit to control the traffic
sent to and from the SAMDS
-
OS, and to and from the
RMUs. When the SAMDS
-
OS requests data from one of the RMUs, the first checkpoint
is the CRU. The CRU analyzes the command sent from the SAMDS
-
OS, and
determines
to which device the command is intended. This is done by
programming

the
transceiver’s control buffer; specifically, the communication channel in the output
settings. Once the transmitter has been programmed with the appropriate destination
ad
dress, the command(s) can then be sent to that particular device.