project - CAE Usershomepages.cae.wisc.edu/~ece539/project/f01/raytan.pdf · of this project is to...

36
1 Project Summary The objective of this project was to design and implement an artificial neural network to control a simple solar tracker. A simple two axis solar tracker was built and all the necessary hardware was purchased or donated to make this project possible. Initially, the neural network will have two training phase using first artificial data off-line training and then live data on-line training. The goal of the on-line training was to give the solar tracker an adaptive control over its sensors (or in the event of malfunction sensor). The on-line training was proven to be very problematic due to the characteristics of the solar panel and the nature of the optical sensors. After many trials, I have set the sampling time to be every 30 second. At this point, the on-line training did not give significant improvement due to the short time training session. Therefore, no conclusion can be drawn on the value of the on-line training. However, overall the results were encouraging. The output of the solar panel did maintain at a fairly constant voltage. Problem Statement and Motivation In alternative energy research, solar is one of the most important sources of energy. There are also researches in fuel cell and Helium-3, but solar energy is the cheapest in the sense that once the technology is well developed, it is maintenance-free. In solar energy research, much attention is put on the development of photovoltaic cells - the element that converts light into electricity. Other topics in solar energy research include inverter design and power grid infrastructures, as well as solar farm design. A Solar farm is basically a place where a large array of solar panels is installed. In September

Transcript of project - CAE Usershomepages.cae.wisc.edu/~ece539/project/f01/raytan.pdf · of this project is to...

1

Project Summary

The objective of this project was to design and implement an artificial neural network to control

a simple solar tracker. A simple two axis solar tracker was built and all the necessary hardware was

purchased or donated to make this project possible. Initially, the neural network will have two training

phase using first artificial data off-line training and then live data on-line training. The goal of the on-line

training was to give the solar tracker an adaptive control over its sensors (or in the event of malfunction

sensor). The on-line training was proven to be very problematic due to the characteristics of the solar

panel and the nature of the optical sensors. After many trials, I have set the sampling time to be every

30 second. At this point, the on-line training did not give significant improvement due to the short time

training session. Therefore, no conclusion can be drawn on the value of the on-line training. However,

overall the results were encouraging. The output of the solar panel did maintain at a fairly constant

voltage.

Problem Statement and Motivation

In alternative energy research, solar is one of the most important sources of energy. There are

also researches in fuel cell and Helium-3, but solar energy is the cheapest in the sense that once the

technology is well developed, it is maintenance-free. In solar energy research, much attention is put on

the development of photovoltaic cells - the element that converts light into electricity. Other topics in

solar energy research include inverter design and power grid infrastructures, as well as solar farm

design.

A Solar farm is basically a place where a large array of solar panels is installed. In September

2

1995, Western Power opened Australia’s largest photovoltaic (PV) power system connected to a

major electricity grid. To maximise the output of the solar farm, other than employing high efficiency

PV panels (which could be very expensive), the use of solar trackers is a common practice. The goal

of this project is to investigate the use of an artificial neural network (and/or fuzzy logic) to control a

solar tracker.

A solar tracker is a mechanical system that tilts the photovoltaic panel into the direction of the

sun to maximise the efficiency of the panel. Often in a large solar farm, the solar trackers are a single-

axis system. The trackers are designed to follow the sun all the day, adjusting the PV panels to find the

best possible angle for receiving the most sunlight. Often, the tilt of the trackers is manually adjusted to

maximise seasonal performance as the angle of the sun in the sky changes between summer and winter.

The most advance solar farms employ satellites and computer to calculate the best tilt angle for the solar

tracker.

In my opinion, the use of advance algorithms and satellites (such as the GPS) to help control the

solar trackers is too expensive (and perhaps unnecessary). There are much researches on

semispherical optical sensors for solar trackers. However, the best solar tracker known to man is, in

fact, a plant - the sunflowers. Also, during different times of the day (especially sunrise and sunset)

aiming the PV panel directly into the direction of the sun doesn’t produce the maximum output due to

the fact that UV rays reflected in the atmosphere produce the max energy on PV panels. Therefore, by

using ANN, the solar tracker will find the optimal tilt angle with minimal sensor inputs (often in the event

of sensor failure), thus increasing its robustness. The result will benefit the solar research community

(and unmanned solar powered robot for space exploration). Although it can be argued that the use of

3

ANN was unnecessary because the system is fairly linear and other techniques such as Energy

Optimisation can be used, but with little background in control, I have chosen to use the ANN to

implement the controller.

Discussion

The Approach and Work Performed

The goal of the project was to investigate the use of ANN to control a solar tracker. This

project is biologically motivated. In order to apply an ANN to the solar tracker, one must first

understand the problem or define the problem so that ANN can be used. There are a few ways to

solve this problem, and one was investigated due to the time constrain.

The solar tracker problem can be realised by a classification problem or a minimisation

problem. Here are the explanations:

Classification problem:

The characteristic of a classification problem is one that has a well defined “choice” or “class”

for some input from the environment. I argued that the solar tracker can be modelled by a classification

problem. Given a few, for example, optical sensor inputs of different directions, the ANN will decide

the direction of the solar panel to turn to. For a typical solar tracker, there are only five choices: tilt up

or down, turn left or right, or remain at the current position.

Minimisation problem:

The characteristic of a minimisation problem is one that has a cost function for which one wish

to minimise by taking appropriate action; such as gradient search. I argued that the solar tracker can be

4

modelled by a classification problem. As I have mentioned earlier the solar panel, depending on the

time of the day, does not always give maximum output even when it is directly facing to the sun.

Therefore using, for example, the solar panel output as the cost function, one will try to minimise the

negative of the output voltage (or power), which will effectively maximise the output. In this case (in

theory), one can reduce all the sensors to just the solar panel itself.

