Last active 2 weeks ago

Revision 16d0da57290e3a288ce0a1fdd524e19cf45801d5

Lab7 code.cpp Raw
1///////////////////////////////////////////////////////////////////////////////////////////////
2// SINEIO
3///////////////////////////////////////////////////////////////////////////////////////////////
4
5#define _CRT_SECURE_NO_WARNINGS
6#define _USE_MATH_DEFINES // for C++
7#include <cmath>
8#include <time.h>
9#include <fstream>
10#include "IIRdf1filt.h"
11#include "../myWin826.h"
12#include "../826api.h"
13#include "../RealTime.h"
14
15#define SAMPLE_RATE 1000 // Hz
16#define MAX_LOOP_TIME 2 //seconds
17#define RECORD_LENGTH (MAX_LOOP_TIME*SAMPLE_RATE)
18
19
20// IO card configuration constants
21#define IO_BOARD_NUM 0 // no change
22#define ADC_SLOT 0 // no change
23
24#define DAC_ZERO_OUTPUT 0x8000
25#define DAC_CONFIG_GAIN S826_DAC_SPAN_10_10 // -10 to 10 spans 20 volts so...
26#define DAC_VRANGE 20.0 // This MUST correspond to the DAC_SPAN just above
27#define DAC_CNT_RANGE 0xFFFF // 16-bit DAC
28#define DAC_OFFSET_COUNTS 0x8000 // 32768 offset for a signed desired output mapped to unsigned DAC write.
29
30#define DAC_CHANNEL 1 // SET ME! CHECK YOUR SETUP: DAC channel output
31
32#define ADC_CHANNEL 0 // SET ME! CHECK YOUR SETUP: analog input channel to track
33
34
35#define ADC_CNT_RANGE 0xFFFF // 2^16= 0xFFFF (16 bit converter)
36#define ADC_GAIN S826_ADC_GAIN_1 // -10 to 10 option
37#define ADC_VRANGE 20 // this must correspond to gain setting
38
39
40#define ADC_ENABLE 1
41
42
43#define SINE_FREQ 5.0 // Hz
44#define SINE_MAG 250 // counts
45
46/* Coeficients for your second-order filter from matlab (Butter() or other IIR filter... */
47/* These are junk values so replace with your design */
48const double a[] = { 1.000000000000000, -1.991114292201654, 0.991153595868935 };
49const double b[] = { 0.995566972017647, -1.991133944035295, 0.995566972017647 };
50
51int main()
52{
53 int errcode = S826_ERR_OK;
54 int boardflags = S826_SystemOpen(); // open 826 driver and find all 826 boards
55 int ncount = 0;
56 uint dacout;
57
58 double voltageout = 0;
59
60 double Amp = 0;
61 double Frequency = 0;
62
63
64 double Ti = 0;
65 double Td = 0;
66 double Kp = 0.008; // Proportional gain
67 double Ki = 0;//Kp/Ti; // Integral gain
68 double Kd = 0;//Kp*Td; // Derivative gain
69 int current_position = 0; // Actual position from encoder
70 double ref_position = 0; // Desired position
71 int error = 0; // Control error
72 double error_derivative = 0; // Derivative of error
73 double integrated_error = 0; // Integral of error
74 int previous_error = 0; // Previous error for derivative calculation
75 char key = '0'; // Keyboard input
76
77 double t = 0; // time variable for sine wave
78
79 // Data collection variables
80 int data_log[2000];
81 int ref_log[2000]; // track position reference
82 int log_index = 0;
83
84 // encoder interface
85 uint start_count;
86 uint counts;
87 int rawcounts[RECORD_LENGTH];
88 double filtcounts[RECORD_LENGTH];
89
90 // real-time filter
91 int N = sizeof(a) / sizeof(double); // number of a's and b's. filter order plus 1.
92 IIRdf1filt filter(N, a, b); // instantiate and initialize the filter
93
94 // file output
95 int i;
96 char outfileName[30];
97
98 counts = 0;
99
100 // instantiate our "real time" object that will pace our loop
101 RealTime realTime(SAMPLE_RATE);
102
103 // Configure data acquisition interfaces and start them running.
104 X826(S826_AdcSlotConfigWrite(IO_BOARD_NUM, ADC_SLOT, ADC_CHANNEL, 0, ADC_GAIN)); // program adc timeslot attributes: slot, chan, 0us settling time. For -5V-5V use: "S826_ADC_GAIN_2"
105 X826(S826_AdcSlotlistWrite(IO_BOARD_NUM, 1 << ADC_SLOT, S826_BITWRITE)); // enable adc timeslot; disable all other slots
106 X826(S826_AdcEnableWrite(IO_BOARD_NUM, ADC_ENABLE)); // enable adc conversions
107 X826(S826_DacRangeWrite(IO_BOARD_NUM, DAC_CHANNEL, DAC_CONFIG_GAIN, 0)); // program dac output range: -10V to +10V
108
109 // Initialize Motor Shaft Encoder Interface
110 S826_CounterModeWrite(0, 0, S826_CM_K_QUADX1); // Configure counter0 as incremental encoder interface.
111 S826_CounterStateWrite(0, 0, 1); // Start tracking encoder position.
112 S826_CounterRead(0, 0, &start_count); // Read initial encoder counts
113
114 // commence pseudo-real-time loop.
115 realTime.Start();
116
117 while (key != 'q')
118 {
119 // Calculate current time 't'
120 t = (double)ncount / SAMPLE_RATE;
121
122 // Generate sine wave signal
123 ref_position = SINE_MAG * sin(2.0 * M_PI * SINE_FREQ * t);
124
125 // scale the desired voltage to the DAC integer output.
126 dacout = (uint)(voltageout * (DAC_CNT_RANGE / DAC_VRANGE) + DAC_OFFSET_COUNTS);
127
128 // output to the DAC
129 X826(S826_DacDataWrite(IO_BOARD_NUM, DAC_CHANNEL, dacout, 0));
130
131 S826_CounterRead(0, 0, &counts); // Read current encoder counts.
132 counts = counts - start_count; // Subtracting the initial counts so we begin from 0
133
134 error = (int)ref_position - counts;
135 integrated_error += error * (1.00 / SAMPLE_RATE);
136 error_derivative = (error - previous_error) / (1.00 / SAMPLE_RATE);
137 previous_error = error;
138 voltageout = Kp * error + Kd * error_derivative + Ki * integrated_error;
139
140 //Saftey
141 if (voltageout > 10.0) voltageout = 10.0;
142 if (voltageout < -10.0) voltageout = -10.0;
143
144 // 1. Read Keyboard Input
145 if (_kbhit()) // if you hit a key keyboard then read input
146 {
147 key = _getch();
148 if (key == 'M') ref_position += 500; // 'right arrow key' increments ref
149 else if (key == 'K') ref_position -= 500; // 'left arrow key' decrements ref ;
150 }
151
152 if (log_index < 2000) {
153 data_log[log_index] = counts;
154 ref_log[log_index] = (int)ref_position;
155 log_index++;
156 }
157
158 realTime.Sleep();
159 ncount++;
160 }
161
162 realTime.Stop(ncount); // stop real-time loop
163
164 X826(S826_DacDataWrite(IO_BOARD_NUM, DAC_CHANNEL, DAC_ZERO_OUTPUT, 0)); // put to zero at the end
165 S826_SystemClose();
166
167 // file output
168 printf("\nType in a file name (freq_amp like 50_10 for 5Hz, 1V is a good idea):\n");
169 scanf("%s", outfileName);
170
171 std::ofstream outfile(strcat(outfileName, ".txt")); // our test file to filter
172
173 outfile << "Counts,Reference:\n";
174 //outfile << Frequency << "," << Amp << "\n";
175
176 // Write raw data to first column of output file
177 for (i = 0; i < log_index; i++)
178 {
179 outfile << data_log[i] << "," << ref_log[i] << "\n";
180 }
181
182 outfile.close();
183
184 return 0;
185}