-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSolarTracker.vhd
More file actions
240 lines (204 loc) · 5.92 KB
/
SolarTracker.vhd
File metadata and controls
240 lines (204 loc) · 5.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
-- FPGA FINAL PROJECT
-- SOLAR TRACKING SYSTEM
-- 12/9/14
-- KRUNAL BHARGAV
-- NABIL MOHAMMAD
-- MICKEY YEUNG
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY Phototest IS
PORT (
KEY: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
CLOCK_50: IN STD_LOGIC;
GPIO: INOUT STD_LOGIC_VECTOR(30 DOWNTO 0);
HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7: OUT STD_LOGIC_VECTOR(0 TO 6);
LEDR: OUT STD_LOGIC_VECTOR(18 DOWNTO 0);
LEDG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
--GPIO LIST:
--2 - SERVO 1 (pulse width)
--3 - SERVO 2
--11-4 - ADC 1 input photo resistor (bphoto1)
--19-12- ADC 2 input photo resistor
--22-20 ADC 1 - shared
--26 - ADC CLOCK Driver - shared
--28 ALE - shared
--29 EOC - 1
--30 EOC - 2
END ENTITY;
ARCHITECTURE rtl of Phototest IS
SIGNAL CLK, RESET, DONE: STD_LOGIC; -- SERVO MOTORS ADJUST ON RISING EDGE OF 'DONE'
SIGNAL EOC1, EOC2: STD_LOGIC; -- END OF CONVERSION SIGNAL INPUT FROM ADC
SIGNAL ADC_DRIVER: INTEGER RANGE 0 TO 78:= 0; -- ADC CLOCK
SIGNAL counter: INTEGER RANGE 0 TO 1000000:= 0; -- PWM FOR CLOCK
SIGNAL SECOND: INTEGER RANGE 0 TO 1000000:= 0; -- STATE CLOCK
SIGNAL PULSE_WIDTH1: INTEGER RANGE 49999 TO 120001:= 75000; -- PULSE WIDTH FOR SERVO 1
SIGNAL PULSE_WIDTH2: INTEGER RANGE 49999 TO 120001:= 75000; -- PULSE WIDTH FOR SERVO 1
SIGNAL B_PHOTO_L1, B_PHOTO_R1: STD_LOGIC_VECTOR(7 DOWNTO 0); -- PHOTORESISTOR VALUES IN BINARY
SIGNAL B_PHOTO_L2, B_PHOTO_R2: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL D_PHOTO_L1, D_PHOTO_R1: INTEGER RANGE 0 TO 255; -- PHOTORESISTOR VALUES IN DECIMAL
SIGNAL D_PHOTO_L2, D_PHOTO_R2: INTEGER RANGE 0 TO 255;
TYPE count_state IS (stop, read_left, read_right, adjust); -- STATE MACHINE
SIGNAL present_state, next_state : count_state;
ATTRIBUTE syn_encoding : string;
ATTRIBUTE syn_encoding OF count_state : TYPE IS "00 01 10 11";
BEGIN
RESET <= KEY(1);
EOC1 <= GPIO(29);
EOC2 <= GPIO(30);
-- PRESENT STATE PROCESS BLOCK
PROCESS(CLK)
BEGIN
IF RESET = '0' THEN
present_state <= stop;
ELSIF (rising_edge(CLK)) THEN
present_state <= next_state;
END IF;
END PROCESS;
--NEXT STATE PROCESS BLOCK (ADC CONTROLS, AND DATA)
PROCESS(present_state, EOC1, EOC2, CLOCK_50, B_PHOTO_L1, B_PHOTO_R1, B_PHOTO_L2, B_PHOTO_R2)
BEGIN
CASE present_state IS
WHEN stop =>
DONE <= '0';
next_state <= read_left;
WHEN read_left =>
GPIO(22 DOWNTO 20) <= "000"; -- SELECT LINE = 0 ON BOTH ADCs
--READS LEFT PHOTORESISTOR OF BOTH SERVO MOTORS
IF(EOC1 = '1') THEN
B_PHOTO_L1(7 DOWNTO 0) <= GPIO(11 DOWNTO 4);
END IF;
IF(EOC2 = '1') THEN
B_PHOTO_L2(7 DOWNTO 0) <= GPIO(19 DOWNTO 12);
END IF;
next_state <= read_right;
WHEN read_right =>
GPIO(22 DOWNTO 20) <= "111"; -- SELECT LINE = 7 ON BOTH ADCs
--READS RIGHT PHOTORESISTOR OF BOTH SERVO MOTORS
IF(EOC1 = '1') THEN
B_PHOTO_R1(7 DOWNTO 0) <= GPIO(11 DOWNTO 4);
END IF;
IF(EOC2 = '1') THEN
B_PHOTO_R2(7 DOWNTO 0) <= GPIO(19 DOWNTO 12);
END IF;
next_state <= adjust;
WHEN adjust =>
--ALLOW SERVO ADJUSTMENT
DONE <= '1';
--CONVERT BINARY TO INTEGER (PHOTORESISTOR VALUES)
D_PHOTO_L1 <= CONV_INTEGER(B_PHOTO_L1(7 DOWNTO 0));
D_PHOTO_R1 <= CONV_INTEGER(B_PHOTO_R1(7 DOWNTO 0));
D_PHOTO_L2 <= CONV_INTEGER(B_PHOTO_L2(7 DOWNTO 0));
D_PHOTO_R2 <= CONV_INTEGER(B_PHOTO_R2(7 DOWNTO 0));
next_state <= stop;
END CASE;
END PROCESS;
--ADC DRIVER
PROCESS (ADC_DRIVER, CLOCK_50)
BEGIN
IF(rising_edge(CLOCK_50)) THEN
IF(ADC_DRIVER< 39) THEN
GPIO(26) <= '0';
ELSE
GPIO(26) <= '1';
END IF;
END IF;
END PROCESS;
-- STATE TIMER
PROCESS (SECOND, CLOCK_50)
BEGIN
IF(rising_edge(CLOCK_50)) THEN
IF(SECOND < 500000) THEN
CLK <= '0';
ELSE
CLK <= '1';
END IF;
END IF;
END PROCESS;
--50MHz CLOCK ADDER
PROCESS(CLOCK_50)
BEGIN
IF (CLOCK_50 = '1' AND CLOCK_50'EVENT) THEN
counter <= counter + 1;
ADC_DRIVER <= ADC_DRIVER + 1;
SECOND <= SECOND + 1;
END IF;
END PROCESS;
-- SERVO 1 MOTOR SIGNAL
PROCESS (CLOCK_50,counter, PULSE_WIDTH1)
BEGIN
IF(rising_edge(CLOCK_50)) THEN
IF(counter < PULSE_WIDTH1) THEN
GPIO(2) <= '1';
ELSE
GPIO(2) <= '0';
END IF;
END IF;
END PROCESS;
-- SERVO 2 MOTOR SIGNAL
PROCESS (CLOCK_50, counter, PULSE_WIDTH2)
BEGIN
IF(rising_edge(CLOCK_50)) THEN
IF(counter < PULSE_WIDTH2) THEN
GPIO(3) <= '1';
ELSE
GPIO(3) <= '0';
END IF;
END IF;
END PROCESS;
-- SERVO 1 FEEDBACK CONTROLS
PROCESS(DONE, PULSE_WIDTH1, D_PHOTO_L1, D_PHOTO_R1)
BEGIN
IF (rising_edge(DONE)) THEN
IF(D_PHOTO_L1 > D_PHOTO_R1 + 5) THEN -- plus 30 error
IF(PULSE_WIDTH1 < 117500) THEN
PULSE_WIDTH1 <= PULSE_WIDTH1 + 2500;
ELSE
PULSE_WIDTH1 <= PULSE_WIDTH1;
END IF;
ELSIF(D_PHOTO_R1 > D_PHOTO_L1 + 5) THEN -- plus 30 error
IF(PULSE_WIDTH1 > 52500) THEN
PULSE_WIDTH1 <= PULSE_WIDTH1 - 2500;
ELSE
PULSE_WIDTH1 <= PULSE_WIDTH1;
END IF;
ELSE
PULSE_WIDTH1 <= PULSE_WIDTH1;
END IF;
END IF;
END PROCESS;
-- SERVO 2 FEEDBACK CONTROLS
PROCESS(DONE, PULSE_WIDTH2, D_PHOTO_L2, D_PHOTO_R2)
BEGIN
IF (rising_edge(DONE)) THEN
IF(D_PHOTO_L2 > D_PHOTO_R2 + 5) THEN -- plus 5 error term
IF(PULSE_WIDTH2 < 115000) THEN
PULSE_WIDTH2 <= PULSE_WIDTH2 + 5000;
ELSE
PULSE_WIDTH2 <= PULSE_WIDTH2;
END IF;
ELSIF(D_PHOTO_R2 > D_PHOTO_L2 + 5) THEN -- plus 5 error term
IF(PULSE_WIDTH2 > 55000) THEN
PULSE_WIDTH2 <= PULSE_WIDTH2 - 5000;
ELSE
PULSE_WIDTH2 <= PULSE_WIDTH2;
END IF;
ELSE
PULSE_WIDTH2 <= PULSE_WIDTH2;
END IF;
END IF;
END PROCESS;
-- ALE (ADDRESS LATCH ENABLE) FOR ADC CONTROL
PROCESS(SECOND)
BEGIN
IF(rising_edge(CLOCK_50)) THEN
IF( SECOND < 15) THEN
GPIO(28) <= '1';
ELSE
GPIO(28) <= '0';
END IF;
END IF;
END PROCESS;
END rtl;