One can also use a desire output to fine tune the weight of the classification ANN for the solar

tracker. For example, by purposely forcing the output of the classification to “remain at the same

position” if and only if the solar panel output is at the desire output value. This desire output value can

be one that is determined artificially. In the solar panel case, one can define the desire output as the

actual maximum achievable output of the solar panel. However, one undesired consequence is that the

solar panel will keep trying to search for the unachievable output all day! On the other hand, if one

lower this desire value to be just “good enough”, then the solar panel might never achieve its design

efficience.

The five sensors are oriented in five different directions (approximately with 5 degrees

variation), and the goal is to centre the middle sensor to face directly into the sun. The prototype of the

solar tracker design is shown in the accompany PowerPoint file. The entire structure was built by the

rapid prototype machine. The two motors for the tilt and rotation were donated by Maxon Motor.

Finally, the motor and sensors are connected to the ATMEL STK-500 development board. The

development board communicate the sensor data back to the computer via a serial cable. The ANN is

actually running on the computer. The ANN will take the data from the development board, and

decide which of the five directions it will go (up, down, left, right, or stay the same). The decision will

5

then send back to the development board and send the signal to the motor to achieve the appropriate

direction. The solar tracker was constructed using the Rapid Prototype Machine in ME shops. The

Pro-Engineer parts are shown here. The finished prototype is about 50 cm tall. The PV panel is a 15-

cm x 15-cm capable of maximum output (from manufacture data) 12V at 60 mA.

The Training

Based on the discussion above, I initially decided to take the combination approach. I designed

a neural network with minium sensor inputs to operate a two-axis solar tracker (rotation and tilt). Since

no two sensors are identical, thus there will be inherited noises in the input signal. The ANN seems to

be a good choice in this respect. The solar tracker has five optical sensors (photo transistor type) as

input, thus the ANN also. I first trained the BP neural network with artificial data and direction to turn.

The goal is to give the solar tracker the basic behaviour for tracking the sun. Then, I will put the ANN

on the actual solar tracker, and a BP network with the PV output voltage as the cost function to refine

the weights of the ANN to create the final network.

This method was proven to be very difficult to do with the setup I have. The first BP training

was not difficult since the data were artificial. (Training data were created in Microsoft Excel and is

included in the appendix of the electronic version of this report.) However, the second BP training was

too noisy (which I will explain later in this section) and therefore the training actually degraded the

artificially trained ANN. Because of the time constrain, the final ANN was only the artificially trained

portion.

I first created 499 artificial training data for the ANN. The neural network has five integer

6

value inputs (ranged from 200 to 255 with the assumption that the PV panel is facing approximately the

direction of the sun) and five integer value outputs (corresponding to the four directions to turn and one

to stay). The data were scaled by using the following equation to maximise the contrast of the input

data

Using trial and error, the two best ANN were a 5 - 10 - 10 - 5 and 5 - 10 - 8 - 5 configuration. The

learning rate of the ANN was 0.3 and the momentum was 0.8 with tolerance of 0.1 for a 5 - 10 - 8 - 5

neural network and 0.5 learning rate, 0.7 momentum with 0.1 tolerance for a 5 -10 - 10 - 5

configuration. Since both yield similar results, it was decided that the 5 - 10 - 8 - 5 neural network was

superior because it is smaller. The weight of the neural network is included in the Appendix.

The second BP training was a little too ambitious. I used PV voltage output (at time = t) will be

measured against the pervious voltage output (at time = t - 1) to produce an error for the cost function.

The only time when an error occurred was when the delta voltage was negative; i.e. if you turn the

direction that will reduce the output of the PV. This was proven to be very difficult for a few

reasons: first, the actual output of the sun changes from one second to the next. Thus, even if the PV

stayed pointing at the same direction, the voltage might still drop. The optical sensors are different in

nature than the PV, therefore, even when the centre optical sensor produces an output of 255, the

voltage of the PV might still drop because of cloud condition. Second, the readings from the optical

sensors fluctuated also. Therefore, there wasn’t consistent “input data”. And lastly, it took too long to

train the ANN this way. Since it was difficult to decide how long of the time interval between each data

7

point (there is a tradeoff between the sampling at a fast rate and the stability of the solar tracker),

therefore, it would take more than 30 minutes to evaluate if there was actual improvement on the ANN.

There were a few changes I made to the approach. To minimise the noise of the input data, I

put a filter over the optical sensor and increased the directional sensitivity. Instead of optimising the PV

panel output, it was the output of the centre optical sensor. Finally, to minimise the instability of the

system, I reduced the sampling frequency. The results were that the system was responding smoothly.

Unfortunately, no significant improvement was observed.

Results

There are three main programmes for this project: the controller programme (which is the

programme ATMEL development board that handles the motor driver and analogue to digital

conversion for the optical, and the serial communication to the computer), the neural network

programme, and the driver programme that communicates to the development board via the serial port

and call the neural programme. The neural network programme is derived from “Objected - Oriented

Neural Networks in C++” by Joey Rogers. Both the neural network programme and the driver

programme were developed on a S.u.S.E. Linux version 7.0 evaluation version. The source code is

included in the Appendix.

Data were taken during three trial runs of the solar tracker. The maximum output voltage was

measured to be 9.23 V in a four-hour period. As can be seen from the data, the curves are fairly

“smooth”, indicating the solar tracker is tracking the sun at a steady rate. Noted that because of the

characteristic of the solar panel (and the nature of the sunlight), the voltage output was not maintained

8

Trial 1

0123456789

10

0 100 200 300 400 500 600 700Time (x30 sec.)

Vo

ltag

e (V

)

Trial 2

0123456789

10

0 100 200 300 400 500 600 700Time (x30 sec.)

Vo

ltag

e (V

)

constant. Therefore, the fluctuation of the plot was not due to the movement / repositioning of the solar

