-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathv5_main.c
341 lines (306 loc) · 13.1 KB
/
v5_main.c
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*
*
*
* Created on: Nov 13, 2019
* Author: roessing
*/
#include <v5_main.h>
volatile unsigned char DEST_ADDR_high = 0;
volatile unsigned char DEST_ADDR_low = 0;
volatile unsigned char message[MESSAGE_LENGTH];
volatile unsigned char dataID = 0;
volatile unsigned char delay = 0;
volatile unsigned char set_up = 0;
volatile unsigned char mode = 0;
volatile unsigned int running = 0;
volatile int pos = -1;
volatile int timeout = 0;
volatile signed short int mem[NUM];
/*!
* sets up the output ports and pins for startup of a pAMeter
*/
void port_setup()
{
I2CIE set_low RXRDYIE;
relay_setup();
adc_setup();
temperature_sensor_setup();
xbee_setup();
/* LED */
P6DIR |= DEBUG_LED_BITS;
/* Global interrupt enable, start watchdog*/
_EINT();
IE1 &= ~WDTIE;
WDTCTL = WDTPW + WDTHOLD;
/*Set 10 mA mode */
set_mode(0);
Reed_setup();
}
void debug_led_on()
{
P6OUT |= DEBUG_LED_BITS;
}
void debug_led_off()
{
P6OUT &= ~DEBUG_LED_BITS;
}
/*!
* lets the led blink a set number of times
* \param cycles number of blinks
* \param time time between switching
*/
void blink_led(int cycles, int time)
{
int j;
for (j = cycles; j > 0; j--) {
debug_led_on();
wait(time);
debug_led_off();
wait(time);
}
}
/*!
* Controlls the program flow. A flow diagram can be found below. In contrast to the old firmware this one is optimized for a fast data taking.
* The ADC is capable to do 500 ksamples per second.
* The seperation in taking data long and taking data short is done to avoid a repetetive use of an if statement costing valuable computing time.
*
*/
void main(void){
running=1;
WDTCTL = WDTPW + WDTHOLD; // stop watchdog for setup
clock_setup();
port_setup();
usart_setup();
//setup_temperature_sensor();
debug_led_on();
WDTCTL = WDTPW + WDTHOLD; // stop watchdog for setup
MODE_RELAY_PORT_dir = 0xFF;
IE1 enable URXIE0;
U0TCTL enable URXSE;
_EINT();
WDTCTL = WDT_ARST_1000;
IFG1 = 0;
set_up = 0x00;
SLEEP(0);
/* Timer initialization for taking data acquisition time */
TBCTL = CNTL_0 + TBSSEL_1 + ID_3 + MC_2; //Counter length 16bit, Clock ACLK, Divider 1/8, Mode control continuous
while(!set_up){};//interrupted by usart interrupt
while(1){
if(dataID==0x00) taking_data_short();
else taking_data_long();
}
debug_led_on();
}
/*!
* regulates the data taking if only the mean values are to be transmitted (so dataFormat is 0), a flow diagram can be found below.
* The function taking_data_long() is basically analog to this, just sends out the 128 intermediate values as well.
*/
void taking_data_short(){
volatile unsigned char data[LENGTH];
volatile int CYCLE_COUNTER=999;
unsigned long int Counter_B_value;
volatile stat_t temperature;
int temp;
while (1) {
SLEEP(1);
WDTCTL = WDT_ARST_1000; // watchdog now supervises correct measurement procedure
/* Blinking, shows current mode*/
if(CYCLE_COUNTER>=100/delay){
int i;
for (i = 0; i < mode; i++) {
WDTCTL = WDT_ARST_1000;
temperature_sensor_write(0x03, 0xA0, 1);
debug_led_on();
wait(300);
//WDTCTL = WDT_ARST_1000;
debug_led_off();
wait(300);
}
if (!(temp = temperature_sensor_read(0x00, 2)))
temperature=255;
if (temp > 0) {
temperature = temp / 128.;
} else {
temperature = (temp - 65536.) / 128.;
}
CYCLE_COUNTER=0;
}else{ wait(130*(delay-1)); }
// port2_out set_low pin1;
//wait(500);
WDTCTL = WDT_ARST_1000;
timeout = 0;
//setting up timer B to measure the time of data aquisition
TBCTL &= ~(MC_2); //stop counter (if it is accidentially running)
TBR = 0; //set counter 0
TBCTL |= MC_2; //start counter in continuos mode
for (pos = 0; pos < NUM ; /* pos++ by ISR */) {
WDTCTL = WDT_ARST_250;
ADC_PORT_out set_high ADC_CNV;
ADC_PORT_out set_low ADC_CNV;
__delay_cycles(10);
mem[pos++] = clock_bits(0x0000, 16);
}
WDTCTL = WDT_ARST_1000;
/* Data taking finished now prepare and send data*/
/* Stop counter after ADC has finished and calculate time */
TBCTL &= ~(MC_2); //stop counter
Counter_B_value = (unsigned long int)TBR; //write counter value to variable
TBR = 0;
TBCTL |= MC_2; //immediately start again for measurement of time until sending
stat_t time_ADC = (stat_t)Counter_B_value / (stat_t)32768 * 8.0; //calculating time from the counted clock cycles
WDTCTL = WDT_ARST_250;
if (timeout) {
/* ADC did not respond*/
*((stat_t*)&data[0]) = NAN;
*((stat_t*)&data[sizeof(stat_t)]) = NAN;
*((unsigned char*)&data[2 * sizeof(stat_t)]) = mode;
*((stat_t*)&data[2 * sizeof(stat_t) + sizeof(unsigned char)]) = 0; //measurement time
*((unsigned char*)&data[4 * sizeof(stat_t) + sizeof(unsigned char)]) = temperature;
*((unsigned char*)&data[5 * sizeof(stat_t) + 1 * sizeof(unsigned char)]) = 0; //remaining TX
} else {
WDTCTL = WDT_ARST_250;
stat_t m, error;
/* Mean */
m = mean(mem, NUM);
/* Error */
error = sd(mem, m, NUM);
*((stat_t*)&data[0]) = m;
*((stat_t*)&data[sizeof(stat_t)]) = error;
*((unsigned char*)&data[5 * sizeof(stat_t)]) = mode;//nolonger necessary
*((stat_t*)&data[2 * sizeof(stat_t)]) = time_ADC; //ADC meas. time for 128 values. Time until sending calculated shortly before sending
*((stat_t*)&data[4 * sizeof(stat_t)]) = temperature;
*((unsigned char*)&data[5 * sizeof(stat_t) + 2 * sizeof(char)]) = 0;
}
WDTCTL = WDT_ARST_1000;
if (!timeout) {
/* Wake XBEE and wait with a timer for its resurrection (after 13.2ms for some reason) */
SLEEP(0);
//debug_led_on();
wait(14);
//debug_led_off();
/* measure time before sending to reconstruct time of measuring events */
TBCTL &= ~(MC_2); //stop counter
Counter_B_value = (unsigned long int)TBR; //write counter value to variable
stat_t time_send = (stat_t)Counter_B_value / (stat_t)32768 * 8.0; // *8 due to CLK divider of 1/8 (set by ID_3)
*((stat_t*)&data[3 * sizeof(stat_t)]) = time_send; //ADC meas. time for 128 values
/* TX request: (mean value | error | mode | time | number of remaining TXs) */
tx_request(data, LENGTH, DEST_ADDR_high, DEST_ADDR_low);
SLEEP(1); //next ADC reset follows at the beginning of the while(true) loop
}
CYCLE_COUNTER++;
}
}
inline void taking_data_long(){
volatile unsigned char data[LENGTH];
volatile unsigned char rawdata1[RAW_NUM*sizeof(short)];
volatile unsigned char rawdata2[RAW_NUM*sizeof(short)];
volatile unsigned char rawdata3[RAW_NUM*sizeof(short)];
volatile unsigned char rawdata4[RAW_NUM*sizeof(short)];
volatile int CYCLE_COUNTER=0;
unsigned long int Counter_B_value;
volatile stat_t temperature;
int temp;
while (1) {
WDTCTL = WDT_ARST_1000; // watchdog now supervises correct measurement procedure
/* Blinking, shows current mode*/
if(CYCLE_COUNTER>=16){
int i;
for (i = 0; i < mode; i++) {
WDTCTL = WDT_ARST_1000;
temperature_sensor_write(0x03, 0xA0, 1);
debug_led_on();
wait(300);
debug_led_off();
wait(300);
}
if (!(temp = temperature_sensor_read(0x00, 2)))
temperature=255;
if (temp > 0) {
temperature = temp / 128.;
} else {
temperature = (temp - 65536.) / 128.;
}
CYCLE_COUNTER=0;
}
WDTCTL = WDT_ARST_1000;
timeout = 0;
WDTCTL = WDT_ARST_1000;
//temperature = get_temperature();
//get current values, takes approx 60ms per value times 128 values=8s
//setting up timer B to measure the time of data aquisition
TBCTL &= ~(MC_2); //stop counter (if it is accidentially running)
TBR = 0; //set counter 0
TBCTL |= MC_2; //start counter in continuos mode
for (pos = 0; pos < NUM ; /* pos++ by ISR */) {
WDTCTL = WDT_ARST_1000;
ADC_PORT_out set_high ADC_CNV;
ADC_PORT_out set_low ADC_CNV;
mem[pos++] = clock_bits(0x0000, 16);
}
WDTCTL = WDT_ARST_1000;
/* Data taking finished now prepare and send data*/
/* Stop counter after ADC has finished and calculate time */
TBCTL &= ~(MC_2); //stop counter
Counter_B_value = (unsigned long int)TBR; //write counter value to variable
TBR = 0;
TBCTL |= MC_2; //immediately start again for measurement of time until sending
stat_t time_ADC = (stat_t)Counter_B_value / (stat_t)32768 * 8.0; //calculating time from the counted clock cycles
//temperature = (temperature + get_temperature()) / 2;
WDTCTL = WDT_ARST_250;
if (timeout) {
/* ADC did not respond, happens on overflow or floating gates */
*((stat_t*)&data[0]) = NAN;
*((stat_t*)&data[sizeof(stat_t)]) = NAN;
*((unsigned char*)&data[2 * sizeof(stat_t)]) = mode;
*((stat_t*)&data[2 * sizeof(stat_t) + sizeof(unsigned char)]) = 0; //measurement time
*((unsigned char*)&data[4 * sizeof(stat_t) + sizeof(unsigned char)]) = temperature;
*((unsigned char*)&data[5 * sizeof(stat_t) + 1 * sizeof(unsigned char)]) = 0; //remaining TX
} else {
WDTCTL = WDT_ARST_250;
stat_t m, error;
/* Mean */
m = mean(mem, NUM);
/* Error */
error = sd(mem, m, NUM);
*((stat_t*)&data[0]) = m;
*((stat_t*)&data[sizeof(stat_t)]) = error;
*((unsigned char*)&data[5 * sizeof(stat_t)]) = mode;
*((stat_t*)&data[2 * sizeof(stat_t)]) = time_ADC; //ADC meas. time for 128 values. Time until sending calculated shortly before sending
*((stat_t*)&data[4 * sizeof(stat_t)]) = temperature;
*((unsigned char*)&data[5 * sizeof(stat_t) + sizeof(char)]) = 4;
//put raw values into 2 separate words
/*Filling raw data arrays*/
unsigned int k;
for (k = 0; k < RAW_NUM; k++) {
*((short*)&rawdata1[k * sizeof(short)]) = (short)((int)mem[k] - 32768);
*((short*)&rawdata2[k * sizeof(short)]) = (short)((int)mem[k + RAW_NUM] - 32768);
*((short*)&rawdata3[k * sizeof(short)]) = (short)((int)mem[k + 2 * RAW_NUM] - 32768);
*((short*)&rawdata4[k * sizeof(short)]) = (short)((int)mem[k + 3 * RAW_NUM] - 32768);
}
/*Last byte of each data array denotes the number of remaining TXs*/
*((unsigned char*)&rawdata1[RAW_NUM * sizeof(short)]) = 3;
*((unsigned char*)&rawdata2[RAW_NUM * sizeof(short)]) = 2;
*((unsigned char*)&rawdata3[RAW_NUM * sizeof(short)]) = 1;
*((unsigned char*)&rawdata4[RAW_NUM * sizeof(short)]) = 0;
}
WDTCTL = WDT_ARST_1000;
if (!timeout) {
/* Wake XBEE and wait with a timer for its resurrection (after 13.2ms for some reason) */
SLEEP(0);
wait(14);
/* measure time before sending to reconstruct time of measuring events */
TBCTL &= ~(MC_2); //stop counter
Counter_B_value = (unsigned long int)TBR; //write counter value to variable
stat_t time_send = (stat_t)Counter_B_value / (stat_t)32768 * 8.0; // *8 due to CLK divider of 1/8 (set by ID_3)
*((stat_t*)&data[3 * sizeof(stat_t)]) = time_send; //ADC meas. time for 128 values
/* TX request: (mean value | error | mode | time | number of remaining TXs) */
tx_request(data, LENGTH, DEST_ADDR_high, DEST_ADDR_low);
tx_request(rawdata1, sizeof(rawdata1), DEST_ADDR_high, DEST_ADDR_low);
tx_request(rawdata2, sizeof(rawdata2), DEST_ADDR_high, DEST_ADDR_low);
tx_request(rawdata3, sizeof(rawdata3), DEST_ADDR_high, DEST_ADDR_low);
tx_request(rawdata4, sizeof(rawdata4), DEST_ADDR_high, DEST_ADDR_low);
SLEEP(1); //next ADC reset follows at the beginning of the while(true) loop
}
CYCLE_COUNTER++;
}
}