tracker, but rather the inherent characteristic of the problem. Three plots of the actual data are shown

here.

Figure 1. Data taken on 19th of November 2001 from 12:00 p.m. to 4:00 p.m..

9

Trial 3

0123456789

10

0 100 200 300 400 500 600 700Time (x30 sec.)

Vo

ltag

e (V

)

Figure 2. Data taken on 23rd of November 2001 from 12:00 p.m. to 4:30 p.m..

Figure 3. Data taken on 24th of November 2001 from 11:00 a.m. to 4 p.m..

These data were taken over a five-hour period on three different days. During the afternoon hours

(after 2:00 p.m.), the output maintains a constant voltage of approximately 9V. The adjustment of the

tilt angle and the measurement of output voltage were done every 30 seconds. There are a few places

between 300 to 500 where the voltage drop is because there were reflective objects (windows of

vehicles parked outside my apartment) reflecting bright light into the optical sensor causing the solar

tracker to turn to that direction resulting the drop of the output voltage. The noise in the plot came from

the fact that the solar tracker was placed indoor and there were obstacles such as windows and moving

trees in the line of sight with the sun.

Conclusion and Suggested Future Work

10

Neural Net Decision

0

1

0 100 200 300 400 500 600

Time (x30 sec.)

Co

rrec

tio

n

I was able to apply a neural network to control a solar tracker. It is my suspicion that if the on-

line training was successful, then the “dips” in figure 1 would not have occurred (since the neural

network would have monitor the solar panel output voltage also). On the other hand, the neural

network control was very stable. Here is a plot of the “correction” vs. time for the 23rd of November.

The values of y indicated if the neural network made a decision to move (1) or to stay (0).

Figure 4. The occurrence of correction decided by the ANN.

Noted that there are time intervals (as long as 5 ~ 6 minutes) that the solar tracker remains stationary

(which is desirable). It is difficult to judge if the on-line training is degrading the performance of the

solar tracker. With the on-line training, there are often a period of oscillation. With better knowledge

of characteristic the solar panel, one might be able to conclude the values of the on-line training.

Although, the on-line training portion was “unsuccessful”, however the results were encouraging. Since

the results of the on-line training portion is inconclusive, the data were not included in this report.

11

Additional fine tuning can be performed to improve the performance of the solar tracker. Several

literatures had suggested that the use of fuzzy logic or time series to predict the location of the sun to

prevent the false sensor data such as one resulting from moving cloud or during rainy day. In fact, a

fuzzy logic controller may be more superior because its size is more compact (and require less

hardware for my project). I also believe that the “pervious” state(s) of input might help improve the

performance by reducing the effect of noise or disturbance or sudden change of sensor data. One must

also ask how many “pervious” state must the neural network remember. These approaches will require

extensive data collection at the site of the installation of the solar tracker. Also, this approach may not

be applicable in a large scale solar farm or solar panels installed in cities. The optical sensors are too

sensitive to bright light. Since finding the direction of maximum light intensity is important, the direct

transfer of the approach described here may not be applicable. In fact, a better use of the ANN in the

solar tracking application is to use it to predict the optimal direction of the solar panel. Given the scale

of this project, the result is acceptable.

One suggestion was to take advantage of the symmetry of the sensor orientation to reduce the

dimension of the feature vector. This will result a very compact ANN. At the same time, it might give a

better performance when one or more sensors had dropped out from service. I purposely took out one

sensor during a trial, and the “behaviour” of the solar tracker did not change dramatically. The Neural

Net Decision plot looks very similar to the one above, but the maximum output voltage was only 8.8

volt. Since I was unable to draw conclusive results from this one trial, the data were not included in this

report.

Overall, I believed the results were encouraging. The controller was very responsive.

12

However, I would take a fuzzy logic controller approach for the future design. The solar tracker

behaviour with a “malfunction” sensor was interesting, but a better testing scheme is required to

determine the overall performance and the value of the ANN approach.

13

ReferenceAnnual Report 24, Climate Monitoring & Diagnostics Laboratory CMDL,

http://www.cmdl.noaa.gov/publications/annrpt24/322.htm

Western Power Corporation, Kalbarri Photovoltaic System,http://www.westernpower.com.au/our_environment/renewable_energy/solar/

Gordon, M.. and Wenger, H., Central-Station Solar Photovoltaic Systems: Field Layout, Tracker, andArray Geometry Sensitivity Studies, Solar Energy, Vol. 46, No. 4, pp. 211-217, April 1991.

Panico, P., Garvison, P., Wenger, H., and D. Shugar, Backtracking: A Novel Strategy for TrackingPV Systems, IEEE Photovoltaic Specialists Conference, Las Vegas, NV, October 1991.

Rogers, Joey., (1997) Object - Oriented Neural Networks in C++, Academic Press, Inc., New York.

14

Appendix ANeural Network Weight. The node labelling convention is starting from the input layer, the first

node is labelled node 1, thus the first hidden layer first node is node 6, the next hidden layer first node isnode 16, and so on. Here is the weight of the 5 - 10 - 8 - 5 configuration:

15

Node Weight From To Node Weight From To Node Weight From To Node Weight From To0 -6.901416173 1 6 43 4.546939 4 14 86 -5.64103 12 19 129 2.741797 15 231 -5.137948269 2 6 44 -2.6321 5 14 87 -5.24199 13 19 130 -9.02233 16 242 -4.854224121 3 6 45 -5.05705 1 15 88 3.166138 14 19 131 8.923421 17 243 -0.546010865 4 6 46 10.59604 2 15 89 8.858821 15 19 132 7.716239 18 244 12.86077968 5 6 47 -4.54972 3 15 90 2.391506 6 20 133 -2.33067 19 245 -5.335119845 1 7 48 -1.58348 4 15 91 -0.10429 7 20 134 -8.56689 20 246 -4.853718922 2 7 49 -3.98411 5 15 92 0.536585 8 20 135 -4.15561 21 247 8.783092977 3 7 50 6.570963 6 16 93 -3.22794 9 20 136 4.941341 22 248 -2.795098623 4 7 51 -2.91327 7 16 94 3.806725 10 20 137 -10.7237 23 249 -0.413413988 5 7 52 5.981212 8 16 95 3.19486 11 20 138 0.3883 16 25

10 -3.328135163 1 8 53 -0.63564 9 16 96 2.797892 12 20 139 -7.1871 17 2511 -3.078320004 2 8 54 8.178021 10 16 97 -1.05139 13 20 140 -0.18123 18 2512 -3.698454914 3 8 55 -4.73824 11 16 98 -0.07111 14 20 141 14.28008 19 2513 -3.155630396 4 8 56 -6.32894 12 16 99 -0.14643 15 20 142 -5.786 20 2514 7.073576367 5 8 57 2.064939 13 16 100 7.430634 6 21 143 -4.07384 21 2515 -0.015043211 1 9 58 2.000927 14 16 101 0.259842 7 21 144 -2.89066 22 2516 -6.428302039 2 9 59 6.318585 15 16 102 3.713326 8 21 145 0.445678 23 2517 1.100867828 3 9 60 -1.64774 6 17 103 -2.76937 9 21 146 -11.6459 16 2618 7.277860244 4 9 61 -3.16932 7 17 104 -6.62353 10 21 147 -9.64494 17 2619 -2.122403715 5 9 62 -1.55732 8 17 105 0.619416 11 21 148 -4.0611 18 2620 -4.700004884 1 10 63 7.042222 9 17 106 -5.02798 12 21 149 -11.5447 19 2621 -3.598377235 2 10 64 7.636222 10 17 107 -8.46393 13 21 150 1.708354 20 2622 -3.914650508 3 10 65 0.524054 11 17 108 -3.31809 14 21 151 -1.03552 21 2623 9.09109631 4 10 66 -4.34313 12 17 109 -10.3607 15 21 152 1.390899 22 2624 -3.749182939 5 10 67 4.835328 13 17 110 -4.49839 6 22 153 8.656038 23 2625 -0.710910848 1 11 68 -6.4515 14 17 111 1.323691 7 22 154 5.119139 16 2726 0.802157178 2 11 69 -4.82492 15 17 112 -2.83924 8 22 155 4.505884 17 2727 8.917990567 3 11 70 -2.5262 6 18 113 0.559458 9 22 156 -11.0233 18 2728 -7.914079108 4 11 71 1.787274 7 18 114 -5.59261 10 22 157 -9.61731 19 2729 0.084673624 5 11 72 -0.16826 8 18 115 2.629107 11 22 158 -4.97014 20 2730 -3.304797913 1 12 73 -0.39167 9 18 116 5.788038 12 22 159 -11.5891 21 2731 -4.204934319 2 12 74 -8.40724 10 18 117 4.750746 13 22 160 -7.50345 22 2732 8.444109436 3 12 75 4.200085 11 18 118 -1.90309 14 22 161 2.970087 23 2733 -4.159947299 4 12 76 2.159742 12 18 119 -4.35231 15 22 162 2.149943 16 2834 -4.099009801 5 12 77 8.254782 13 18 120 -3.08917 6 23 163 -3.85344 17 2835 12.12093076 1 13 78 -5.20158 14 18 121 3.619951 7 23 164 -3.39297 18 2836 -5.04082006 2 13 79 3.212892 15 18 122 -4.06784 8 23 165 -8.71039 19 2837 -6.213685309 3 13 80 -5.91628 6 19 123 1.111685 9 23 166 -1.26157 20 2838 -4.957917146 4 13 81 -5.88166 7 19 124 5.225561 10 23 167 12.58586 21 2839 -4.953345372 5 13 82 -2.29928 8 19 125 -2.10899 11 23 168 -7.08499 22 2840 -10.12415128 1 14 83 -10.0261 9 19 126 4.46367 12 23 169 -7.16987 23 2841 0.643175844 2 14 84 -3.86799 10 19 127 -6.58345 13 2342 8.576902477 3 14 85 -0.8994 11 19 128 1.64691 14 23

Appendix BThe source code for the driver programme and the ATMEL micro controller source code are

listed here. The neural network program is adopted from Joey Rogers’s book “Object-OrientedNeural Network in C++” and therefore the source code will not be included here.

16

/************************************************************************

File Name: solar_tracker.cc Version: 0.9a Created by: Ray Tang, Jr. [email protected] Date: 10-15-2001 Description: This is a program for the ECE/CS/ME 539 - Introduction to Artificial Neural Network and the Fuzzy Systems. This program is design to talk to the ATMEL development board and drive the neural network program.

Details: This program will control the serial port and the neural network program call bp_app. The bp_app is a C++ neural network program from the book "Object-Oriented Neural Network in C++" by Joey Rogers. I used the source code to deveope the main neural network program and design this program to drive the neural network. The idea is this: the program will open up com1 and wait until it reads five integer data value. These five data values corresponds to the five sensor on the solar tracker. These values will then be input to the bp_app and produce the output. The output will then be sent back to the ATMEL development board in integer form and the ATMEL development will tilt up or down, turn left or right, or stay at the current position depending on the neural network output.

Disclaimer: This program does not come with any warrenty. You are free to distribute this program as long as the original text and comments are not deleted or modified. Feel free to modifiy if necessary to suit your needs, i.e. com1 may not be available to you. I tried to comments wherever I think it unclear, but feel free to add your comments for future development. I would like to hear feedbacks on what you have done to this program.

Information: This program is developed on S.u.S.E. Linux 7.0 free. It should compile on any other Linux platform with the apporiate libraries. Have a lot of fun!

Future Development: Error detection and other useful protocol was not program in this version. So, the program might crash. :-)

*************************************************************************/

#include <sys/types.h>#include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h>#include <string.h>#include <stdlib.h>#include <fstream.h>#include <iostream.h>

17

#include <unistd.h>

/************************************************************ Everything is in the main loop. It is not good programming style, but that's OK. The main loop open and close the serial ports as well as any other necessary files. The "main" loop is in fact an infinite loop with a while(1) statement.*************************************************************/

void main(void) {int fd, res; // file pointer to serial portchar buf[255]; // buffer for reading from serial//char serial_port_input; // serial port dataunsigned int num_chars_to_read = 255; // only read 5 (int) numbersunsigned int num_chars_to_write = 1; // only send back 1 char

struct termios oldtio,newtio; // serial termIO var//buf = &serial_port_input;

float temp1, temp2, temp3, temp4, temp5; // readings from neural netoutput int direction; // convert descion to "direction"

char buffer[256]; // dummy buffer to skip lines float dummy; // dummy variable

/* fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );

NOCTTY If the file is a terminal device, this flag prevents the file from becoming the con trolling terminal of the process

RDWR Open the file for both reading and writing.*/

fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY ); // open com1 if (fd < 0) {perror("/dev/ttyS0"); exit(-1);} // catch error

/* Configure the port for access: */// struct termios oldtio,newtio;

tcgetattr(fd,&oldtio); /* save current port settings */

bzero(&newtio, sizeof(newtio));// newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD; // no CRTSCTS// newtio.c_iflag = IGNPAR | ICRNL;

newtio.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD; // no CRTSCTS newtio.c_iflag = IGNPAR; newtio.c_oflag = 0;

/* set input mode (canonical, no echo, no signals) */

18

//newtio.c_lflag = ICANON; newtio.c_lflag = 0;

newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 5; /* blocking read until 5 chars received*/

tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio);

while (1) { // infinite loop

/* Read from the serial port: */ //res = -1; //while (!res) {

res = read(fd, buf, num_chars_to_read);//}if (res < 0) {perror("read"); exit(-1);}ofstream outfile("input.dat"); // object for writingoutfile << buf; // output to the fileoutfile.close(); // for the bp_app//printf("%d\n", res);

/* Calling the Neural Network Program */// bp_app RUN solar.net input.dat// bp_app is the acutal program// solar.net is the pretrained network// input.dat is the data coming from the serial port// the output is directed to file call nerualnetdecision.out

system("bp_app RUN solar.net input.dat > neuralnetdecision.out"); ifstream myFile("neuralnetdecision.out"); //float temp1, temp2, temp3, temp4, temp5; //int direction;

//char buffer[256]; //float dummy;

// Skip the first four lines of the output myFile.getline(buffer, 100); myFile.getline(buffer, 100); myFile.getline(buffer, 100); myFile.getline(buffer, 100); // get the neural net output myFile >> dummy >> temp1 >> temp2 >> temp3 >> temp4 >> temp5; // convert the decsion to a binary number // direction is a binary number // each bit corresponding to one direction // the development board will take care of the rest direction = 0; direction = (temp1 > 0.5);

19

direction = direction * 2 + (temp2 > 0.5); direction = direction * 2 + (temp3 > 0.5); direction = direction * 2 + (temp4 > 0.5); direction = direction * 2 + (temp5 > 0.5); /* Write to the serial port: */ *buf = direction;

write(fd, buf, num_chars_to_write);}

/* Clean up when done: */tcsetattr(fd,TCSANOW,&oldtio);close(fd);

}

Appendix CThis is the driver programme for the ATMEL development board that controls the solar

tracker. The actual licence of the software belongs to the Mechanical Engineering at University ofWisconsin Madison.

/*********************************************This program was produced by theCodeWizardAVR V1.0.2.0 StandardAutomatic Program Generator© Copyright 1998-2001Pavel Haiduc, HP InfoTech S.R.L.http://infotech.ir.roe-mail:[email protected] , [email protected]

Project : Version : Date : 11/15/2001Author : Site Lic. 10 Univ. of Wisconsin Company : 1513 Univ. Ave. Madison WI 53706Comments:

Chip type : AT90S8535Clock frequency : 8.000000 MHzMemory model : SmallInternal SRAM size : 512External SRAM size : 0Data Stack size : 128*********************************************/

#include <90s8535.h>

// Alphanumeric LCD Module functions#asm .equ __lcd_port=0x15

20

#endasm#include <lcd4x40.h> #pragma used+

#define TRUE 1#define FALSE 0 unsigned char WhichKey, TheKey; // Is Key pressed? Checkingvariable//unsigned char received_key;unsigned char KeyState; // Finite state machine counterunsigned char NewKey; // Remembering which key ispressedunsigned char KeyNumber; // dummy key variableunsigned int KeyCount; // Number of no key pressed interrupteint column, row; //Keyboard layoutunsigned char column_mask = 0b1000000; // Keybard maskint column_count = 3; // Number of column. Can be changed!int lock_status, four_sec_cycle; int sensor_data1, sensor_data2, sensor_data3, sensor_data4, sensor_data5;int correction;// float kc = 0.05; // Controller Gain (volts/count)float kc = 0.25;unsigned char c, cprev, m;int delta, r, e, global, R;int d;

/* Trip bit-3 on PORTB to low = PORTB & 0b11110111 *//* Trip bit-3 on high = PORTB | 0b00001000 */ /* Current keyboard layout */static char keypad_layout[4][4] = {

{'1','2','3','A'},{'4','5','6','B'},{'7','8','9','C'},{'*','0','#','D'}

};

// Time Delay loopvoid Delay(int time) {

int lcv;for(lcv = 0; lcv < time; lcv++);

}

// Check key pressed procedurevoid Check_Key(void) // test to see if any key is depressed{ //unsigned int delay; unsigned char KeyValue, column_key_mask, row_key_mask, KeyDetected; int i;

21

// int row_count = 1;

PORTA = 0x20; // disable address decoder //PORTB = 0x00; // Make data port, PortB, an output PORTB = PORTB & 0b00001000; // Make data port, PortB, an output //DDRB = 0xFF; // change port B direction as output DDRB = DDRB | 0b11110111; // change port B direction as output // Rotate the column mask for each interrupt to check the next key if (column_mask == 0b00010000) { // if at end of the cycle

column_mask = 0b10000000; // set column to 1 column_count = 3; // set row to 1 } else {

column_mask >>= 1; // next column column_count-=1; // next row }; //lcd_putchar(column_count + 0x30); //lcd_putchar(column_mask + 0x30); /* if (column_count >= 4) column_count = 1; else column_count+=1; */ // 0b10000000 >> 1 everytime;

column_key_mask = column_mask ^ 0b11111111; // Flip the column mask. column_key_mask = column_key_mask & 0b11110111; // Keep bit 3 to zero

//PORTB = 0b01111111; // output bit pattern to check key -> bit 7 is 0 lineA, check low!! PORTB = PORTB | column_key_mask; Delay(1); PORTA = 0x16; // write to latch PORTA = 0x20; // disable decoder -> address line disable

//PORTB = 0xFF; // PORTB = input -> All high!! PORTB = PORTB | 0b11110111; //DDRB = 0x00; // change directoin port B to input DDRB = DDRB & 0b00001000;

PORTA = 0x1C; // enable input latch -> address line enable Delay(1); KeyValue = PINB; // Read in key value -> read from input letch PORTA = 0x20; // disable address -> address line disable

22

//PORTB = 0x00; // make data port,portB, an output again PORTB = PORTB & 0b00001000; //DDRB = 0xFF; // change port B direction as output DDRB = DDRB | 0b11110111;

//PORTB = 0b11111111; // make output lines all high on keyboard PORTB = PORTB | 0b11110111; Delay(1); // settling time PORTA = 0x16; // write to keyboard latch 0b00010110 PORTA = 0x20; // disable decoder 0b00100000

row_key_mask = 0b00010000; // mask key A first //column = column_count; for (i = 1; i <= 4; i+=1 ) { // check all rows of key press

WhichKey = KeyValue & row_key_mask; // mask off input value, only onebit at a time if (WhichKey == 0) {

KeyDetected = TRUE; // Ture if any key has been pressedcolumn = column_count; // remember which column you are at

// row = row_count; }row_key_mask <<= 1;

}

if (KeyDetected == TRUE) {WhichKey = 0;

// column = column_count;}

switch (KeyState) // to depressed (case 1) with bouncing // back to released (case 0) { case 0: // no key depressed yet {// PORTB = 0; if(WhichKey==0) // key hit detected { NewKey = 1; // put the key pressed into the globe memory KeyNumber = 1; // return key value,dummy for now KeyState = 1; // move to next state KeyCount = 0; // clear bounce counter //column = column_count; /* Decoding the Keypad. Read in the row and column of where the program

23

at and see which key the user has pressed.*/

if ((KeyValue & 0b00010000) == 0) { row = 0;

//TheKey = 0;column = column_count;

}if ((KeyValue & 0b00100000) == 0) {

row = 1;//TheKey = 1;column = column_count;

}

if ((KeyValue & 0b01000000) == 0) { row = 2;

//TheKey = 2; column = column_count;

}

if ((KeyValue & 0b10000000) == 0) { row = 3;

//TheKey = 3; column = column_count;

}

/* if (column_mask == 0b10000000)column = 1;

if (column_mask == 0b01000000)column = 2;

if (column_mask == 0b00100000)column = 3;

if (column_mask == 0b00010000)column = 4; */

} break; } case 1: // key hit previously, wait for release { if(WhichKey != 0) // no key depressed { KeyCount+=1; // increment counter if(KeyCount >= 100) // count how many no key events in a row { KeyState = 0; // key has been really released 200 consecutivetests } }

24

if(WhichKey == 0) // key still depressed or bouncing { KeyCount = 0; break; } } // end case 1 } // end switch

}

// UART Receiver bufferchar rx_buffer[8];volatile unsigned char rx_wr_index,rx_rd_index,rx_counter;// This flag is set on UART Receiver buffer overflowbit rx_buffer_overflow;#pragma used-

// UART Receiver interrupt service routine#pragma savereg-interrupt [UART_RXC] void uart_rx_isr(void){#asm .equ __rx_buffer_size=8

push r26 in r26,sreg push r26 push r27 push r30 push r31#endasm#ifdef _MODEL_TINY_#asm ldi r26,_rx_buffer lds r30,_rx_wr_index add r26,r30 clr r27#endasm#endif#ifdef _MODEL_SMALL_#asm ldi r26,low(_rx_buffer) ldi r27,high(_rx_buffer) lds r30,_rx_wr_index clr r31 add r26,r30 adc r27,r31#endasm#endif#asm

25

in r30,udr st x,r30 lds r30,_rx_wr_index inc r30 cpi r30,__rx_buffer_size brlo __uart_rx_isr0 clr r30__uart_rx_isr0: sts _rx_wr_index,r30 lds r30,_rx_counter inc r30 sts _rx_counter,r30 cpi r30,__rx_buffer_size+1 brlo __uart_rx_isr1#endasmrx_buffer_overflow=1;#asm__uart_rx_isr1: pop r31 pop r30 pop r27 pop r26 out sreg,r26 pop r26#endasm}#pragma savereg+

#ifndef _DEBUG_TERMINAL_IO_// Get a character from the UART Receiver buffer#define _ALTERNATE_GETCHAR_#pragma warn-#pragma used+char getchar(void){#asm lds r30,_rx_counter tst r30 breq _getchar#endasm#ifdef _MODEL_TINY_#asm ldi r26,_rx_buffer lds r30,_rx_rd_index add r26,r30 clr r27#endasm#endif#ifdef _MODEL_SMALL_#asm ldi r26,low(_rx_buffer)

26

ldi r27,high(_rx_buffer) lds r30,_rx_rd_index clr r31 add r26,r30 adc r27,r31#endasm#endif#asm inc r30 cpi r30,__rx_buffer_size brlo __getchar0 clr r30__getchar0: sts _rx_rd_index,r30 ld r30,x cli lds r26,_rx_counter dec r26 sts _rx_counter,r26 sei#endasm}#pragma used-#ifdef _WARNINGS_ON_#pragma warn+#endif#endif

#pragma used+// UART Transmitter bufferchar tx_buffer[8];volatile unsigned char tx_wr_index,tx_rd_index,tx_counter;#pragma used-// UART Transmitter interrupt service routine#pragma savereg-interrupt [UART_TXC] void uart_tx_isr(void){#asm .equ __tx_buffer_size=8

push r26 in r26,sreg push r26 lds r26,_tx_counter tst r26 breq __uart_tx_isr1 dec r26 sts _tx_counter,r26 push r27 push r30 push r31

27

#endasm#ifdef _MODEL_TINY_#asm ldi r26,_tx_buffer lds r30,_tx_wr_index add r26,r30 clr r27#endasm#endif#ifdef _MODEL_SMALL_#asm ldi r26,low(_tx_buffer) ldi r27,high(_tx_buffer) lds r30,_tx_wr_index clr r31 add r26,r30 adc r27,r31#endasm#endif#asm inc r30 cpi r30,__tx_buffer_size brlo __uart_tx_isr0 clr r30__uart_tx_isr0: sts _tx_wr_index,r30 ld r30,x out udr,r30 pop r31 pop r30 pop r27__uart_tx_isr1: pop r26 out sreg,r26 pop r26#endasm}#pragma savereg+

#ifndef _DEBUG_TERMINAL_IO_// Write a character to the UART Transmitter buffer#define _ALTERNATE_PUTCHAR_#pragma warn-#pragma used+void putchar(char c){#asm lds r30,_tx_counter cpi r30,__tx_buffer_size brsh _putchar tst r30

28

brne __putchar00 sbis usr,udre rjmp __putchar00 ld r30,y out udr,r30 rjmp __putchar03__putchar00:#endasm#ifdef _MODEL_TINY_#asm ldi r26,_tx_buffer lds r30,_tx_rd_index add r26,r30 clr r27#endasm#endif#ifdef _MODEL_SMALL_#asm ldi r26,low(_tx_buffer) ldi r27,high(_tx_buffer) lds r30,_tx_rd_index clr r31 add r26,r30 adc r27,r31#endasm#endif#asm inc r30 cpi r30,__tx_buffer_size brlo __putchar01 clr r30__putchar01: sts _tx_rd_index,r30 ld r30,y st x,r30 cli lds r30,_tx_counter inc r30 sts _tx_counter,r30 sei__putchar03:#endasm}#pragma used-#ifdef _WARNINGS_ON_#pragma warn+#endif#endif

// Standard Input/Output functions#include <stdio.h>

29

// Timer 0 overflow interrupt service routineinterrupt [TIM0_OVF] void timer0_ovf_isr(void){// Reinitialize Timer's 0 value//TCNT0=0x10;// Place your code here

four_sec_cycle--; TCNT0 = 0xF8; // reload timer, should give 965 HZ

// Check_Key(); // go read keypad for "A" key depressed /* if (lock_status == 0) { PORTD.6 = 0; }*/ if (four_sec_cycle == 0){ PORTD.4 = !PORTD.4; //lock_status = TRUE;

four_sec_cycle = 100;}

//TCNT0 = 0xF8; // reload timer, should give 965 HZ Check_A_Key(); // go read keypad for "A" key depressed // user inserts lots of code here cprev = c; // Keep the previous position PORTA = 0x07; // Place encoder chip bits on the data bus for(d=0; d < 1; d++){} // delay for bus settling

c = PINC; // Read the encoderPORTA = 0x20; // Disable

// Compute change in position keeping track of rollover delta = (int)c - (int)cprev;

if(delta > 127) {

delta = delta - 256;}if(delta < -127) { delta = delta + 256; }

// Update the global position global = global + delta;

// Desired Positionr = R;

// Errore = r - global;

30

// Manipulationm = (unsigned char)(kc*e + 127);

PORTC = m; // Write manipulation to PortCPORTA = 0x00; // Output to DACfor(d=0; d < 1; d++){} // delay for bus settlingPORTA = 0x20; // Disable

}

void Reset_Encoder(void){ PORTA = 0x04; //pull encoder reset line low PORTA = 0x20; //pull back high}

// Declare your global variables herevoid WriteToSerial(char char_out) { PORTA = 0x20; // disable address decoder //Delay(1); // settling time //PORTB = 0x00; // Make data port, PortB, an output PORTB = 0b00001000; // Change Serial port Direction // by changing PortB bit 3 //DDRB = 0xFF; // change port B direction as output // DDRB = DDRB | 0b00001000; // change port B direction as output PORTA = 0x16; // write to latch // Delay(1); // settling time PORTA = 0x20; // disable decoder -> address line disable// Delay(1);

putchar(char_out); Delay(2000); // wait until all char are sent

PORTB = 0b00000000; // Change Serial port Direction to listen again PORTA = 0x16; // write to latch

//DDRB = DDRB & 0b11110111; // change port B direction as input //DDRB = 0b00000000; // change port B direction as input// PORTA = 0x1C; // enable input latch -> address line enable Delay(1); PORTA = 0x20;// getchar();} void WriteToSerial2(void) {

// putchar(0xC0);

31

// Delay(1); // wait until all char are sent// char_out = 0x2; // putchar(0x02);// putchar(0x1);// Delay(1); // wait until all char are sent// char_out = getchar() + 0x30;// lcd_putchar(char_out); putchar(sensor_data1); putchar(sensor_data2); putchar(sensor_data3); putchar(sensor_data4); putchar(sensor_data5);

Delay(5); correction = getchar(); R = correction;

}

void main(void){// Declare your local variables here

// Input/Output Ports initialization// Port A/*PORTA=0x00;DDRA=0x00; */

// Port B/*PORTB=0x00;DDRB=0x00; */

// Port C/*PORTC=0x00;DDRC=0x00; */

//char *p_message = "Oh Boy";// Declare your local variables hereint x_post = 0;int y_post = 0;

// Input/Output Ports initialization// Port APORTA=0x00;DDRA=0x3F;

// Port BPORTB=0xFF;DDRB=0xFF;

32

// Port CPORTC=0x00;DDRC=0xFF;

// Port DPORTD=0x00;DDRD=0x00;

// Timer/Counter 0 initialization// Clock source: System Clock// Clock value: Timer 0 Stopped// Mode: Output Compare// OC0 output: Disconnected//TCCR0=0x00;//TCNT0=0x10;TCCR0=0x05;TCNT0=0xF8;

// Timer/Counter 1 initialization// Clock source: System Clock// Clock value: Timer 1 Stopped// Mode: Output Compare// OC1A output: Discon.// OC1B output: Discon.// Noise Canceler: Off// Input Capture on Falling EdgeTCCR1A=0x00;TCCR1B=0x00;TCNT1H=0x00;TCNT1L=0x00;OCR1AH=0x00;OCR1AL=0x00;OCR1BH=0x00;OCR1BL=0x00;

// Timer/Counter 2 initialization// Clock source: System Clock// Clock value: Timer 2 Stopped// Mode: Output Compare// OC2 output: DisconnectedTCCR2=0x00;ASSR=0x00;TCNT2=0x00;OCR2=0x00;

// External Interrupt(s) initialization// INT0: Off// INT1: OffGIMSK=0x00;

33

MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initializationTIMSK=0x01;

// UART initialization// Communication Parameters: 8 Data, 1 Stop, No Parity// UART Receiver: On// UART Transmitter: On// UART Baud rate: 9600UCR=0xD8;UBRR=0x33;

// Analog Comparator initialization// Analog Comparator: Off// Analog Comparator Input Capture by Timer/Counter 1: OffACSR=0x80;

// LCD module initializationlcd_init();

// Global enable interrupts#asm("sei")

PORTA = 0x20; // disable address linesPORTD.4 = 1;lcd_init();lcd_clear();lcd_gotoxy(0,0);//lcd_putchar(keypad_layout[0][0]);//x_post = 1;KeyState = 0; // status of keyboard state machine//NewKey = 0;//getchar();//rx_counter = 0;

four_sec_cycle = 4;

PORTA = 0x20; // disable address lines Reset_Encoder(); KeyState = 0; // status of keyboard state machinec = 0;cprev = 0;R = 0;global = 0;

while (1) {

char var_code; Check_Key(); // go read keypad for "A" key depressed

if(NewKey == 1) {

34

// lcd_clear();// lcd_gotoxy(x_post,0);// lcd_putchar(TheKey + 0x30);// lcd_putchar(column + 0x30);// lcd_putchar(row + 0x30);

NewKey = 0; // clearing key state

// x_post+=2; if (keypad_layout[row][column] == 'A') { // Clear screen

lcd_clear(); x_post = 0;y_post = 0;var_code = 1;WriteToSerial2(var_code);//KeyNumber = (unsigned char)getchar();//lcd_putchar(KeyNumber);

}

if (keypad_layout[row][column] == 'D') { // Move down if pressedx_post-=1;y_post+=1;//lock_status = 1;//four_sec_cycle = 4;PORTD.4 = !PORTD.4;

}else if (keypad_layout[row][column] == 'C') {

x_post-=1;y_post-=1;

}else if (keypad_layout[row][column] != 'A') {

lcd_gotoxy(x_post,y_post);lcd_putchar(keypad_layout[row][column]);//TheKey = keypad_layout[row][column];x_post+=1;

} //WriteToSerial(keypad_layout[row][column]);

}

sensor_data1 = PORTD.1;sensor_data2 = PORTD.2;sensor_data3 = PORTD.3;seneor_data4 = PORTD.4;sensor_data5 = PORTD.5;

WriteToSerial2();

/* if (rx_counter) {TheKey = (unsigned char)getchar();

lcd_putchar(TheKey); // lcd_putchar(getchar());

35

// lcd_putchar('Q'); //KeyNumber = getchar();

//lcd_putchar(KeyNumber);

//x_post+=1;} */

else if(rx_counter) { // Get the character from the receive buffer

KeyNumber = (unsigned char)getchar();

// Output the character to the LCDlcd_putchar(KeyNumber);

} //lcd_putchar(15 + 0x30); //lcd_puts(p_message); //lcd_clear(); //lcd_putchar("A"); //lcd_gotoxy(0,1); //lcd_putsf(" oh boy");

}; // end while}

ECE/CS/ME 539 - Introduction to Artificial Neural Networks and Fuzzy SystemsFinal Project

Instructor: Prof. Yu Hen Hu

Prepared by: Ray TangUW ID: 9013634614

E-mail: [email protected]: 25 October 2001